]> git.decadent.org.uk Git - nfs-utils.git/commitdiff
Imported Upstream version 1.2.4 upstream/1.2.4
authorLuk Claes <luk@debian.org>
Sat, 9 Jul 2011 10:20:38 +0000 (12:20 +0200)
committerLuk Claes <luk@debian.org>
Sat, 9 Jul 2011 10:20:38 +0000 (12:20 +0200)
72 files changed:
.gitignore
ChangeLog
aclocal/keyutils.m4 [new file with mode: 0644]
aclocal/libnfsidmap.m4
configure.ac
support/export/client.c
support/export/export.c
support/export/hostname.c
support/export/nfsctl.c
support/include/exportfs.h
support/include/misc.h
support/include/nfslib.h
support/include/rpcmisc.h
support/nfs/Makefile.am
support/nfs/atomicio.c [new file with mode: 0644]
support/nfs/conffile.c
support/nfs/exports.c
support/nfs/nfs_mntent.c
support/nfs/rpcdispatch.c
support/nfs/strlcat.c [new file with mode: 0644]
support/nfs/strlcpy.c [new file with mode: 0644]
support/nfs/svc_create.c
support/nsm/file.c
tests/nsm_client/nsm_client.c
utils/Makefile.am
utils/exportfs/exportfs.c
utils/exportfs/exportfs.man
utils/exportfs/exports.man
utils/gssd/Makefile.am
utils/gssd/gss_util.c
utils/gssd/gssd.man
utils/gssd/gssd_proc.c
utils/gssd/krb5_util.c
utils/gssd/svcgssd.c
utils/gssd/svcgssd.man
utils/gssd/svcgssd_krb5.c [new file with mode: 0644]
utils/gssd/svcgssd_krb5.h [new file with mode: 0644]
utils/gssd/svcgssd_proc.c
utils/idmapd/Makefile.am
utils/idmapd/atomicio.c [deleted file]
utils/idmapd/idmapd.c
utils/idmapd/strlcat.c [deleted file]
utils/idmapd/strlcpy.c [deleted file]
utils/mount/Makefile.am
utils/mount/fstab.c
utils/mount/mount.c
utils/mount/mount_config.h
utils/mount/mount_constants.h
utils/mount/mount_libmount.c [new file with mode: 0644]
utils/mount/network.c
utils/mount/network.h
utils/mount/nfs.man
utils/mount/nfsumount.c
utils/mount/parse_opt.c
utils/mount/stropts.c
utils/mount/utils.c [new file with mode: 0644]
utils/mount/utils.h [new file with mode: 0644]
utils/mount/version.h
utils/mountd/cache.c
utils/mountd/mountd.c
utils/mountd/mountd.man
utils/mountd/rmtab.c
utils/mountd/v4root.c
utils/nfsd/nfssvc.c
utils/nfsidmap/Makefile.am [new file with mode: 0644]
utils/nfsidmap/nfsidmap.c [new file with mode: 0644]
utils/nfsidmap/nfsidmap.man [new file with mode: 0644]
utils/nfsstat/nfsstat.c
utils/nfsstat/nfsstat.man
utils/statd/hostname.c
utils/statd/sm-notify.c
utils/statd/statd.man

index 4bff9e382a27e1c3855126fbdf430a7fc1290e72..f5b5cf044f2ede7bf0c8972604d372d552a52797 100644 (file)
@@ -64,6 +64,7 @@ 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
index efef742cd22a9f2bdf7ae0e27e42552e52545960..062ed67716545c548b330742c97d3dccaf091c5f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
-commit 3030aded70e616cdeac4223785754b86a33b587d
-Author: Eberhard Kuemmerle <e.kuemmerle@fz-juelich.de>
-Date:   Mon Sep 27 13:24:48 2010 -0400
+commit 684cf4a5e0e84a1367690d7ecf4882cbdf4f3228
+Author: Prem Karat <prem.karat@linux.vnet.ibm.com>
+Date:   Thu Jun 30 07:29:20 2011 -0400
 
-    Added the -p <principal> flag to the svcgssd manpage
+    mount.nfs: Fix for the bug in v1.2.4 that breaks mount.nfs
     
-    Signed-off-by:  Eberhard Kuemmerle <E.Kuemmerle@fz-juelich.de>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 6cc96cada639a823961d5d8a136cbcdc8b8952b8
-Author: Eberhard Kuemmerle <e.kuemmerle@fz-juelich.de>
-Date:   Mon Sep 27 13:16:23 2010 -0400
-
-    svcgssd: Adding a <-p principal> flag
-    
-    Allow the principal that is used to get the machines creds definable
-    on the command like with the new '-p <principal>'. This is useful
-    in cluster environments.
+    commit 30ebf047 failed to include these changes that breaks mount.nfs.
+    mount.nfs will continue to work fine with these changes
     
-    Signed-off-by:  Eberhard Kuemmerle <E.Kuemmerle@fz-juelich.de>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 837796686ad8f9178c7b6855ada728a53ae511e3
-Author: David Lecorfe <dlecorfec@gmail.com>
-Date:   Mon Sep 27 13:29:31 2010 -0400
+commit 057d2add27d1e05fed3ae7206ee043b6c1fda45a
+Author: NeilBrown <neilb@suse.de>
+Date:   Tue Jun 28 13:24:33 2011 -0400
 
-    nfs-iostat.py: don't wait for an extra interval when given a count
-    
-    If I invoke the tool with an interval of 10 and a count of 2, it will:
-    - show the summary
-    - sleep 10s
-    - show the stats for the last 10s
-    - sleep 10s
-    - exit
+    Do not compile unnecessary files when the libmount code is enable
     
-    Signed-off-by: David Lecorfe <dlecorfec@gmail.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit eaa588a137b0b2f38aa9e9c542635a222e51ee48
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Mon Sep 27 10:16:34 2010 -0400
+commit 30ebf04700654deddbf5f57d95e84ec69cea8610
+Author: Prem Karat <prem.karat@linux.vnet.ibm.com>
+Date:   Tue Jun 28 11:53:40 2011 -0400
 
-    nfsd: Enable IPv6 support in rpc.nfsd again.
+    mount.nfs: Don't hard code source and destination
     
-    Revert commit b2a3cd59 so that rpc.nfsd can create IPv6 listener
-    sockets for the kernel.
+    Currently souce and destination parameters should be passed as first and
+    second paramter while using mount.nfs. This patch allows them to be passed
+    anywhere while mounting.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    Current functionality is
+       mount.nfs source destn -o <options>
+    This patch will allow to do this
+       mount.nfs -o <options> source destn
+               or
+       mount.nfs -o <options> source -o <options> destn
+    
+    Signed-off-by: Prem Karat <prem.karat@linux.vnet.ibm.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit c18e9a780f376b868e62b75abe64b0fd9915ada5
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Mon Sep 27 10:14:34 2010 -0400
+commit b3e190c4adfc9ec47567c968bd000d282d07b05e
+Author: NeilBrown <neilb@suse.de>
+Date:   Tue Jun 28 11:36:31 2011 -0400
 
-    mountd: Update mountd/exportfs man pages to reflect IPv6 changes
+    mount: improve signal management when locking mtab
     
-    Document IPv6 support in rpc.mountd and exportfs, and clarify existing
-    language in the man page.
+    As mount.nfs can run setuid it must be careful about how the user can
+    interact with in.  In particular it needs to ensure it does not
+    respond badly to any signals that the user might be able to generate.
     
-    Clean up: Use bold consistently for program names, and italics
-    consistently for file names.  Use "rpc.mountd" consistently as the
-    name of the mountd daemon.
+    This is particularly an issue while updating /etc/mtab (when that is
+    not linked to /proc/mounts).  If the user can generate a signal which
+    kills mount.nfs while /etc/mtab is locked, then it will leave the file
+    locked, and could possibly corrupt mtab (particularly if 'ulimit 1'
+    was previously issued).
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 7e454e03131f56872639fe7b62b726479b22c087
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Mon Sep 27 10:13:39 2010 -0400
-
-    mountd: Use MNT status values instead of NFSERR
+    Currently lock_mtab does set some handlers for signals, but not
+    enough.  It arranges for every signal up to (but not including)
+    SIGCHLD to cause mount.nfs to unlock mdadm promptly exit ... even if
+    the default behaviour would be to ignore the signal.  SIGALRM is
+    handled specially, and signals after SIGCHLD are left with their
+    default behaviour.  This includes for example SIGXFSZ which can be
+    generated by the user running "ulimit 1".
     
-    Clean up:  The MNT protocol has its own enum type defining error
-    status values.  While the values can be the same as the NFSERR enum
-    type on some systems, it's not guaranteed to be true everywhere.
+    So: change this so that some signals are left unchanged, SIGALRM is
+    handled as required, and all signals that the user can generate are
+    explicitly ignored.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    The remainder still cause mount.nfs to print a message, unlock mtab, and
+    exit.
+    
+    Signed-off-by: NeilBrown <neilb@suse.de>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit ef32b76ae37926faacaf4b8121eba638567c4692
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Mon Sep 27 10:11:18 2010 -0400
+commit a99b7846e2abec5e26ab6b764b921d79559e0a0f
+Author: J. Bruce Fields <bfields@redhat.com>
+Date:   Mon Jun 27 12:31:07 2011 -0400
 
-    mountd: Fix up version and usage messages
+    mountd: move fsidtype-specific code to helpers
     
-    Clean up: rpc.mountd is no longer known as kmountd.  Use the program's
-    basename rather than the full pathname for the usage message.  Display
-    a version message at start up similar to statd's.
+    Now we can move these big switch statements into helper functions.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: J. Bruce Fields <bfields@redhat.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 2c15cf2963367dee7106964c38ab7b1e30ba347d
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Mon Sep 27 10:09:49 2010 -0400
+commit e6559fd0b7b63f5d152d33d598dc74d78df30ecb
+Author: J. Bruce Fields <bfields@redhat.com>
+Date:   Mon Jun 27 12:30:36 2011 -0400
 
-    mountd: Unregister mountd if my_svc_run() returns
+    mountd: gather fsid information into one struct
     
-    Fix a long standing bug: when my_svc_run() returns, mountd should
-    unregister itself with the local rpcbind so that it can subsequently
-    start cleanly.
+    A large part of nfsd_fh() is concerned with extracting
+    fsid-type-specific information from the fsid, then matching that
+    information with information from the export list and the filesystem.
     
-    Log a more helpful error message in this case.
+    Moving all that information into one struct will allow some further
+    simplifications.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: J. Bruce Fields <bfields@redhat.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit b551b1fd0052de9b8c674b30c39d9f2a1e9d79cc
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Mon Sep 27 10:09:10 2010 -0400
+commit 13a0a61d037f2cc09e7997a96ce5822b9317883b
+Author: J. Bruce Fields <bfields@redhat.com>
+Date:   Mon Jun 27 12:29:51 2011 -0400
 
-    mountd: Support TI-RPC mountd listener
+    mountd: prefer explicit subexports over crossmnt parents
     
-    If TI-RPC is available, use it to create mountd's svc listener.  If
-    not, use the old function, rpc_init(), to create mountd's listener.
+    If a parent is exported with crossmnt, and if a child is also explicitly
+    exported, then both exports could potentially produce matches in this
+    loop; that isn't a bug.
     
-    IPv6 can be supported if TI-RPC is available.  In this case,
-    /etc/netconfig is searched to determine which transports to advertise.
+    Instead of warning and ignoring the second match we find, we should
+    instead prefer whichever export is deeper in the tree, so that
+    children's options can override those of their parents.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    Reported-by: Olga Kornievskaia <aglo@citi.umich.edu>
+    Signed-off-by: J. Bruce Fields <bfields@redhat.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit c5571da8e92f87fc9ec6e8aa8075c69497361c87
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Mon Sep 27 10:06:35 2010 -0400
+commit f8d26c1db9a260597828685c7f62e1b29e78285f
+Author: Jeff Layton <jlayton@redhat.com>
+Date:   Wed Jun 22 15:52:55 2011 -0400
 
-    mountd: Make NFS version checks more strict
-    
-    Ensure users and programmers specify NFS version numbers correctly.
-    This also makes the next patch more clean.
+    manpage: add section on character class matches to exports(5)
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: Jeff Layton <jlayton@redhat.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 05f93b531d59df6e976d9b40c97b51546524040a
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Mon Sep 27 09:50:11 2010 -0400
+commit cb6676aea5bcfcbeaf868e53177eff51f4efe9a8
+Author: James Pearson <james-p@moving-picture.com>
+Date:   Wed Jun 22 15:51:47 2011 -0400
 
-    nfs-utils: Fix source code character encoding
-    
-    Minor clean up.
-    
-    Most modern Linux distributions set UTF-8 locales.  Standardize the
-    character encoding of source files on UTF-8, to squelch vim com-
-    plaints.
+    nfs-utils: remove possibly false statement from exports.man
     
-    I probably missed a few spots.
-    
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 5341111d4b34bcd1b1263d5ed215cbe375aa9314
-Author: Steve Dickson <steved@redhat.com>
-Date:   Mon Sep 27 09:35:26 2010 -0400
-
-    libnfs.a: Remove support/nfs/fstab.c
+    A very minor change suggested by J. Bruce Fields <bfields@fieldses.org>
+    to remove the statement that exporting to a single host or IP address is
+    the "most common format" - as it probably isn't.
     
+    Signed-off-by: James Pearson <james-p@moving-picture.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 72ae199db4be7bf0092e15adaa8a43ce2434bf9f
+commit 7d71ff8e3825a7f8c2d5c9b5b9344e95e7aa1392
 Author: Jeff Layton <jlayton@redhat.com>
-Date:   Thu Sep 16 14:34:39 2010 -0400
+Date:   Wed Jun 22 15:51:02 2011 -0400
 
-    rpc.nfsd: mount up nfsdfs is it doesn't appear to be mounted yet
+    manpage: add info about IPv6 configuration to exports(5)
     
-    There's a bit of a chicken and egg problem when nfsd is run the first
-    time. On Fedora/RHEL at least, /proc/fs/nfsd is mounted up whenever nfsd
-    is plugged in via a modprobe.conf "install" directive.
-    
-    If someone runs rpc.nfsd without plugging in nfsd.ko first,
-    /proc/fs/nfsd won't be mounted and rpc.nfsd will end up using the legacy
-    nfsctl interface. After that, nfsd will be plugged in and subsequent
-    rpc.nfsd invocations will use that instead.
-    
-    This is a problem as some nfsd command-line options are ignored when the
-    legacy interface is used. It'll also be a problem for people who want
-    IPv6 enabled servers. The upshot is that we really don't want to use the
-    legacy interface unless there is no other option.
-    
-    To avoid this situation, have rpc.nfsd check to see if the "threads"
-    file is already present. If it's not, then make an attempt to mount
-    /proc/fs/nfsd.  This is a "best-effort" sort of thing, however so we
-    just ignore the return code from the mount attempt and fall back to
-    using nfsctl() if it fails.
+    The parts of the exports(5) manpage that discuss IP addressing neglect
+    IPv6 configuration. Update to include info on how to export to IPv6
+    subnets and addresses, and add a line demonstrating that to the EXAMPLE
+    section.
     
     Signed-off-by: Jeff Layton <jlayton@redhat.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 63afb96b9d36e72782ad25ca496896029a9d9061
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Sep 16 14:25:52 2010 -0400
+commit 545ea1098089d6396d5a70111ec231c4de967faa
+Author: Benny Halevy <benny@tonian.com>
+Date:   Wed Jun 22 15:44:17 2011 -0400
 
-    libexport.a: Enable IPv6 support in hostname.c
+    nfsstat: reorder nfs4 stats for 2.6.39
     
-    If --enable-ipv6 is specified when building nfs-utils, libexport's
-    host_foo() helpers can now return both IPv4 and IPv6 addresses.
-    
-    This means IPv6 presentation addresses and IPv6 DNS resolution
-    results are handled properly in the mountd cache and /etc/exports,
-    but does not yet enable IPv6 mountd listeners.
-    
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: Benny Halevy <benny@tonian.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit d901e329e380a2adc22783b1b241e414aa24cf51
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Sep 16 14:21:48 2010 -0400
+commit c7ce7a4674ad446bee4dd3baf90155ce6b216816
+Author: Mi Jinlong <mijinlong@cn.fujitsu.com>
+Date:   Wed Jun 22 15:41:27 2011 -0400
 
-    mountd: Ensure cache downcall can handle IPv6 addresses
+    libexport.a: fix using bad index for loop at cltsetup()
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    In cltsetup(), when checking the address, use clp's naddr for index,
+    instead of  cltarg's naddr, which it's always zero there.
+    
+    Signed-off-by: Mi Jinlong <mijinlong@cn.fujitsu.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 1ba28ec59f39de0bc4953b42556d847efbb508eb
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Sep 16 14:21:08 2010 -0400
+commit b50ad13298b3e9519a9bdecb8c146c9ecf39cef8
+Author: Jeff Layton <jlayton@redhat.com>
+Date:   Wed Jun 22 14:51:38 2011 -0400
 
-    mountd: Handle IPv6 addresses in kernel auth_unix_ip upcalls
+    nfs: fix host_reliable_addrinfo
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit ffe8c9a084fec4fdd3acfcf4b36fbe434d297b82
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Sep 16 14:19:19 2010 -0400
-
-    mountd: clean up cache API
-    
-    Clean up: Squelch compiler warnings and document public parts of
-    cache API.
-    
-    cache.c: At top level:
-    cache.c:67: warning: no previous prototype for auth_unix_ip
-    cache.c:123: warning: no previous prototype for auth_unix_gid
-    cache.c:217: warning: no previous prototype for get_uuid
-    cache.c:247: warning: no previous prototype for uuid_by_path
-    cache.c:326: warning: no previous prototype for nfsd_fh
-    cache.c:745: warning: no previous prototype for nfsd_export
-    cache.c:820: warning: no previous prototype for cache_open
-    cache.c:832: warning: no previous prototype for cache_set_fd
-    cache.c:841: warning: no previous prototype for
-    cache_process_req
-    cache.c:921: warning: no previous prototype for cache_export
-    cache.c:953: warning: no previous prototype for
-    cache_get_filehandle
+    According to Neil Brown:
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 6f189dae5eb38800c8ae3e2d5c098d11fb44d7d5
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Sep 16 14:17:08 2010 -0400
-
-    exportfs: Enable IPv6 support in matchhostname()
+        The point of the word 'reliable' is to check that the name we get
+        really does belong to the host in question - ie that both the
+        forward and reverse maps agree.
     
-    To gain IPv6 support in matchhostname(), simply replace the socket
-    address comparison helpers with the generic versions that can handle
-    IPv4 and IPv6.
+        But the new code doesn't do that check at all.  Rather it simply
+        maps the address to a name, then discards the address and maps the
+        name back to a list of addresses and uses that list of addresses as
+        "where the request came from" for permission checking.
     
-    host_addrinfo() (called by matchhostname()) returns IPv6 addresses
-    only if IPv6 support is enabled.
+    This bug is exploitable via the following scenario and could allow an
+    attacker access to data that they shouldn't be able to access.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 10a6b17d3588647ab5e1ee81ba40f1ce12a5184d
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Sep 16 13:54:21 2010 -0400
-
-    mountd: Support IPv6 in mountlist_list()
+        Suppose you export a filesystem to some subnet or FQDN and also to a
+        wildcard or netgroup, and I know the details of this (maybe
+        showmount -e tells me) Suppose further that I can get IP packets to
+        your server..
     
-    Replace inet_aton(3) and gethostbyaddr(3) calls in mountlist_list()
-    with calls to the new host_foo() DNS helpers.
+        Then I create a reverse mapping for my ipaddress to a domain that I
+        own, say "black.hat.org", and a forward mapping from that domain to
+        my IP address, and one of your IP addresses.
     
-    The new functions will support IPv6 without additional changes, once
-    IPv6 is enabled in the generic hostname helpers.
+        Then I try to mount your filesystem.  The IP address gets correctly
+        mapped to "black.hat.org" and then mapped to both my IP address and
+        your IP address.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 76209cdbe989ee4cdfbf489f2695ac779457e763
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Sep 16 13:51:51 2010 -0400
-
-    mountd: Handle memory exhaustion in mountlist_list()
+        Then you search through all of your exports and find that one of the
+        addresses: yours - is allowed to access the filesystem.
     
-    I'm about to replace inet_aton(3)/gethostbyaddr(3) with
-    host_pton()/host_canonname() in mountlist_list().
+        So you create an export based on the addrinfo you have which allows
+        my IP address the same access as your IP address.
     
-    Since host_canonname() returns a string allocated with strdup(3)
-    instead of xstrdup(), mountlist_list() must now deal with memory
-    exhaustion properly.
+    Fix this by instead using the forward lookup of the hostname just to
+    verify that the original address is in the list. Then do a numeric
+    lookup using the address and stick the hostname in the ai_canonname.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    Reviewed-by: NeilBrown <neilb@suse.de>
+    Signed-off-by: Jeff Layton <jlayton@redhat.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit a8348c2c48d45f991995707fa22a2fa441aaa907
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Sep 16 13:48:38 2010 -0400
+commit 7235a2164aabfd8dba1f7e1577047bda45053db0
+Author: James Pearson <james-p@moving-picture.com>
+Date:   Tue Jun 7 16:25:13 2011 -0400
 
-    mountd: Add mountlist_freeall()
+    exports: Clearly Defining Exports Priorities
     
-    I'm about to add a second bit of logic that needs to free all
-    mountlist records, so introduce a helper for freeing them.
+    Added some verbiage to the exports(5) man page
+    that clearly explains the precedence around
+    how exports will work with regard to netgroups.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 454aea5dad83ca75f3154ff12ecff39169703e69
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Sep 16 13:46:26 2010 -0400
+commit a36f2437caffb23c68fdc0900544d59198bd52b6
+Author: Neil Brown <neilb@suse.de>
+Date:   Tue Jun 7 13:18:55 2011 -0400
 
-    mountd: support IPv6 in mountlist_del_all()
+    Document "-n" for svcgssd
     
-    Replace IPv4-specific code in the mountlist_del_all() path with code
-    that is address family agnostic.
+    The svcgssd man page doesn't mention the "-n" flag.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: NeilBrown <neilb@suse.de>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 4210d6f0c9cad57907877bf1e5d32ebe4a27bf17
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Sep 16 13:44:02 2010 -0400
+commit 40aed2c3fb5164195a9975ae7f15ebd4b992839d
+Author: Pavel Shilovsky <piastry@etersoft.ru>
+Date:   Tue Jun 7 13:18:13 2011 -0400
 
-    mountd: Support IPv6 in mountd's svc routines
+    mountd: Fix missing varialble assignment in auth_unix_gid
     
-    Replace IPv4-specific code with use of our generic hostname helpers
-    in the routines that handle incoming MNT RPC requests.
-    
-    These functions will support IPv6 without additional changes, once
-    IPv6 is enabled in the generic hostname helpers.
-    
-    As part of this update, I've modified all of mountd's _svc routines
-    to use a debug message format that is consistent with statd.  It may
-    be overkill for some of these; if so we can pull them out later.
+    When we get into auth_unix_gid at the second time, groups_len
+    is not 0 and ngroups variable leave as 0. Then we use ngroups
+    in getgrouplist that fails in this case. This patch fixes it.
     
+    Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit f35762f959cc5f29ad7817f8b7968e3792132651
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Sep 16 13:39:39 2010 -0400
+commit 8935933dedcd820c2fb3dddff8b79fd5841dc217
+Author: Benny Halevy <bhalevy@panasas.com>
+Date:   Mon May 23 08:37:17 2011 -0400
 
-    mountd: add IPv6 support in auth_authenticate()
+    nfsstat: reorder nfs4 stats for 2.6.38 and up
     
-    Make the entire auth_authenticate() code path address-family agnostic.
+    match order in 2.6.38, 2.6.39 (-rc3) and development tree
+    while at it, get rid of obsolete ds_write and ds_commit
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: Benny Halevy <bhalevy@panasas.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 29b8a7700129d9768e3e2d94c81eec9f84ba8691
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Sep 16 09:32:52 2010 -0400
+commit 27dcd8a775024160e741cce53e4a402eaac3501d
+Author: NeilBrown <neilb@suse.de>
+Date:   Mon May 23 08:23:51 2011 -0400
 
-    libnfs.a: Fix API for getfh() & friends
-    
-    This is more of a clean-up than a behavioral change.
-    
-    POSIX requires that a "struct sockaddr" is the same size as a "struct
-    sockaddr_in".  Therefore, a variable or field of type "struct sockaddr"
-    cannot contain an AF_INET6 address.  However, "struct sockaddr *" is
-    often used to reference a generic (ie non-address family specific)
-    socket address, generating some confusion about this.
+    supress socket error when address family is not supported
     
-    The nfsctl_arg struct uses a struct sockaddr (not a pointer) to pass
-    the client's IP address to the kernel.  This means the legacy nfsctl()
-    kernel API can never support IPv6.  Fortunately for us, this legacy
-    interface was replaced by a text-based cache interface a few years
-    back.  We don't need to support non-AF_INET addresses here.
+    From: Suresh Jayaraman <sjayaraman@suse.de>
     
-    The getfh() functions in nfs-utils provide a handy C API for the
-    kernel's nfsctl interface.  The getfh() functions still take a struct
-    sockaddr *, though, and that can imply that a non-IPv4 address can be
-    passed via this API.  To make it abundantly clear that only IPv4
-    addresses can be used with this interface, change the synopses of
-    getfh() and friends to take a struct sockaddr_in * instead of a struct
-    sockaddr * .
+    It was observed that when ipv6 module was not loaded and cannot be auto-loaded,
+    when starting NFS server, the following error occurs:
+       "rpc.nfsd: unable to create inet6 TCP socket: errno 97 (Address
+       family not supported by protocol)"
     
-    This makes these functions conform with other places in mountd and
-    exportfs that already grok the difference between a struct sockaddr
-    and a struct sockaddr_in.
+    This is obviously a true message, but does not represent an "error" when ipv6
+    is not enabled.  Rather, it is an expected condition.  As such, it can be
+    confusing / misleading / distracting to display it in this scenario.
     
-    While we're here...
+    This patch instead of throwing error when a socket call fails with
+    EAFNOSUPPORT, makes it as a NOTICE.
     
-    Introduce some nice documenting comments for the get_fh() functions,
-    and...
-    
-    Since mountd will support IPv6 in the near future, assert that the
-    family of client addresses passed to this API is indeed AF_INET, in
-    order to prevent non-AF_INET addresses from ever being passed to the
-    legacy nfsctl() interface.
-    
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
+    Signed-off-by: Neil Brown <neilb@suse.de>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit a88c279992f4b63e3dcaac9930e300fd4bb03dd7
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Sep 16 07:28:18 2010 -0400
+commit 7a802337bfc92d0b30fe94dbd0fa231990a26161
+Author: NeilBrown <neilb@suse.de>
+Date:   Mon May 23 08:19:57 2011 -0400
 
-    mount.nfs: Don't do anything fancy if this is a remount
-    
-    We don't want to append "vers=4" or perform any negotiation if the
-    "remount" mount option was specified.  It will just end in tears.
+    Remove risk of nfs_addmntent corrupting mtab
     
-    This attempts to address
+    nfs_addmntent is used to append directly to /etc/mtab.
+    If the write partially fail, e.g. due to RLIMIT_FSIZE,
+    truncate back to original size and return an error.
     
-      https://qa.mandriva.com/show_bug.cgi?id=60311
+    See also https://bugzilla.redhat.com/show_bug.cgi?id=697975
+    (CVE-2011-1749) CVE-2011-1749 nfs-utils: mount.nfs fails to anticipate RLIMIT_FSIZE
     
-    and
-    
-      https://bugzilla.linux-nfs.org/show_bug.cgi?id=187
-    
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: NeilBrown <neilb@suse.de>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 6f73daf5a5711dc0620f7d43c61c4fd57c0d3f80
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Sep 16 07:26:07 2010 -0400
+commit 56f537535190d034039570bafd9a0de71b79b8f1
+Author: Ben Myers <bpm@sgi.com>
+Date:   Mon May 23 08:07:00 2011 -0400
 
-    mount.nfs: Refactor mount version and protocol autonegotiation
-    
-    Clean up.
-    
-    I'm beginning to agree with Bruce and Steve's assessment that the
-    fallthrough switch case in nfs_try_mount() is more difficult to read
-    and understand than it needs to be.  The logic that manages
-    negotiating NFS version and protocol settings is getting more complex
-    over time anyway.
-    
-    So let's split the autonegotiation piece out of nfs_try_mount().
+    exportfs: getexportent interprets -test-client- as default options
     
-    We can reduce indenting, and use cleaner switch-based logic.  Also,
-    adding more comments can only help.
+    With commit 1374c3861abdc66f3a1410e26cc85f86760b51dd Neil added a
+    -test-client- export to test the exportability of filesystems when exportfs
+    is run.  When using the old cache controls (i.e. /proc/fs/nfsd is not
+    mounted) exportfs will read /proc/fs/nfs/exports to process existing
+    exports and find these test client entries.  The dash at the beginning of
+    -test-client- will be cause getexportent to look for default options in the
+    rest of the string, which test-client- will not match:
     
-    Neil also suggested replacing the pre-call "errno = 0" trick.  The
-    lower-level functions may try to mount several times (given a list of
-    addresses to try).  errno could be set by any of those.  The mount
-    request will succeed at some point, and "success" is returned, but
-    errno is still set to some non-zero value.
+    exportfs: /proc/fs/nfs/exports:1: unknown keyword "test-client-(rw"
     
-    The kernel version check in nfs_try_mount() is more or less loop
-    invariant: it's impossible for the result of that test to change
-    between retries.  So we should be able to safely move it to the logic
-    that sets the initial value of mi->version.
+    This patch resolves that problem (as Steve suggested) by not processing any
+    default options if we are reading the list of existing exports from the
+    kernel.  Default options are converted to individual exports by exportfs so
+    the kernel won't have any regardless.
     
-    This patch is not supposed to cause a behavioral change.
-    
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: Ben Myers <bpm@sgi.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 64bf8db367fd43e80dd135b460afc157808647fa
-Author: Bian Naimeng <biannm@cn.fujitsu.com>
-Date:   Thu Sep 16 07:12:47 2010 -0400
+commit c8e802c036a3f0fcd4481dae8b3ec09fb71f4118
+Author: Jim Rees <rees@umich.edu>
+Date:   Wed May 18 12:42:02 2011 -0400
 
-    rpc.idmapd: Type of idmap client should be defined by ic_id not ic_clid.
+    Removed compilation warnings from mountd/cache.c
     
-    The type of idmap_client is defined by idmap_client.ic_id for nfs,
-    so nfsd should have the same style.
+    Commit 5604b35a6 introduced a number of missing initializer
+    warnings that were missed. This patch removes those warnings.
     
-    Signed-off-by: Bian Naimeng <biannm@cn.fujitsu.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 7f77ef90ad52eced1552efc2242e063aa4501ddc
-Author: Benny Halevy <bhalevy@panasas.com>
-Date:   Tue Jul 20 08:40:34 2010 +0300
-
-    nfsstat: add release_lockowner to client stats
-    
-    Signed-off-by: Benny Halevy <bhalevy@panasas.com>
-
-commit bf6da0a22d971364dae25ec2f62c01fbd2960f07
+commit 68f7938c85258a8c54b13169dcdeae61cc1bf286
 Author: Steve Dickson <steved@redhat.com>
-Date:   Thu Sep 9 10:47:32 2010 -0400
+Date:   Tue Apr 26 13:32:35 2011 -0400
 
-    Cleaned up a warning from commit 44f09b7
+    nfsstat: Output headings mislabled
+    
+    The badclnt and badauth headers were reversed
+    when the server side rpc stats (-s -o rpc) were
+    displayed.
     
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 911630538580cdaaee1c37cdf1a8b35b8ed6b23f
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Wed Sep 8 13:28:24 2010 -0400
+commit 2e4a7e9b50a641dc8640a5dd911ee4a2f0b2c073
+Author: Steve Dickson <steved@redhat.com>
+Date:   Tue Apr 19 12:31:30 2011 -0400
 
-    mount.nfs: Prepare way for "vers=4,rdma" mounts
+    rpc.svcgssd: Segmentation fault on error
     
-    At some point, when the kernel starts to support "vers=4,rdma" mounts,
-    we will want the mount.nfs command to pass "vers=4,rdma" mounts
-    instead of rejecting them.
+    Commit 544ed73d introduced a regression that caused
+    rpc.svcgssd to seg fault on "Wrong principal in request"
+    errors in gss_accept_sec_context()
     
-    Assuming that the kernel will reject these today with EPROTONOSUPPORT,
-    that would cause the version fallback logic to go to "vers=3,rdma"
-    automatically.  So the extra check we have now is not needed anyway.
-    
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit f99d1b8e8768ab96b51bed52f21a626ac9a4797f
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Wed Sep 8 13:27:31 2010 -0400
+commit 5604b35a61e22930873ffc4e9971002f578e7978
+Author: Sean Finney <sean.finney@sonyericsson.com>
+Date:   Tue Apr 19 11:04:35 2011 -0400
 
-    mount.nfs: Support an "rdma" mount option
+    nfs-utils: Increase the stdio file buffer size for procfs files
     
-    The kernel NFS client's mount option parser recognizes a stand-alone
-    "rdma" mount option, similar to the legacy "udp" and "tcp" options.
+    Previously, when writing to /proc/net/rpc/*/channel, if a cache line
+    were larger than the default buffer size (likely 1024 bytes), mountd
+    and svcgssd would split writes into a number of buffer-sized writes.
+    Each of these writes would get an EINVAL error back from the kernel
+    procfs handle (it expects line-oriented input and does not account for
+    multiple/split writes), and no cache update would occur.
     
-    The mount.nfs command text-based mount option parser used to pass
-    "rdma" straight to the kernel, but since we've started handling MNT in
-    the kernel instead of in user space, "rdma" on the command line has
-    not worked.
+    When such behavior occurs, NFS clients depending on mountd to finish
+    the cache operation would block/hang, or receive EPERM, depending on
+    the context of the operation.  This is likely to happen if a user is a
+    member of a large (~100-200) number of groups.
     
-    Until now, no-one has noticed, especially since an "rdma" mount option
-    isn't documented in nfs(5).
+    Instead, every fopen() on the procfs files in question is followed by
+    a call to setvbuf(), using a per-file dedicated buffer of
+    RPC_CHAN_BUF_SIZE length.
     
-    Support "rdma" in mount.nfs command, and document it in nfs(5).
+    Really, mountd should not be using stdio-style buffered file operations
+    on files in /proc to begin with.  A better solution would be to use
+    internally managed buffers and calls to write() instead of these stdio
+    calls, but that would be a more extensive change; so this is proposed
+    as a quick and not-so-dirty fix in the meantime.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: Sean Finney <sean.finney@sonyericsson.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 44f09b7c4c79ca184a29138078c68a4db7aeb85a
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Wed Sep 8 13:26:34 2010 -0400
+commit 9274e94db85bac04e170414cb8e0f4be271cde90
+Author: Sean Finney <sean.finney@sonyericsson.com>
+Date:   Tue Apr 19 11:05:47 2011 -0400
 
-    mount.nfs: Use nfs_nfs_protocol() for checking for proto=rdma
+    mountd: Use a dynamic buffer for storing lists of gid's
     
-    Clean up: Now that nfs_get_proto() can recognize "rdma" we can re-use
-    nfs_nfs_protocol() instead of ad hoc checks for "proto=rdma".
+    Previously, in auth_unix_gid, group lists were stored in an array of
+    hard-coded length 100, and in the situation that the group lists for a
+    particular call were too large, the array was swapped with a dynamically
+    allocated/freed buffer.  For environments where users are commonly in
+    a large number of groups, this isn't an ideal approach.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit a77ca5c6a79486dc8c5a4c327fe5310f5d497766
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Wed Sep 8 13:25:56 2010 -0400
-
-    getport: Recognize "rdma" and "rdma6" netid
+    Instead, use malloc/realloc to grow the list on an as-needed basis.
     
-    The mount.nfs command must recognize the values of "rdma" and "rdma6"
-    with the "proto=" mount option.  Typically the mount.nfs command
-    relies on libtirpc or getprotobyname(3) to recognize netids and
-    translate them to protocol numbers.
-    
-    RFCs 5665 and 5666 define the "rdma" and "rdma6" netids.  IANA defines
-    a specific port number for NFS over RDMA (20049), but has not provided
-    a protocol name and number for RDMA transports, and is not expected
-    to.  The best we can do is translate these by hand, as needed, to get
-    RDMA mount requests to the kernel without erroring out.
-    
-    Only the forward translation is needed until such time that "rdma" and
-    "rdma6" start to appear in rpcbind registries.  For now, the version
-    and transport negotiation logic is skipped, avoiding rpcbind queries
-    for RDMA mounts.
-    
-    Note: As of kernel 2.6.36, the kernel's NFS over RDMA transport
-    capability does not support IPv6.
-    
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: Sean Finney <sean.finney@sonyericsson.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 57f36cd692c56b3b62705b5fafef4c25561a39ff
-Author: Guillaume Rousse <Guillaume.Rousse@inria.fr>
-Date:   Thu Sep 9 10:33:47 2010 -0400
+commit a99269230a0e77e7bed4fa31c9547f0d61c7f206
+Author: Karel Zak <kzak@redhat.com>
+Date:   Wed Apr 6 12:39:21 2011 -0400
 
-    Clarification about options supported by different versions
+    mount: add --enable-libmount-mount
     
-    Signed-off-by: Guillaume Rousse <Guillaume.Rousse@inria.fr>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit b7df3370555877598d9f2ef49fae2ad4458e9f72
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Sep 9 10:27:17 2010 -0400
-
-    libexport.a: Refactor init_netmask()
+    This patch allows to link mount.nfs with libmount from util-linux >=
+    v2.19. The new libmount based code is enabled by CONFIG_LIBMOUNT and
+    is stored in mount_libmount.c. The old code is not affected by this
+    change.
     
-    Instead of a single function that can handle both AF_INET and AF_INET6
-    addresses, two separate functions might be cleaner.
+    The libmount does not have officially stable API yet, so the
+    --enable-libmount-mount is marked as experimental in the configure
+    help output.
     
-    The original plan was to keep code redundancy at a minimum, but the
-    resulting code was cumbersome at best.  I think I've traded a little
-    extra code for something that will be much easier to read, understand,
-    and maintain.
+    The ./configure option is the same as we use in util-linux to enable
+    support for libmount in mount(8).
     
-    I've also eliminated the "#if / #endif" instances inside the functions.
+    The addr= (and some other options necessary for remount/umount) are
+    stored to /etc/mtab or to /dev/.mount/utab. The utab file is *private*
+    libmount file. It's possible that some mount options (for example
+    user=) will be moved to kernel, so the utab will not be necessary.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 60abb9889cea52022adf9c8bb946e9d19d79f9ed
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Tue Aug 31 15:31:57 2010 -0400
-
-    libexport.a: IPv6 support in client_check()
+    About libmount:
     
-    Introduce support for IPv6 in client_check()'s helpers.  The local
-    addrs_match() twins are no longer needed since we can use
-    nfs_compare_addrs() now.
+      * supports systems without and with regular /etc/mtab
+      * does not store VFS and FS mount options in userspace
+      * manages user= option and evaluate permissions
+      * parses VFS mount options and generate MS_* flags
+      * parses /etc/{fstab,mtab}, /proc/mounts or /proc/self/mountinfo
+      * long-term goal is to use the same code in all mount.<type> helpers
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 965b15b855c0c621462256b0ab687fc32644255a
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Tue Aug 31 15:30:14 2010 -0400
-
-    libexport.a: IPv6 support for client_init_subnet()
+    Note, use
     
-    To parse and store an IPv6 host or subnet address, init_netmask()
-    needs to handle 128 bit subnet masks.
+       LIBMOUNT_DEBUG=0xffff mount.nfs foo:/path /path
     
-    Unfortunately what once was a pretty simple little function has grown
-    much larger.  This logic must now not only parse IPv6 addresses
-    correctly, but must also distinguish between IPv4 and IPv6.
+    to debug the library.
     
-    To avoid code duplication, I'm "bending" the cardinal rule of not
-    using "#ifdef" inside functions.
+    On systems with util-linux v2.19 the findmnt(8) command uses libmount
+    to list all/selected mount points:
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 2824097496f6b154befbf3b3d15dacf237b07f83
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Tue Aug 31 15:29:02 2010 -0400
-
-    libexport.a: Prepare init_subnetwork() for IPv6 support
-    
-    Retire the slash32 logic in inet_netmask() in favor of a more generic
-    netmask parser that can support IPv6 addresses.
+       $ findmnt /path
+       $ findmnt --mtab /path
     
-    If an invalid IP address string is given to inet_addr(3), it returns
-    INADDR_NONE, which is actually a "valid" address (255.255.255.255).
-    We're none the wiser to the substitution until something breaks later.
+    the --mtab appends userspace mount options (e.g. user=) to the output.
     
-    This patch provides better sanity checking of the parsed address, now
-    that such an error can be reported to client_init()'s callers.
-    We can also check the prefixlen value a little more carefully as well.
-    
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    CC: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: Karel Zak <kzak@redhat.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 03fc34b23c2bff48f54c2d889d7851a31fb64a3d
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Tue Aug 31 15:27:19 2010 -0400
+commit c01e5ca6179b8f5b041605d9bbd75a0f76812d54
+Author: Karel Zak <kzak@redhat.com>
+Date:   Wed Apr 6 11:36:40 2011 -0400
 
-    libexport.a: Use host helper to parse address in client_init()
+    mount: move generic functions to utils.c and network.c
     
-    Take the first step towards making it possible to parse either IPv4 or
-    IPv6 addresses in client_init().  It won't handle IPv6 until
-    host_pton() has IPv6 support enabled, and it still doesn't deal with
-    IPv6 netmasks yet.
+    Move generic code that could be shared between standard mount.nfs and
+    libmount version to utils.c and network.c.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    CC: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: Karel Zak <kzak@redhat.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 502edf1df5e727cf88b19b634f60392652f35ddc
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Tue Aug 31 15:25:35 2010 -0400
+commit d6c1b35c6b40243bfd6fba2591c9f8f2653078c0
+Author: Kevin Coffman <kwc@citi.umich.edu>
+Date:   Wed Apr 6 11:25:03 2011 -0400
 
-    libexport.a: Prepare to recognize IPv6 addresses in        client_gettype()
+    nfs-utils: Add support to svcgssd to limit the negotiated enctypes
     
-    The current open-coded parsing logic in client_gettype() will be hard
-    to modify to recognize IPv6 addresses.  Use a more generic mechanism
-    for detecting IP presentation addresses.
+    Recent versions of Kerberos libraries negotiate and use
+    an "acceptor subkey".  This negotiation does not consider
+    that a service may have limited the encryption keys in its
+    keytab.  A patch (http://src.mit.edu/fisheye/changelog/krb5/?cs=24603)
+    has been added to the MIT Kerberos code to allow an application
+    to indicate that it wants to limit the encryption types negotiated.
+    (This functionality has been available on the client/initiator
+    side for a while.  The new patch adds this support to the
+    server/acceptor side.)
     
-    IPv6 will be enabled automatically in client_gettype() when host_pton()
-    is changed to support IPv6 addresses.
+    This patch adds support to read a recently added nfsd
+    proc file to determine the encryption types supported by
+    the kernel and calls the function to limit encryption
+    types negotiated for the acceptor subkey.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 26fd34002585e6a5aa09204b0b01d836fa83dcf3
+commit 73840ef610accf4cf667427bc64805377c0d8394
 Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Tue Aug 24 07:19:34 2010 -0400
+Date:   Wed Apr 6 10:53:57 2011 -0400
 
-    exportfs: Use xlog() for error reporting
-    
-    exportfs already invokes xlog_open() because libexport.a uses xlog()
-    exclusively for error reporting and debugging messages.  If we can
-    use xlog() throughout exportfs itself, that enables xlog debugging
-    messages everywhere in the code path.
+    exports: add a configurable time-to-live for the kernel    cache entries
     
-    In addition, use xlog() instead of fprintf(stderr) for reporting
-    errors in exportfs.c, to be consistent with libexport.a and other
-    components of nfs-utils.
+    From: Trond Myklebust <Trond.Myklebust@netapp.com>
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 6d7babe6afae068e8a1054f785785d374788f5ee
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Tue Aug 24 07:18:04 2010 -0400
-
-    exportfs: exportfs.c no longer needs #include "xmalloc.h"
+    The fedfs ldap server will specify a ttl for its entries.
     
-    Clean up:  No calls to xmalloc() or xstrdup() here.  No need for the
-    double #include of xmalloc.h.
-    
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit e22f5a9c8e53a2373e8a939771e964ad315cdc5f
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Tue Aug 24 07:16:10 2010 -0400
-
-    statd: statd fails to monitor if no reverse mapping of mon_name exists
+    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
     
-    Commit 8ce130c4 switched in the new statd_canonical_name() function
-    that constructs a "unique" name statd can use to uniquely identify a
-    monitor record.
+    This is a refactoring change only.  There should be no change in
+    behavior.
     
-    The legacy statd would monitor a client that sent an IP address with
-    no reverse map as its caller_name.  To remain bug-for-bug compatible,
-    allow this case in the new statd.
+    Original patch had updates to utils/mountd/junctions.c, which no
+    longer exists.  These are not included here.
     
-    This shouldn't be a problem: statd_canonical_name() needs to create
-    a unique name for the monitored host so it can keep track of monitor
-    requests from the same remote.  The IP address itself should work as
-    well as the host's canonical name, in case there is no reverse
-    mapping.
+    Create a macro for the default cache TTL, which is used in several
+    places besides the export cache.
     
-    We still enforce the requirement that a mon_name that is a DNS name
-    must have a forward map to an IP address.
+    Make e_ttl unsigned.
     
     Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 1bb84a09ff58d1314826945db2f3f1f63015e263
+commit 38e4c685410885a6d464ddd44eff4fd5e7f8459f
 Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Tue Aug 24 07:13:54 2010 -0400
+Date:   Wed Apr 6 10:49:52 2011 -0400
 
-    libexport: Fix IP address check in check_netgroup()
+    statd: Remove vestigial "-w" option from man page synopsis
     
-    Neil Brown reports that recent changes to replace
-    gethostby{addr,name}(3) with get{addr,info}name(3) may have
-    inadvertently broken netgroup support.
+    The synopsis of rpc.statd in its man page lists "-w" as a valid
+    option.  There is currently no support in the source code for a "-w"
+    option.
     
-    There used to be a gethostbyaddr(3) call in the third paragraph in
-    check_netgroup().  The reason for that gethostbyaddr(3) call was that
-    the first innetgr(3) call has already confirmed that hname is not a
-    member of the netgroup.  We also need to confirm that, if hname
-    happens to be an IP address, the hostname bound to that IP address is
-    not a member of the netgroup, either.
+    BugLink: https://bugzilla.linux-nfs.org/show_bug.cgi?id=199
     
-    Fix this by restoring appropriate address to hostname mapping of hname
-    before retrying the innetgr(3) call.
-    
-    See http://marc.info/?l=linux-nfs&m=128084830214653&w=2 .
-    
-    Introduced by commit 0509d3428f523776ddd9d6e9fa318587d3ec7d84.
-    
-    Reviewed-by: Neil Brown <neilb@suse.de>
     Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit abdc32b6af6f38a741a481aeefb5623916152498
+commit b57cd77c13831051ad974ae027d96cd88a8d0c59
 Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Tue Aug 24 07:06:14 2010 -0400
+Date:   Wed Apr 6 10:48:38 2011 -0400
 
-    bexport: Add a common exit label to check_netgroup()
+    mount.nfs: Don't leak socket in nfs_ca_sockname()
     
-    check_netgroup() is going to be changed to free dynamically
-    allocated resources before it returns, so a common
-    exit point is needed.
+    Ensure the test socket is always closed before nfs_ca_sockname()
+    returns.  Otherwise it's orphaned.
     
-    Reviewed-by: Neil Brown <neilb@suse.de>
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 396aac50f5addea2f4d62c25600ca68788a56d97
-Author: Guillaume Rousse <Guillaume.Rousse@inria.fr>
-Date:   Tue Aug 17 17:47:38 2010 -0400
-
-    Fix the description of nfsversion mount option in the man nfs page
+    BugLink: https://bugzilla.linux-nfs.org/show_bug.cgi?id=197
     
+    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit e2003650c68cf47806fb24f7d88fae5524b70aab
+commit 502eef09d8050ffb87d394397c2780e1ef042d68
 Author: Steve Dickson <steved@redhat.com>
-Date:   Mon Jul 19 12:12:52 2010 -0400
+Date:   Wed Apr 6 10:46:06 2011 -0400
 
-    Remove warnings from nfsctl.c
+    Removed a warning from v4root.c
     
-    nfsctl.c: In function 'expsetup':
-    nfsctl.c:112: warning: signed and unsigned type in conditional expression
+    v4root.c:176:9: warning: variable 'ret' set but not used
     
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 1e472b3476cc6d7b95573b7d630d0fc51bebadf3
-Author: Steve Dickson <steved@redhat.com>
-Date:   Wed Aug 4 10:48:17 2010 -0400
-
-    Removed warnings from mountd.c
-    
-    mountd.c: In function 'mount_null_1_svc':
-    mountd.c:195: warning: unused parameter 'rqstp'
-    mountd.c:195: warning: unused parameter 'argp'
-    mountd.c:195: warning: unused parameter 'resp'
-    mountd.c: In function 'mount_dump_1_svc':
-    mountd.c:213: warning: unused parameter 'argp'
-    mountd.c: In function 'mount_umnt_1_svc':
-    mountd.c:224: warning: unused parameter 'resp'
-    mountd.c: In function 'mount_umntall_1_svc':
-    mountd.c:248: warning: unused parameter 'argp'
-    mountd.c:248: warning: unused parameter 'resp'
-    mountd.c: In function 'mount_export_1_svc':
-    mountd.c:258: warning: unused parameter 'argp'
-    mountd.c: In function 'mount_exportall_1_svc':
-    mountd.c:269: warning: unused parameter 'argp'
-    mountd.c: In function 'mount_dump_1_svc':
-    mountd.c:216: warning: unused parameter 'argp'
-    mountd.c: In function 'mount_umnt_1_svc':
-    mountd.c:227: warning: unused parameter 'resp'
-    mountd.c: In function 'mount_umntall_1_svc':
-    mountd.c:251: warning: unused parameter 'argp'
-    mountd.c:251: warning: unused parameter 'resp'
-    mountd.c: In function 'mount_export_1_svc':
-    mountd.c:261: warning: unused parameter 'argp'
-    mountd.c: In function 'mount_exportall_1_svc':
-    mountd.c:272: warning: unused parameter 'argp'
-    
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 14e6ec262e58e962c2d7e9161ca9c56529de3170
-Author: Steve Dickson <steved@redhat.com>
-Date:   Wed Aug 4 10:41:18 2010 -0400
-
-    Removed warnings from idmapd.c
-    
-    idmapd.c:120: warning: missing initializer
-    idmapd.c:120: warning: (near initialization for 'nfsd_ic[0].ic_event')
-    idmapd.c:121: warning: missing initializer
-    idmapd.c:121: warning: (near initialization for 'nfsd_ic[1].ic_event')
-    idmapd.c: In function 'flush_nfsd_cache':
-    idmapd.c:173: warning: comparison between signed and unsigned integer expressions
-    idmapd.c: In function 'dirscancb':
-    idmapd.c:384: warning: unused parameter 'fd'
-    idmapd.c:384: warning: unused parameter 'which'
-    idmapd.c: In function 'svrreopen':
-    idmapd.c:468: warning: unused parameter 'fd'
-    idmapd.c:468: warning: unused parameter 'which'
-    idmapd.c:468: warning: unused parameter 'data'
-    idmapd.c: In function 'clntscancb':
-    idmapd.c:474: warning: unused parameter 'fd'
-    idmapd.c:474: warning: unused parameter 'which'
-    idmapd.c: In function 'nfsdcb':
-    idmapd.c:488: warning: unused parameter 'fd'
-    idmapd.c: In function 'nfscb':
-    idmapd.c:663: warning: unused parameter 'fd'
-    idmapd.c: In function 'validateascii':
-    idmapd.c:850: warning: comparison between signed and unsigned integer expressions
-    idmapd.c:858: warning: comparison between signed and unsigned integer expressions
-    idmapd.c: In function 'getfield':
-    idmapd.c:916: warning: comparison between signed and unsigned integer expressions
-    
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 2ccfd2d5f390bcac7a44f8887cd3f15df1966e0f
+commit c2fa189a0467c25666f014cf9ff2576a9f54d682
 Author: Steve Dickson <steved@redhat.com>
-Date:   Wed Aug 4 10:29:28 2010 -0400
+Date:   Wed Apr 6 10:39:10 2011 -0400
 
-    Removed warnings from configfile.c
+    Removed a warning from exportfs.c
     
-    configfile.c:195: warning: 'inline' is not at beginning of declaration
-    configfile.c:232: warning: 'inline' is not at beginning of declaration
+    exportfs.c:280:29: warning: 'exp' may be used uninitialized in this function
     
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit bc8fdd5ebcabe57cacd382673ca9e4a79ff7b18e
+commit b98ae9df8c4904289c9390288325058b24caa423
 Author: Steve Dickson <steved@redhat.com>
-Date:   Wed Aug 4 10:26:13 2010 -0400
+Date:   Wed Apr 6 10:36:30 2011 -0400
 
-    Removed warnings from svcgssd_proc.c
+    Removed a warning from conffile.c
     
-    svcgssd_proc.c: In function 'send_response':
-    svcgssd_proc.c:135: warning: unused parameter 'f'
-    svcgssd_proc.c: In function 'handle_nullreq':
-    svcgssd_proc.c:434: warning: comparison of unsigned expression < 0 is always false
+    conffile.c:258:19: warning: 'j' may be used uninitialized in this function
     
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit be5b2ed57b0e0a3da91f4ec785718302d0351199
-Author: Steve Dickson <steved@redhat.com>
-Date:   Wed Aug 4 10:22:13 2010 -0400
+commit 012e1a4bf2a002e8cd4d5be3478bfa20a91cbfed
+Author: Masatake YAMATO <yamato@redhat.com>
+Date:   Mon Mar 7 08:36:19 2011 -0500
 
-    Removed warnings from network.c
+    Update man pages for /etc/exports.d
     
-    network.c: In function 'nfs_verify_family':
-    network.c:1366: warning: unused parameter 'family'
+    Man page updates for /etc/exports.d.
     
+    Signed-off-by: Masatake YAMATO <yamato@redhat.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 6b8d7c05fe738a4c7295754b4be552c703024f58
-Author: Steve Dickson <steved@redhat.com>
-Date:   Tue Jul 20 18:43:46 2010 -0400
+commit c7427b57e2be8ef0d57ad0618d4590c062b130f5
+Author: Masatake YAMATO <yamato@redhat.com>
+Date:   Mon Mar 7 08:18:51 2011 -0500
 
-    Removed warnings from nfs4mount.c
+    Read /etc/exports.d/*.export as extra export files
     
-    nfs4mount.c: In function 'fill_ipv4_sockaddr':
-    nfs4mount.c:149: warning: comparison between signed and unsigned integer expressions
+    This patch adding a capability to read /etc/exports.d/*.exports as
+    extra export files to exportfs.
     
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit cf2fd4869fdb77741bca9e3f713af49b889661b3
-Author: Steve Dickson <steved@redhat.com>
-Date:   Tue Jul 20 18:40:31 2010 -0400
-
-    Removed warnings from nfsmount.c
+    If one wants to add or remove an export entry in a script, currently
+    one may have to use sed or something tool for adding or removing the
+    line for the entry in /etc/exports file.
     
-    nfsmount.c: In function 'nfsmount':
-    nfsmount.c:513: warning: missing initializer
-    nfsmount.c:513: warning: (near initialization for 'mnt_server.saddr')
-    nfsmount.c:514: warning: missing initializer
-    nfsmount.c:514: warning: (near initialization for 'nfs_server.saddr')
+    With the patch, adding and removing an entry from a script is much
+    easier.
+    cat<<EOF... or mv can be used for adding. rm can be used for removing.
     
+    Signed-off-by: Masatake YAMATO <yamato@redhat.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 45a73911fff657942ec67317d000badb8e2c5282
+commit edb9b7f2ab9806afb9af31eabeb505fe454c51df
 Author: Steve Dickson <steved@redhat.com>
-Date:   Tue Jul 20 18:22:32 2010 -0400
+Date:   Sat Mar 5 16:17:01 2011 -0500
 
-    Removed warnings from svcgssd.c
+    Cleaned up a warning in rpcdispatch.c
     
-    svcgssd.c: In function 'sig_hup':
-    svcgssd.c:160: warning: unused parameter 'signal'
+    rpcdispatch.c:40:20: warning: comparison between signed and unsigned
+    integer expressions
     
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit b8ba21cedc6aac3b2847217caf55885bb1a74805
+commit 930323817b61877d61fb8ef57229013daa2e6091
 Author: Steve Dickson <steved@redhat.com>
-Date:   Tue Jul 20 18:13:45 2010 -0400
+Date:   Sat Mar 5 16:13:01 2011 -0500
 
-    Removed warnings from gssd_proc.c
+    mount: Remove MOUNT_CONFIG warnings
     
-    gssd_proc.c: In function 'create_auth_rpc_client':
-    gssd_proc.c:939: warning: comparison between signed and unsigned integer expressions
-    gssd_proc.c:939: warning: comparison between signed and unsigned integer expressions
-    gssd_proc.c: In function 'handle_krb5_upcall':
-    gssd_proc.c:1164: warning: comparison between signed and unsigned integer expressions
-    gssd_proc.c: In function 'handle_spkm3_upcall':
-    gssd_proc.c:1178: warning: comparison between signed and unsigned integer expressions
+    The following changes are needed to remove compile warnings when
+    MOUNT_CONFIG is not defined
     
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit f4321ac3466aa9d4c4e11ba232f1ff9bea561288
-Author: Steve Dickson <steved@redhat.com>
-Date:   Tue Jul 20 18:08:13 2010 -0400
+commit 3ef3dc8f1e87ba7a6eaa3c2a6965aff6c80ba414
+Author: Chuck Lever <chuck.lever@oracle.com>
+Date:   Thu Mar 3 17:26:33 2011 -0500
 
-    Removed warnings from krb5_util.c
+    mount: Recognize zero as a valid value for the port= option
     
-    krb5_util.c: In function 'realm_and_service_match':
-    krb5_util.c:617: warning: unused parameter 'context'
-    krb5_util.c: In function 'limit_krb5_enctypes':
-    krb5_util.c:1275: warning: unused parameter 'uid'
+    While zero is not a valid IP port number, zero does represent a valid
+    value for "port=".  It means "query rpcbind to discover the actual
+    non-zero port number to use".  So the parsing functions that handle
+    "port=" should not flag zero as an invalid value.
     
+    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit f89b109c04a8eab81bfa8b8fcdc7692673e13e49
-Author: Steve Dickson <steved@redhat.com>
-Date:   Tue Jul 20 17:53:47 2010 -0400
+commit b3a4dbfb61dad59829f5191d727267b2ea45937a
+Author: Mi Jinlong <mijinlong@cn.fujitsu.com>
+Date:   Wed Feb 9 11:29:42 2011 -0500
 
-    Removed warnings from gssd_main_loop.c
+    Gssd: modify wrong err message at handle_gssd_upcall
     
-    gssd_main_loop.c: In function 'dir_notify_handler':
-    gssd_main_loop.c:64: warning: unused parameter 'sig'
-    gssd_main_loop.c:64: warning: unused parameter 'si'
-    gssd_main_loop.c:64: warning: unused parameter 'data'
+    Modify wrong err message at handle_gssd_upcall when
+    sscanf encryption types fail.
     
+    Signed-off-by: Mi Jinlong <mijinlong@cn.fujitsu.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit d2c329ba4b7ccdea76bcc857a73206eab68428f8
-Author: Steve Dickson <steved@redhat.com>
-Date:   Tue Jul 20 17:45:17 2010 -0400
+commit 45e4597bd570ed40221f51887cde7d7f096f55e7
+Author: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Date:   Wed Feb 9 11:27:19 2011 -0500
 
-    Removed warnings from gssd.c
+    Support AD style kerberos automatically in rpc.gss
     
-    gssd.c: In function 'sig_hup':
-    gssd.c:78: warning: unused parameter 'signal'
+    An Active Directory KDC will only grant a TGT for UPNs, getting
+    a TGT for SPNs is not possible:
     
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 8a72ac3280ce8f9d0f48383d47dd06c80567bc09
-Author: Steve Dickson <steved@redhat.com>
-Date:   Tue Jul 20 17:19:20 2010 -0400
-
-    Removed warnings from atomicio.c
+    $ kinit -k host/ib5@ADS.ORCORP.CA
+    kinit: Client not found in Kerberos database while getting initial
+    credentials
     
-    atomicio.c: In function 'atomicio':
-    atomicio.c:48: warning: comparison between signed and unsigned integer expressions
+    The correct thing to do for machine credentials is to get a TGT
+    for the computer UPN <HOSTNAME>$@REALM:
+    $ kinit -k IB5\$
+    $ klist
+    12/22/10 11:43:47  12/22/10 21:43:47  krbtgt/ADS.ORCORP.CA@ADS.ORCORP.CA
     
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 14becdb7bc23f075f786325f7e953c2f928fe385
-Author: Steve Dickson <steved@redhat.com>
-Date:   Mon Jul 19 14:54:51 2010 -0400
-
-    Removed warnings from nfsstat.c
+    Samba automatically creates /etc/krb5.keytab entry for the computer UPN,
+    this patch makes gssd_refresh_krb5_machine_credential prefer it above
+    the SPNs if it is present.
     
-    nfsstat.c: In function 'print_callstats':
-    nfsstat.c:797: warning: comparison between signed and unsigned integer
-    expressions
-    nfsstat.c:801: warning: comparison between signed and unsigned integer
-    expressions
-    nfsstat.c:802: warning: comparison between signed and unsigned integer
-    expressions
-    nfsstat.c:805: warning: comparison between signed and unsigned integer
-    expressions
+    The net result is that nfs client works automatically out of the box
+    if samba has been used to setup kerberos via 'net ads join' 'net ads
+    keytab create'
     
-    nfsstat.c: In function 'print_callstats_list':
-    nfsstat.c:821: warning: comparison between signed and unsigned integer
-    expressions
-    nfsstat.c:828: warning: comparison between signed and unsigned integer
-    expressions
+    Tested using Windows Server 2003 R2 as the AD server.
     
-    nfsstat.c: In function 'unpause':
-    nfsstat.c:1111: warning: unused parameter 'sig'
+    Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit b594ee2b2a1b9c0c5823a7af279488f113f91be4
+commit 730f6986f86873513fa021a450eb55ccd0f2fbff
 Author: Steve Dickson <steved@redhat.com>
-Date:   Mon Jul 19 14:48:37 2010 -0400
+Date:   Wed Jan 26 07:49:19 2011 -0500
 
-    Removed warnings from nfssvc.c
+    Fixed segfault in rpc.mountd
     
-    nfssvc.c:184: warning: comparison between signed and unsigned integer expressions
-    nfssvc.c: In function 'nfssvc_setvers':
-    nfssvc.c:254: warning: comparison between signed and unsigned integer expressions
-    nfssvc.c: In function 'nfssvc_threads':
-    nfssvc.c:280: warning: comparison between signed and unsigned integer expressions
+    A unallocated piece of memory, instead of a NULL point, was being
+    used to initialize a ->next point in the mount link list which
+    caused a segfault after a few remote accesses via the showmount
+    command.
     
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 7b331fb9d24a71242a6c0a45a06c49174b552c64
+commit 544ed73d5ab27c1390833d5cf93b9585c151667d
 Author: Steve Dickson <steved@redhat.com>
-Date:   Mon Jul 19 14:43:26 2010 -0400
+Date:   Fri Jan 14 10:12:28 2011 -0500
 
-    Removed warnings from cache.c
+    Improve debugging in svcgssd
     
-    cache.c:812: warning: missing initializer
-    cache.c:812: warning: (near initialization for 'cachelist[0].f')
-    cache.c:813: warning: missing initializer
-    cache.c:813: warning: (near initialization for 'cachelist[1].f')
-    cache.c:814: warning: missing initializer
-    cache.c:814: warning: (near initialization for 'cachelist[2].f')
-    cache.c:815: warning: missing initializer
-    cache.c:815: warning: (near initialization for 'cachelist[3].f')
-    cache.c:816: warning: missing initializer
-    cache.c:816: warning: (near initialization for 'cachelist[4].f')
-    cache.c: In function 'cache_export_ent':
-    cache.c:887: warning: comparison between signed and unsigned integer expressions
-    cache.c:907: warning: comparison between signed and unsigned integer expressions
-    
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 9d5eaa2e939723c47649f0f112b43cc8ff414740
-Author: Steve Dickson <steved@redhat.com>
-Date:   Mon Jul 19 13:07:00 2010 -0400
-
-    Removed warnings from fsloc.c
+    Added in gss_display_error() which translates the GSS error into the
+    actual GSS macro name. Currently only the translation of these errors
+    are logged. Since those translations are buried deep in the kerberos
+    library code, having the actual GSS macro name makes it easier to
+    follow the code.
     
-    fsloc.c: In function 'replicas_lookup':
-    fsloc.c:149: warning: unused parameter 'key'
+    Moved the nfs4_init_name_mapping() call into main() so if debug is
+    enabled the DNS name and realms will be logged during start up.
     
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit e10000740fc4c323dbc8d501d7c0caeae12c19b5
-Author: Steve Dickson <steved@redhat.com>
-Date:   Mon Jul 19 12:39:52 2010 -0400
+commit 57be18b9ab08148a1cc9d5af588119885720be8b
+Author: Mi Jinlong <mijinlong@cn.fujitsu.com>
+Date:   Tue Jan 4 11:16:45 2011 -0500
 
-    Removed warnings from conffile.c
+    libnsm.a: modify return value to false from 0 at nsm_drop_privileges()
     
-    conffile.c: In function 'conf_parse_line':
-    conffile.c:301: warning: comparison between signed and unsigned integer expressions
-    
-    conffile.c: In function 'conf_load_defaults':
-    conffile.c:356: warning: unused parameter 'tr'
+    At nsm_drop_privileges(), for improving readability, unify
+    the return value.
     
+    Signed-off-by: Mi Jinlong <mijinlong@cn.fujitsu.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 8810c9dd5b66a097a235e6eabd399739a44df63e
-Author: Steve Dickson <steved@redhat.com>
-Date:   Mon Jul 19 12:34:14 2010 -0400
+commit 5c498280fd9353ded3ea169841079bdae23418e2
+Author: Chuck Lever <chuck.lever@oracle.com>
+Date:   Mon Dec 13 14:50:45 2010 -0500
 
-    Remove warnings from nfs_mntent.c
+    libnsm.a: sm-notify sometimes ignores monitored hosts
     
-    nfs_mntent.c: In function 'mangle':
-    nfs_mntent.c:36: warning: comparison between signed and unsigned integer expressions
+    Monitored host information is stored in files under /var/lib/nfs.
+    When visiting entries in the monitored hosts directory, libnsm.a
+    examines the value of dirent.d_type to determine if an entry is a
+    regular file.
     
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 1ca569633e14c844e32d8e5e3a1c54be01a8b633
-Author: Steve Dickson <steved@redhat.com>
-Date:   Mon Jul 19 12:31:48 2010 -0400
-
-    emove warnings from cacheio.c
+    According to readdir(3), the d_type field is not supported by all
+    file system types.  My root file system happens to be one where d_type
+    isn't supported.  Typical installations that use an ext-derived root
+    file system are not exposed to this issue, but those who use xfs, for
+    instance, are.
     
-    cacheio.c: In function 'cache_flush':
-    cacheio.c:352: warning: comparison between signed and unsigned integer expressions
+    On such file systems, not only are remote peers not notified of
+    reboots, but the NSM state number is never incremented.  A statd warm
+    restart would not re-monitor any hosts that were monitored before
+    the restart.
     
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 0cdfd35cecc17eb1927f15d33205e43ec66675f2
-Author: Steve Dickson <steved@redhat.com>
-Date:   Mon Jul 19 12:28:09 2010 -0400
-
-    Remove warnings from svc_socket.c
-    
-    svc_socket.c: In function 'svcudp_socket':
-    svc_socket.c:160: warning: unused parameter 'reuse'
+    When writing support/nsm/file.c, I copied the use of d_type from the
+    original statd code, so this has likely been an issue for some time.
     
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 9c99b4633b185452614eb6c5630a30b30626a838
-Author: Steve Dickson <steved@redhat.com>
-Date:   Mon Jul 19 12:17:24 2010 -0400
-
-    Removed warnings from rpcdispatch.c
+    Replace the use of d_type in support/nsm/file.c with a call to
+    lstat(2).  It's extra code, but is guaranteed to work on all file
+    system types.
     
-    rpcdispatch.c: In function 'rpc_dispatch':
-    rpcdispatch.c:30: warning: comparison between signed and unsigned
-         integer expressions
-    rpcdispatch.c:35: warning: comparison between signed and unsigned
-         integer expressions
+    Note there is a usage of d_type in gssd.  I'll let gssd and rpcpipefs
+    experts decide whether that's worth changing.
     
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit b6e0ddd7bb3843bb8bb5ff56816b31bcf17adacd
-Author: Steve Dickson <steved@redhat.com>
-Date:   Mon Jul 19 12:05:51 2010 -0400
-
-    Enable extra compile warnings (-Wextra) by default.
+    Fix for:
     
-    Added -Wextra to the CFLAGS which enables more checking
-    during compilation, which in turn, will hopefully flag
-    potential problems before they occur.
+      https://bugzilla.linux-nfs.org/show_bug.cgi?id=193
     
+    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 12af21aca517dfbaec465447d8336bcc4769f71d
-Author: Doug Nazar <nazard.michi@gmail.com>
-Date:   Mon Jul 19 11:08:46 2010 -0400
+commit 089df7c754d9ebab0a7b804f396626ac95fee2e6
+Author: Chuck Lever <chuck.lever@oracle.com>
+Date:   Mon Dec 13 14:47:42 2010 -0500
 
-    gssd: picking wrong creds
+    libnsm.a: Replace __attribute_noinline__
     
-    When not using machine credentials for root, if the machine
-    credential cache file is newer than the root credential file
-    the wrong file will get picked. Ignore the machine file in
-    this case.
+    Replace the __attribute_noinline__ form with
     
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit e2aa2c8c4cc21eb312a301855c2e211dedf93146
-Author: Doug Nazar <nazard.michi@gmail.com>
-Date:   Mon Jul 19 10:58:47 2010 -0400
-
-    mountd: Fix memcmp result comparison error for uuid match.
-    
-    Fixed Small typo in the new fs uuid comparison code
+      __attribute__((__noinline__)).
     
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit eafc5a8873b09482c71313f425080cce2031010a
-Author: Doug Nazar <nazard.michi@gmail.com>
-Date:   Mon Jul 19 10:48:34 2010 -0400
-
-    gssd: Fix endtime issue
+    Even though the compiler didn't complain about __attribute_malloc__,
+    also replace those in order to maintain consistent style throughout the
+    source file.
     
-    Commit 4c5ff6d4 removed the setting of endtime for a few contexts by
-    accident.
+    Fix for:
     
-    Now to figure out why I get stale handles on submounts.
+      https://bugzilla.linux-nfs.org/show_bug.cgi?id=194
     
+    Reported-by: "Gabor Z. Papp" <gzp@papp.hu>
+    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 0bd7e91cea26bcfc5581290e4cdd87870da29b9e
+commit 7869a76207d3f4b3bd4ab57b4a7a8807ac2ff0c6
 Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Mon Jul 19 10:09:12 2010 -0400
+Date:   Mon Dec 13 14:36:15 2010 -0500
 
-    nfs-utils: Fix C aliasing rules violation in       nfs_getrpccaller()
+    sm-notify: Make use of AI_NUMERICSERV conditional
     
-    Squelch compiler warnings reported with -Wextra:
+    Gabor Papp reports nfs-utils-1.2.3 doesn't build on his system that
+    uses glibc-2.2.5:
     
-    In file included from statd.c:24:
-    ../../support/include/rpcmisc.h: In function nfs_getrpccaller_in:
-    ../../support/include/rpcmisc.h:58: warning: dereferencing type-punned
-    pointer might break strict-aliasing rules
-    ../../support/include/rpcmisc.h: In function nfs_getrpccaller:
-    ../../support/include/rpcmisc.h:63: warning: dereferencing type-punned
-    pointer might break strict-aliasing rules
+    make[3]: Entering directory
+    `/home/gzp/src/nfs-utils-1.2.3/utils/statd'
+    gcc -DHAVE_CONFIG_H -I. -I../../support/include   -D_GNU_SOURCE -Wall
+       -Wextra -Wstrict-prototypes  -pipe -g -O2 -MT sm-notify.o -MD
+       -MP -MF .deps/sm-notify.Tpo -c -o sm-notify.o sm-notify.c
+       sm-notify.c: In function 'smn_bind_address':
+    sm-notify.c:247: error: 'AI_NUMERICSERV' undeclared (first use in this
+    function)
+    sm-notify.c:247: error: (Each undeclared identifier is reported only
+    once
+    sm-notify.c:247: error: for each function it appears in.)
+    make[3]: *** [sm-notify.o] Error 1
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit a8715bec8bd671135f20fc0422d2a9fc0993758a
-Author: Kevin Constantine <kevin.constantine@disneyanimation.com>
-Date:   Tue Jun 22 17:43:19 2010 -0400
-
-    nfs-iostat.py: divide by zero with fresh mount
+    According to the getaddrinfo(3) man page, AI_NUMERICSERV is available
+    only since glibc 2.3.4.  getaddrinfo(3) seems to convert strings
+    containing a number to the right port value without the use of
+    AI_NUMERICSERV, so I think we can survive on older glibc's without it.
+    It will allow admins to specify service names as well as port numbers
+    on those versions.
     
-    When an export is freshly mounted, /proc/self/mountstats displays age = 0.
-    This causes nfs-iostat.py to divide by zero throwing an error.  When we
-    have age = 0, other stats are greater than 0, so we'll set age = 1 and
-    print the relevant stats.
+    There are uses of AI_NUMERICSERV in gssd and in nfs_svc_create().  The
+    one in nfs_svc_create() is behind HAVE_LIBTIRPC, and the other is a
+    issue only for those who want to deploy Kerberos -- likely in both
+    cases, a more modern glibc will be present.  I'm going to leave those
+    two.
     
-    Signed-off-by: Kevin Constantine <kevin.constantine@disneyanimation.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 9c3f7a220b4812c5d560db5fcacad790fc8b17af
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Tue Jun 22 13:31:38 2010 -0400
-
-    libexport.a: Remove unused hostent-based DNS helper        functions
-    
-    Clean up:  Get rid of hostent-based DNS helper functions in
-    libexport.a that have been replaced by addrinfo-based DNS helpers.
+    Fix for:
     
-    None of the original code remains, so replace the copyright notice as
-    well.
+      https://bugzilla.linux-nfs.org/show_bug.cgi?id=195
     
+    Reported-by: "Gabor Z. Papp" <gzp@papp.hu>
     Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 21015ace7d0a356b24a57540ccfeb41d941e78ed
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Tue Jun 22 13:06:40 2010 -0400
+commit e8dbaddc8465dcd07b53f8e80a537703dd0248ca
+Author: Sid Moore <learnmost@gmail.com>
+Date:   Fri Dec 3 09:19:06 2010 -0500
 
-    libexport.a: Replace matchhostname()
-    
-    So that exportfs can eventually support IPv6 addresses, copy statd's
-    getaddrinfo(3)-based matchhostname to exportfs, with adjustments for
-    dealing with export wildcards and netgroups.  Until exportfs has full
-    IPv6 support, however, we want to ensure that IPv6 addresses continue
-    to remain blocked in the address comparison code used by exportfs.  At
-    a later point we'll replace much of this with the generic functions
-    in sockaddr.h.
-    
-    Since it contains special logic for handling wildcard and netgroups,
-    this function is specialized for exportfs, and does not belong in
-    one of the shared libraries.
+    rpc.mountd: Checking RPC Procedure ID before process it
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 22d6566d473f71e241c791a02435d414648c99e8
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Tue Jun 22 12:51:42 2010 -0400
+commit 3c6973c595d62dc6452967d50ae8abe69f9f8bad
+Author: Mi Jinlong <mijinlong@cn.fujitsu.com>
+Date:   Mon Nov 29 10:59:10 2010 -0500
 
-    libexport.a: Add documenting comments
+    libnfs.a: fix a bug when parse section's arg
     
-    Clean up.  Add a few additional documenting comments for globally
-    visible functions.
+    When parsing section's arg at configure file, the pointer
+    should stop when fetch ']', and give the warning message.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 53928c0166dcc0acceaa995edb8551b48968b5dd
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Tue Jun 22 12:44:44 2010 -0400
+commit 86f7be64cafd17d4a3f164603484eaedb4757431
+Author: Harshula Jayasuriya <harshula@redhat.com>
+Date:   Mon Nov 22 11:22:31 2010 -0500
 
-    libexport.a: Make export_add() static
-    
-    Clean up: export_add() is not called from outside of export.c, so make
-    it a static helper.
+    nfs-utils: nfsstat: has_stats() does not function correctly for NFSv4 client stats
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 8940675a20967145b37a596334c25a54804435cc
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Tue Jun 22 12:43:55 2010 -0400
-
-    libexport.a: Make export_read() return void
+    The NFSv4 client procs/ops in "struct rpc_procinfo nfs4_procedures" is
+    used to generate the NFS client stats interface:
+    ------------------------------------------------------------
+    net 0 0 0 0
+    rpc 15 0 0
+    proc2 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+    proc3 22 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0
+    proc4 42 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
+    0 0 0
+    0 0 0 0 0 0 0
+    ------------------------------------------------------------
+    Note, for proc4, the number 42. That is the number of stats that follow
+    on the same line. Currently nfsstat's has_stats() relies on this number
+    to be equal to CLTPROC4_SZ. Unfortunately this is not the case. I have
+    changed has_stats() not to rely on these two values being equal. This
+    should also allow nfsstat to work with different kernel versions that
+    expose a different number of NFS client ops.
     
-    Clean up: export_read()'s return value is always zero, and its only
-    caller never checks it.
+    * Fix has_stats()
+    * Stop print_clnt_list() printing server stats!
+    * Describe the option -3 and -4 completely in the nfsstat manpage.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: Harshula Jayasuriya <harshula@redhat.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 0509d3428f523776ddd9d6e9fa318587d3ec7d84
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Tue Jun 22 12:43:01 2010 -0400
+commit 0868dcccb9a3bf3d022a32ff31311fe371484e77
+Author: Steve Dickson <steved@redhat.com>
+Date:   Sat Nov 20 15:01:21 2010 -0500
 
-    mountd: Replace "struct hostent" with "struct addrinfo"
-    
-    struct hostent can store either IPv4 or IPv6 addresses, but it can't
-    store both address families concurrently for the same host.  Neither
-    can hostent deal with parts of socket addresses that are outside of
-    the sin{,6}_addr field.
+    Enable nfsidmap to compile
     
-    Replace the use of "struct hostent" everywhere in libexport.a, mountd,
-    and exportfs with "struct addrinfo".  This is a large change, but
-    there are so many strong dependencies on struct hostent that this
-    can't easily be broken into smaller pieces.
+    Only enable the compilation of nfsidmap when libnfsidmap support it.
     
-    One benefit of this change is that hostent_dup() is no longer
-    required, since the results of getaddrinfo(3) are already dynamically
-    allocated.
-    
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 3ca5879be32c4c11750e12230ff588195fff0738
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Tue Jun 22 12:40:27 2010 -0400
+commit 6f07548141e710767d425e119d9823691293771d
+Author: Bryan Schumaker <bjschuma@netapp.com>
+Date:   Fri Nov 19 12:01:10 2010 -0500
 
-    exportfs: Add a common exit label in exportfs()
+    Add the new nfsidmap program
     
-    Clean up: Reduce code duplication by introducing a goto label for
-    freeing hp and exiting.  This will make replacing "struct hostent *"
-    with "struct addrinfo *" more straightforward in this code.
+    This patch adds the nfsidmap program to nfs-utils.  This program is
+    called by the nfs idmapper through request-keys to map between
+    uid / user name and gid / group name.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
+    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 94ce1eb94babb4c587b2826452fb053cba745098
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Tue Jun 22 10:41:03 2010 -0400
+commit 409487978593de13ae36be0ee56d8111ad6b3319
+Author: Steve Dickson <steved@redhat.com>
+Date:   Mon Nov 22 11:33:37 2010 -0500
 
-    libexport.a: Add helpers to manage DNS lookups
-    
-    Introduce DNS query helpers based on getaddrinfo(3) and
-    getnameinfo(3).  These will eventually replace the existing
-    hostent-based functions in support/export/hostname.c.
-    
-    Put some of these new helpers to immediate use, where convenient.
+    Removed a couple warnings from utils/mount/stropts.c
     
-    As they are part of libexport.a, I've added the forward declarations
-    for these new functions in exportfs.h rather than misc.h, where the
-    hostent-based forward declarations are currently.
+    stropts.c:740:6: warning: 'ret' may be used uninitialized in this function
+    stropts.c:653:6: warning: 'ret' may be used uninitialized in this function
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 8d61f2518bebe11c5fd0624857f83de1dceca991
-Author: NeilBrown <neilb@suse.de>
-Date:   Tue Jun 22 10:37:25 2010 -0400
+commit f4968a724c1d4162a8e2b9f6a19c460cc56c95f7
+Author: Chuck Lever <chuck.lever@oracle.com>
+Date:   Fri Oct 29 12:56:21 2010 -0400
 
-    Improve support for exporting btrfs subvolumes
+    nfs(5): Document remount behavior
     
-    If you export two subvolumes of a btrfs filesystem, they will both be
-    given the same uuid so lookups will be confused.
-    blkid cannot differentiate the two, so we must use the fsid from
-    statfs64 to identify the filesystem.
+    It appears that, for a long while, NFS "remount" mounts have
+    completely wiped the existing mount options in /etc/mtab for a given
+    mount point.  This is a problem for umount.nfs, since it reads its
+    options out of /etc/mtab to find out how to do the unmount.
     
-    We cannot tell if blkid or statfs is best without knowing internal
-    details of the filesystem in question, so we need to encode specific
-    knowledge of btrfs in mountd.  This is unfortunate.
+    The mount(8) command provides the NFS mount subcommand with the mount
+    options to perform the remount.  There are four cases to consider:
     
-    To ensure smooth handling of this and possible future changes in uuid
-    generation, we add infrastructure for multiple different uuids to be
-    recognised on old filehandles, but only the preferred on is used on
-    new filehandles.
+      1. Both the device and mount directory are specified on the
+         command line, and the target mount point is in /etc/fstab
     
-    Signed-off-by: NeilBrown <neilb@suse.de>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 9ac7a15017b876d4d8d3a4502ebaf954f36f7f54
-Author: Steve Dickson <steved@redhat.com>
-Date:   Thu Jun 3 08:53:22 2010 -0400
-
-    mount.nfs: silently fails when the network protocol is not found
+      2. Only one of the device and mount directory is specified on
+         the command line, and the target mount point is in
+         /etc/fstab
     
-    mount.nfs should display some type of error diagnostics when
-    the network protocol can not be determined.
+      3. Both the device and mount directory are specified on the
+         command line, and the target mount point is not in /etc/fstab
     
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 740171dea45a57e396a86fbda1579a465f101854
-Author: Steve Dickson <steved@redhat.com>
-Date:   Thu Jun 3 08:32:56 2010 -0400
-
-    mount: silently fails when bad option values are given
+      4. Only one of the device and mount directory is specified on
+         the command line, and the target mount point is not in
+         /etc/fstab
     
-    mount.nfs should not only fail when an invalid option values
-    are supplied (as it does), it should also print a diagnostic
-    message identifying the problem
+    Currently only case 4 works correctly.  In that case, mount(8)
+    provides the correct set of mount options to the mount.nfs
+    subcommand and it can update /etc/mtab correctly.
     
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 94c3d7c91de582cf29ff9100950ecd4a5fd1606b
-Author: Kevin Constantine <kevin.constantine@disneyanimation.com>
-Date:   Wed Jun 2 08:34:14 2010 -0400
-
-    nfsiostat.man: Add linebreak before --version option
+    Cases 1 and 3 replace all mount options in /etc/mtab with the options
+    provided on the command line during a remount.  Case 2 replaces the
+    mount options in /etc/mtab with a mix of options from /etc/fstab and
+    /etc/mtab.
     
-    The nfsiostat man file was missing a linebreak before the --verbose option
+    Cases 1 and 3 are historical behavior.  Basically this is a formal
+    interface to allow administrators to replace the mount options in
+    /etc/mtab completely, instead of merging in new ones.  The present
+    patch documents that behavior in nfs(5), and provides best practice
+    for remounting NFS mount points.
     
-    Signed-off-by: Kevin Constantine <kevin.constantine@disneyanimation.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 291b329ad1f5a65270097f4ec3a8dd465df42669
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Mon May 24 06:02:22 2010 -0400
-
-    mountd: Convert colons in IPv6 presentation addresses tosemicolons
+    There are near-term plans to address case 2 by fixing mount(8)
+    (provided by utils-linux-ng in most distributions).
     
-    The /var/lib/nfs/rmtab file delineates fields in each of its lines
-    with a ":".  The first field contains the IP address of a client, in
-    presentation format.  IPv6 presentation format addresses contain
-    colons, which screws up the field delineation of rmtab.
+    This is a partial fix for:
     
-    Use a simple simple scheme to convert the colons in incoming client
-    names to some other character, and then convert them back when the
-    rmtab file is read.
+      https://bugzilla.linux-nfs.org/show_bug.cgi?id=188
     
     Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 9e398e49be79af62fca8efb21849d8a2714dc92a
+commit 6d1a82b005994f759f2c847c0354413a24643da5
 Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Mon May 24 06:01:22 2010 -0400
+Date:   Thu Oct 28 13:15:22 2010 -0400
 
-    libexport.a: Refactor rmtab_read()
+    nfs(5): Grammar and style fixes
     
-    Clean up: Make it easier to add IPv6 support by refactoring part of
-    rmtab_read() into a helper function.
+    Clean up grammar and style issues introduced by recent updates.  Also,
+    I'm not certain inappropriate options are always ignored.
     
     Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 2fd2dfd9ebb2de145d50039233bd2a53b7f03062
-Author: NeilBrown <neilb@suse.de>
-Date:   Mon May 24 05:55:26 2010 -0400
-
-    Mountd listens on 2 different versions for NFSv2 (MOUNTv1 and MOUNTv2)
-    and one for NFSv3 (MOUNTv3)
-    
-    When --no-nfs-version requests an NFS version to be disabled, the
-    code actually disabled the MOUNT version. This works is several cases,
-    but requires --no-nfs-version 1 to completely disable NFSv2, which
-    is wrong.
-    
-    So if we do disable 1, 2, and 3. mountd complain and won't run, it
-    is not possible to run just v4 - i.e. not listening for MOUNT requests
-    at all (as v4 doesn't need them).
-    
-    So change the handling of "--no-nfs-version 2" it disable MOUNTv1 as
-    well as
-    MOUNTv2, and allow mountd to continue running as long as one of
-    NFSv2 NFSv3 NFSv4 is enabled.
-    
-    Signed-off-by: NeilBrown <neilb@suse.de>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 6299a310d77e6495efdf7c50491f0b055fee2cfe
+commit ab2cdb859f738a25e2567a2ec674cfa78a0a175d
 Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Wed May 5 15:41:07 2010 -0400
+Date:   Thu Oct 28 13:13:19 2010 -0400
 
-    mountd/exportfs: Make m_addrlist field a nfs_sockaddr
-    
-    To store non-AF_INET addresses in the nfs_client structure, we need to
-    use more than in_addr for the m_addrlist field.  Make m_addrlist
-    larger, then add a few helper functions to handle type casting and
-    array indexing cleanly.
+    mount.nfs: mnt_freq and mnt_pass are always zero
     
-    We could treat the nfs_client address list as if all the addresses
-    in the list were the same family.  This might work for MCL_SUBNETWORK
-    type nfs_clients.  However, during the transition to IPv6, most hosts
-    will have at least one IPv4 and one IPv6 address.  For MCL_FQDN, I
-    think we need to have the ability to store addresses from both
-    families in one nfs_client.
-    
-    Additionally, IPv6 scope IDs are not part of struct sin6_addr.  To
-    support link-local IPv6 addresses and the like, a scope ID must be
-    stored.
+    Clean up.
     
-    Thus, each slot in the address list needs to be capable of storing an
-    entire socket address, and not simply the network address part.
+    No need to pass constant zeros to add_mtab() from its only call site.
+    Ensure that initialization of a struct mntent is consistent in both
+    places that it is done.
     
     Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 6ff1fd42db18c657fbc5f81169a566b41d53e731
+commit bc4a0c42570d5620cc1bb32428e16b9c9b5f3863
 Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Wed May 5 14:42:01 2010 -0400
+Date:   Thu Oct 28 13:10:48 2010 -0400
 
-    libexport.a: Clean up client_add()
-    
-    Clean up: client_add()'s current callers never set unknown m_type
-    values, so the m_type check is unnecessary.
+    mount.nfs: Fix memory leak in nfs_sys_mount()
     
-    All of client_add()'s callers are in the same source file where it is
-    defined, so make it a static helper function.
+    This appears to have been left behind by last year's adjustments to
+    how the extra_opts string is constructed.
     
     Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 9bb85c5e8d2285f82367c75df5530a71a9a5a5f2
+commit 1f237ac72e6f563908b350e11fd2bb866c003028
 Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Wed May 5 14:37:13 2010 -0400
+Date:   Thu Oct 28 13:09:38 2010 -0400
 
-    libexport.a: Refactor client_init()
+    mount: Fix compiler warning in nfs_parse_retry_option()
     
-    Clean up:  Move subnet hostname parsing logic out of client_init() to
-    make it simpler to introduce IPv6 support.
+    stropts.c: In function nfs_parse_retry_option:
+    stropts.c:131: warning: conversion to unsigned int from long int may
+    alter its value
     
-    Make client_init() a helper, since it's already static.
+    Make it more clear what the second argument is for, and flag the
+    switch fallthrough case.
     
     Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 0a8bd742cc1412e2553f152ee0c3aab8c5570212
-Author: Mike Frysinger <vapier@gentoo.org>
-Date:   Fri Apr 23 12:22:53 2010 -0400
+commit 1ea2c3be33f2eb4630c5cdb78edf2bb670b294ab
+Author: Chuck Lever <chuck.lever@oracle.com>
+Date:   Thu Oct 28 12:12:12 2010 -0400
 
-    Make capabilities support optional
-    
-    The new code using libcap is quite minor, so rather than always reqiure
-    libcap support, make it a normal --enable type flag.  Current default
-    behavior is retained -- if libcap is found, it is enabled, else it is
-    disabled like every nfs-utils version in the past.
+    nfs-utils: Remove all uses of AI_ADDRCONFIG
     
-    Signed-off-by: Mike Frysinger <vapier@gentoo.org>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit fbc038b7a5c7f5f102bf2c4fb149030d0092eec8
-Author: Mike Frysinger <vapier@gentoo.org>
-Date:   Fri Apr 23 12:18:27 2010 -0400
-
-    set +x on autogen.sh
+    It was reported that, if only "lo" is up,
     
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 08e1512e4a932f41867f0b515348b9402db50cbd
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Fri Apr 23 12:09:35 2010 -0400
-
-    libexport.a: Allow malloc(3) failures in client_lookup() and friends
+      mount.nfs 127.0.0.1:/export /mount
     
-    Clean up: Use malloc(3) instead of xmalloc() in client_lookup() and
-    client_dup(), ensuring that a failed memory allocation here doesn't
-    cause our process to exit suddenly.
+    fails with "Name or service not known".
     
-    Allocation of nfs_client records and the m_hostname string are now
-    consistently handled with malloc(3), calloc(3), strdup(3), and
-    free(3).
+    "man 3 getaddrinfo" says this:
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit aa4b66b12b631885ed85f3ebe97e68b033407178
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Fri Apr 23 12:08:49 2010 -0400
-
-    libexport.a: Allow m_hostname allocation to fail instead of exit
+      If hints.ai_flags includes the AI_ADDRCONFIG flag, then IPv4
+      addresses are returned in the list pointed to by res only if the
+      local system has at least one IPv4 address configured, and IPv6
+      addresses are only returned if the local system has at least
+      one IPv6 address configured.
     
-    Clean up: Replace xstrdup() with strdup(3) in client_init(), to
-    prevent the process from exiting if the memory allocation fails.
+    The man page oversimplifies here.  A review of glibc shows that
+    getaddrinfo(3) explicitly ignores loopback addresses when deciding
+    whether an IPv4 or IPv6 address is configured.
     
-    Note that both of client_init()'s callers set m_hostname equal to NULL
-    before calling, thus the extra free(3) at the top of client_init() is
-    unneeded.
+    This behavior around loopback is a problem not just for mount.nfs,
+    but also for RPC daemons that have to start up before a system's
+    networking is fully configured and started.  Given the history of
+    other problems with AI_ADDRCONFIG and the unpredictable behavior it
+    introduces, let's just remove it everywhere in nfs-utils.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 5d954d871fb265af584faef5df6e2e7e6ada7c3b
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Fri Apr 23 12:02:34 2010 -0400
-
-    libexport.a: Allow client_init() to fail instead of exit
+    This fix addresses:
     
-    client_init()'s current callers can now deal correctly with a failure.
-    Get rid of code that can cause our process to exit in client_init(),
-    if address mask parsing or memory allocation fails.
+      https://bugzilla.linux-nfs.org/show_bug.cgi?id=191
     
     Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 75cbc8d3fc9e7c3750629bd72519770ab58b868f
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Fri Apr 23 12:00:28 2010 -0400
+commit f8e315543b7f1db7f37a4bfe8ede3020cef62868
+Author: Jeff Layton <jlayton@redhat.com>
+Date:   Thu Oct 28 09:18:33 2010 -0400
 
-    libexport.a: Add client_free()
+    nfs-utils: fix default value for --enable-tirpc
     
-    Clean up: Introduce a helper to free a nfs_client record.
+    We need $enable_tirpc to be a tristate. 'yes' means that someone
+    explicitly requested building with tirpc. 'no' means that it was
+    explicitly disabled. Anything else means that no one specified a value.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 7fc6f6c6b68ba7fa1be6de05ce3b9e2d97b82ea4
-Author: Steve Dickson <steved@redhat.com>
-Date:   Fri Apr 16 10:56:29 2010 -0400
-
-    Add in autoconf support for mountstats and nfsiostats
+    Fix it by setting the value to a blank string so that the default is
+    properly undefined.
     
+    Reported-by: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: Jeff Layton <jlayton@redhat.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit d8ff9ef2828059bb2ee115d22f3c9579421daf54
+commit c62d756402509ca5d07c1fd4d2e5a9d78dc4171b
 Author: Steve Dickson <steved@redhat.com>
-Date:   Fri Apr 16 10:49:10 2010 -0400
+Date:   Tue Oct 19 15:54:35 2010 -0400
 
-    Introduce man page for the nfsiostats command
+    Updated rpc.mountd man page
     
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit c03fe46d62bc78cb52d400fa5a52dc4ce9947945
-Author: Steve Dickson <steved@redhat.com>
-Date:   Fri Apr 16 10:46:41 2010 -0400
-
-    Introduce man page for the mountstats command
+    Updated the rpc.mountd man page to no longer reference
+    v3 as the "newer" version and also mentioned v4 as
+    a supported version.
     
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit c4b2281c6c748b768de7a49af89660c9c1a68b11
+commit 79e9079e9af4e5c2aa1d77815df1147b26876eb8
 Author: Steve Dickson <steved@redhat.com>
-Date:   Fri Apr 16 13:31:57 2010 -0400
+Date:   Tue Oct 19 15:54:04 2010 -0400
 
-    Removed some miscellaneous warnings in the new gssd code.
+    Cleared up the sync option in exportfs man page
     
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 4c5ff6d48021731128c4fc13d51610645a6fcf5c
-Author: Kevin Coffman <kwc@citi.umich.edu>
-Date:   Mon Apr 12 17:13:25 2010 -0400
+commit 6f228ea26be06572de245aed5496aaa122cca5a8
+Author: Steve Dickson <steved@redhat.com>
+Date:   Fri Oct 15 17:20:28 2010 -0400
 
-    Add support for non-DES encryption types.
+    Removed duplicate entries in export man page
     
-    Sends a new format of context information to the kernel.
-    (Requires kernel support to do anything useful.)
+    The man page's paragraphs about "refer=" and "replicas="
+    each appear twice.
     
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 76be349d5dd07f55797cb9920cc275667258f10f
-Author: Kevin Coffman <kwc@citi.umich.edu>
-Date:   Thu Apr 15 08:32:20 2010 -0400
+commit 849b7072a04975bb5da09245fbcacb0cb754a909
+Author: Chuck Lever <chuck.lever@oracle.com>
+Date:   Thu Oct 14 10:33:25 2010 -0400
 
-    Try to use kernel function to determine supported Kerberos enctypes.
+    mountd: Clear mountd registrations at start up
     
-    This patch replaces a hard-coded list with a function to obtain
-    the Kerberos encryption types that the kernel's rpcsec_gss code
-    can support.  Defaults to old behavior if kernel does not supply
-    information.
+    Clear stale MNT registrations before mountd tries to create fresh
+    listeners, to ensure that mountd starts.  This is also what statd does.
     
+    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 48d13033dcb27eb3d9ea78c39692ff7c54095950
-Author: Kevin Coffman <kwc@citi.umich.edu>
-Date:   Mon Apr 12 17:06:30 2010 -0400
+commit 93dcf64cc4a9e67f693aea35c8193428015f4a30
+Author: Chuck Lever <chuck.lever@oracle.com>
+Date:   Wed Oct 13 13:57:52 2010 -0400
 
-    gssd: move function limit_krb5_enctypes into the exported functions area
+    behavior as file systems that use the monolithic /sbin/mount command.
+    See the MS_NOMTAB macro in utils-linux-ng/mount/mount.c.
     
-    cleanup: Move function limit_krb5_enctypes() from the section
-    containing static functions into the section containing
-    externally visible functions.
+    Note that mount(8) has MS_USERS and MS_USER in the "nomtab" category
+    as well, but mount.nfs needs to record those values so that unmounting
+    a user-mounted NFS file system can work.
     
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 470448e77bd673b206cf40820f966dcb8f029f27
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Fri Apr 16 13:03:20 2010 -0400
-
-    libexport.a: export_find() should handle address parsing errors
+    While we're here, fix some white space damage in fix_opts_string().
     
-    An address mask parsing error can cause client_init(), and therefore
-    client_dup(), to make our process exit suddenly.  Soon we want to add
-    more complex address parsing in client_init(), so we need this
-    interface to be a little more robust.
+    This is a partial fix for:
     
-    Since export_find() can return NULL in some cases, it can handle NULL
-    returns from its subroutines if an address parsing error occurs, or if
-    memory is exhausted.  Allow for client_dup() to return NULL instead of
-    exiting sideways.
+      https://bugzilla.linux-nfs.org/show_bug.cgi?id=188
     
     Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 9b7cc679c70d00af3f44dc6a8b44a360a2423d64
+commit dc08c702a6c7f824f317af561f491635ee898a71
 Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Fri Apr 16 13:02:15 2010 -0400
+Date:   Wed Oct 13 13:55:10 2010 -0400
 
-    libexport.a: Add export_free()
+    umount.nfs: Distinguish between nfs4 and nfs mounts
     
-    Clean up: Introduce a helper to free an nfs_export record.
+    Neil Brown reports that umount.nfs is still confused by "-t nfs -o
+    vers=4" mounts.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 30eff9c26141746fb26efb1af60d5cbe7a16ebae
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Apr 15 08:59:18 2010 -0400
-
-    libexport.a: Add helper for populating m_addrlist[]
+    /etc/mtab can be confused.  /proc/mounts is authoritative on the
+    fstype of a mount.  Have umount.nfs consult it to determine which
+    mechanism to use for unmounting.  The code to read /proc/mounts was
+    lifted from the nfsstat command.
     
-    Clean up: Move common code that populates an nfs_client record's
-    m_addrlist to a helper function.  This eliminates a little code
-    duplication, and makes it simpler to add IPv6 support later.
+    The code introduced by this patch may look like belt-n-suspenders, but
+    we have two use cases to consider:
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit e1c93f691348392ee36b763bf57946540891ff16
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Apr 15 08:57:29 2010 -0400
-
-    libexport.a: Reduce code duplication in client_init()
+      1.  Old kernels don't support the "vers=4" mount option, so
+          umount.nfs must look for the "nfs4" fstype
+      2.  Upcoming kernels may eliminate support the "nfs4" fstype, so
+          umount.nfs must look for the "vers=4" mount option
     
-    Clean up:  Most cases in client_init() set clp->m_naddr to zero.  Move
-    it to the common part of the function, and simplify the logic.  This
-    will make adding IPv6 support here more straightforward.
+    Thus this logic checks for "nfs4" first then looks for the NFS version
+    setting.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 1fc99e6d5d6b9401e380ee756a4251c86a3b8d54
-Author: Mike Frysinger <vapier@gentoo.org>
-Date:   Thu Apr 15 08:49:28 2010 -0400
-
-    set +x on t0001-statd-basic-mon-unmon.sh
+    Note that we could handle unmounting entirely in the kernel, but that
+    won't help older kernels that have this issue.
     
-    The test framework tries to exec this script, but it fails because it
-    lacks the +x bit.
+    See:
+      https://bugzilla.linux-nfs.org/show_bug.cgi?id=189
     
-    Signed-off-by: Mike Frysinger <vapier@gentoo.org>
+    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit bf867b09201abb155b52e81aeb08757b2f7c6937
+commit 17962b82afb68ca8e6b0d3f432d36c6c7c4980ea
 Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Apr 8 11:01:14 2010 -0400
+Date:   Wed Oct 13 13:01:51 2010 -0400
 
-    libexport.a: replace xlog(L_FATAL) in client_check()
+    mount.nfs: mountproto does not support RDMA
     
-    Clean up: Prevent the process from exiting in client_check().  Report
-    bad m_type values, but return 0.
+    Clean up.  Our client does not support the MNT protocol on RDMA.
     
-    This removes another site where a mountd or exportfs process can exit
-    sideways.
+    nfs_mount_protocol() isn't invoked for RDMA mounts (they are shunted
+    off before nfs_options2pmap() is invoked).  But in case it ever is,
+    it should return the expected response.
     
     Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit a39b43b81a8e7b70310f250c5ffd77816577cd6c
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Apr 8 10:55:02 2010 -0400
+commit 73c61fa5cd114fa6eae0e095724ed63aa66a4a6b
+Author: NeilBrown <neilb@suse.de>
+Date:   Wed Oct 13 12:08:41 2010 -0400
 
-    libexport.a: Refactor wildcard checking in client_check()
+    gcc complained:
     
-    Clean up: refactor wildcard logic out of client_check() to make it
-    easier to introduce IPv6 support.
+    client.c: In function 'init_netmask6':
+    client.c:181:1: warning: no return statement in function returning
+    non-void
     
-    Match the style used for client_check_{fqdn,subnetwork,netgroup}.
+    and Suse' build system complained
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    I: Program returns random data in a function
+    E: nfs-utils no-return-in-nonvoid-function client.c:181
+    
+    when I built without --enable-ipv6
+    
+    Reviewed-by: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: NeilBrown <neilb@suse.de>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 346ca35298e45e55a58d0f566c3b32b69102c6de
+commit 7e90281b88c05b01c61152b54a0cf2faec45b09c
 Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Apr 8 10:54:01 2010 -0400
+Date:   Wed Oct 13 12:02:32 2010 -0400
 
-    libexport.a: Refactor netgroup checking in client_check()
+    mount.nfs: Eliminate compiler warnings in utils/mount/network.c
     
-    Clean up: refactor netgroup logic out of client_check() to make it
-    easier to introduce IPv6 support.
+    Clean up.
     
-     +  Use preferred style of keeping #ifdef out of the middle of
-        function definitions.  Squelch compiler warnings for "#ifndef
-        HAVE_INNETGR" by using __attribute__((unused)).
+    network.c: In function get_socket:
+    network.c:431: warning: dereferencing type-punned pointer might break
+        strict-aliasing rules
     
-     +  Use preferred style of not using curly braces around switch cases.
+    network.c: In function probe_bothports:
+    network.c:759: warning: dereferencing type-punned pointer might break
+        strict-aliasing rules
+    network.c:762: warning: dereferencing type-punned pointer might break
+        strict-aliasing rules
     
-     +  Match style used for check_{fqdn,subnetwork}.
+    network.c: In function nfs_probe_statd:
+    network.c:775: warning: dereferencing type-punned pointer might break
+        strict-aliasing rules
     
-     +  Clarify comment documenting use of h_aliases
+    network.c: In function nfs_call_umount:
+    network.c:904: warning: dereferencing type-punned pointer might break
+        strict-aliasing rules
+    
+    network.c: In function nfs_ca_sockname:
+    network.c:1106: warning: dereferencing type-punned pointer might break
+        strict-aliasing rules
+    network.c:1112: warning: dereferencing type-punned pointer might break
+        strict-aliasing rules
     
     Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 3455138100064d0213b124c72453accde2276be5
+commit 57385cf87790c0cbdfddfccdde66bd2c8da45923
 Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Apr 8 10:52:33 2010 -0400
+Date:   Wed Oct 13 11:59:30 2010 -0400
 
-    libexport.a: Remove unused function client_checkaddr()
+    mount.nfs: Eliminate compiler warning in utils/mount/parse_opt.c
     
-    Clean up.
+    parse_opt.c: In function po_rightmost:
+    parse_opt.c:517: warning: conversion to int from unsigned int may
+        change the sign of the result
+    
+    "i" contains the function's result value, so it should be defined as
+    the same type as the function's return type.
     
     Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit a4e3d5c53195c789ae26697a0b2ecdf05d76a85b
+commit 1ee10ef034cbca86da4df271ac4097a948e7ab59
 Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Apr 8 10:51:54 2010 -0400
+Date:   Wed Oct 13 11:58:27 2010 -0400
 
-    libexport.a: Factor SUBNETWORK checking out of     check_client()
+    mount.nfs: Eliminate compiler warning in utils/mount/nfsumount.c
     
-    Clean up:  Factor the MCL_SUBNETWORK case out of check_client() and
-    client_checkaddr().  This will make it easier to add IPv6 support
-    eventually.
-    
-    The logic in the new helper function will get a little more tangled
-    once IPv6 support is introduced.  Each slot in the clp address list
-    eventually may contain an address from either address family.
+    Clean up.
     
-    Note that the switch statement in client_checkaddr() is redundant,
-    since clp->cl_mtype is loop invariant.  This change makes SUBNETWORK
-    client checking more computationally efficient, at the cost of a few
-    extra lines of code.
+    nfsumount.c:374: warning: ISO C forbids omitting the middle term of
+       a ?: expression
     
-    This commit should not change code behavior in any way.
+    This is also probably harmless, but let's make the code unambiguous.
     
     Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 6abde64e6a605443dfc283ffb2642cb853f8b5b0
+commit e9c97e4f7075e563d7a442ca8298ac56bafba0d5
 Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Thu Apr 8 10:50:41 2010 -0400
+Date:   Wed Oct 13 11:56:58 2010 -0400
 
-    libexport.a: Factor FQDN checking out of check_client()
-    
-    Clean up:  Factor the MCL_FQDN case out of check_client() and
-    client_checkaddr().  This will make it easier to add IPv6 support
-    eventually.
+    mount.nfs: Eliminate compiler warning in utils/mount/nfsumount.c
     
-    The logic in the new helper function will get a little more tangled
-    once IPv6 support is introduced.  Each slot in the clp address list
-    eventually may contain an address from either address family.
+    Clean up.
     
-    Note that the switch statement in client_checkaddr() is redundant,
-    since clp->cl_mtype is loop invariant.  This change makes FQDN client
-    checking more computationally efficient, at the cost of a few extra
-    lines of code.
+    nfsumount.c:265: warning: no previous prototype for nfsumount
     
-    This commit should not change code behavior in any way.
+    It's also a good idea if the compiler can ensure that the prototype
+    in nfsmount.h matches the actual function defined in nfsumount.c.
     
     Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit e8a54a3d5e32c9de009f84d1ef3f26d2dffbf226
-Author: Steve Dickson <steved@redhat.com>
-Date:   Thu Apr 8 10:43:49 2010 -0400
-
-    Remove some warnings that were introduced by commit 6ca440c
-    
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit 132744e9f8885254bcf213c90009d40adeb716bc
+commit e2b6d9cbaf20df26dd371a715fce3ae158f37126
 Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Mon Mar 22 10:18:00 2010 -0400
+Date:   Wed Oct 13 11:54:49 2010 -0400
 
-    libexport.a: e_fslocdata should be freed with free(3)
+    mount.nfs: Eliminate compiler warnings in utils/mount/mount.c
     
-    Clean up: Since e_fslocdata is allocated with strdup(3), and not
-    xstrdup(), it should be freed with free(3), and not xfree().
+    Clean up.
     
-    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit e3b0046b4b12a6e05c0a7afd59ca5431ded51e96
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Mon Mar 22 10:16:04 2010 -0400
-
-    libexport.a: Fix whitespace damage in      support/export/export.c
+    mount.c: In function parse_opt:
+    mount.c:354: warning: conversion to size_t from int may change the
+        sign of the result
+    mount.c:354: warning: conversion to int from size_t may change the
+        sign of the result
+    mount.c:359: warning: conversion to size_t from int may change the
+        sign of the result
+    mount.c:359: warning: conversion to int from size_t may change the
+        sign of the result
+    mount.c: In function parse_opts:
+    mount.c:374: warning: conversion to int from size_t may change the
+        sign of the result
+    mount.c:377: warning: conversion to size_t from int may change the
+        sign of the result
     
-    Clean up whitespace damage introduced by commit 4cacc965.
+    Character string lengths are usually size_t anyway.  We can easily
+    avoid the implicit type cast here.
     
     Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 5f722d8855ebcb2d041e182c8c69c8cbee4bf408
+commit 013e8ec9ffb9f28f97e58299719023faf846a029
 Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Mon Mar 22 10:13:15 2010 -0400
+Date:   Wed Oct 13 11:53:44 2010 -0400
 
-    libexport.a: Clean up client_compose() and client_member()
+    mount.nfs: Eliminate compiler warning in utils/mount/mount.c
+    
+    Clean up.
+    
+    mount.c: At top level:
+    mount.c:324: warning: no previous prototype for ?mount_usage?
     
-    Clean up:  Replace outdated comments, and fix some function
-    declarations.  Use proper type for a couple of automatic variables.
+    mount_usage() has no callers outside of utils/mount/mount.c and no
+    prototype is provided in a header file.  Make it static.
     
     Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit aa4c771fc359e097a3a6c3637f78c7bed7c450e9
+commit 47480475c99335c1203e81662f815b62573c19e8
 Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Mon Mar 22 10:10:59 2010 -0400
+Date:   Wed Oct 13 11:50:57 2010 -0400
 
-    libexport.a: Remove dead code
+    mount.nfs: Eliminate compiler warnings in utils/mount/version.h
     
-    Clean up:  I can't find any call sites for client_find() or
-    client_match().
+    Clean up.
+    
+    In file included from mount.c:50:
+    version.h: In function linux_version_code:
+    version.h:48: warning: conversion to unsigned int from int may
+        change the sign of the result
+    version.h:48: warning: conversion to unsigned int from int may
+        change the sign of the result
+    version.h:48: warning: conversion to unsigned int from int may
+        change the sign of the result
     
     Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 0935cebc1e130c6adfd870c88a6493277c84d47f
+commit 00885013dccbe00f5cc4e19223cf18e85a8e616a
 Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Fri Mar 19 16:14:26 2010 -0400
+Date:   Wed Oct 13 11:44:23 2010 -0400
 
-    mount: Mount should retry unreachable hosts
+    mount.nfs: Eliminate compiler warning in utils/mount/mount.c
     
-    Currently if a server is up but not responding (ie, it answers ARP
-    requests, but not NFS or RPC requests), mount retries or backgrounds
-    itself waiting for the server.
+    Clean up.
     
-    If the server is not responding on the network at all, mount fails
-    the mount request immediately.
+    In file included from mount.c:41:
+    mount_config.h:35: warning: no previous prototype for mount_config_opts
     
-    Users might find it more useful if mount retried in both cases.
+    Functions defined in include files are usually declared as "static
+    inline," eliminating the need for a forward declaration.
     
-    Note that this change means attempting to mount using a misspelled
-    server name will "hang" for the retry amount.  I suppose the error
-    message isn't very helpful whether it fails immediately or waits
-    a couple of minutes, though I imagine that an unreachable server is a
-    much more common occurrence than a misspelling.
+    While I was there, I also fixed the macro that prevents including
+    mount_config.h multiple times, and fixed some white space damage.
     
-    Reported-by: Daniel Goering <g_daniel@gmx.net>
     Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit baa41b2c78e796540c45692ea35214f7090a78cb
+commit ffa577350b03ddd421d455a8cd4cff86e3718264
 Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Fri Mar 19 16:03:45 2010 -0400
+Date:   Wed Oct 13 11:38:22 2010 -0400
 
-    sm-notify: Send fully-qualified and unqualified mon_names
-    
-    During any file locking interaction between an NFS client and server,
-    the client tells the server what hostname it will use as the mon_name
-    argument of the SM_NOTIFY request sent by the client when it reboots.
-    This is the "caller_name" argument of an NLMPROC_LOCK request.
-    
-    The server, however, never tells the client what mon_name argument
-    it will use when sending an SM_NOTIFY request.  In order to recognize
-    the server, clients usually guess what mon_name the server might
-    send, by using the server hostname provided by the user on the mount
-    command line.
+    mount.nfs: Eliminate compiler warnings
     
-    Frequently, the user provides an unqualified server name on the mount
-    command.  The server might then call the client back with a fully
-    qualified domain name, which might not match in some cases.
-    
-    Solaris, and perhaps other implementations, attempt to mitigate this
-    problem by sending two SM_NOTIFY requests to each peer: one with an
-    unqualified mon_name argument, and one with a fully qualified mon_name.
+    Clean up.
     
-    Implement such a scheme for sm-notify.
+    fstab.c: In function ?lock_mtab?:
+    fstab.c:385: warning: declaration of ?errsv? shadows a previous local
+    fstab.c:367: warning: shadowed declaration is here
+    fstab.c:407: warning: declaration of ?errsv? shadows a previous local
+    fstab.c:367: warning: shadowed declaration is here
+    fstab.c:417: warning: declaration of ?tries? shadows a previous local
+    fstab.c:325: warning: shadowed declaration is here
+    fstab.c:422: warning: declaration of ?errsv? shadows a previous local
+    fstab.c:367: warning: shadowed declaration is here
     
-    Since my_name is almost always the fully-qualified hostname associated
-    with the local system, just wiping the left-most '.' in the my_name
-    argument and sending another SM_NOTIFY is nearly always sufficient.
+    These are probably harmless.  Reusing a variable name, however, is a
+    little confusing to follow when reading the code.
     
     Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 900df0e7c0b9006d72d8459b30dc2cd69ce495a5
-Author: Chuck Lever <chuck.lever@oracle.com>
-Date:   Wed Mar 17 06:15:08 2010 -0400
+commit 5fe118b838254023d83424c5010ae73a91ec267d
+Author: Trond Myklebust <Trond.Myklebust@netapp.com>
+Date:   Wed Oct 13 11:27:21 2010 -0400
 
-    sm-notify: Use my_name when sending SM_NOTIFY requests
+    export: Ensure that we free struct exportent->e_uuid
+    
+    Currently, the exportent->e_uuid is initialised in
+    support/nfs/exports.c:parseopts(), but it is never freed.
     
-    The mon_name argument of an SM_NOTIFY request is a string that
-    identifies the rebooting host.
+    Also ensure that exportent->e_uuid is duplicated correctly in
+    dupexportent().
     
-    sm-notify should send the my_name provided by the local lockd at the
-    time the remote was monitored, rather than cocking up a mon_name
-    argument based on the present return value of gethostname(3).  If the
-    local system's hostname happened to change after the last reboot, then
-    the string returned by gethostname(3) will not be recognized by the
-    remote.  Thus the remote will never initiate lock recovery for the
-    original named host, possibly leaving stale locks.
+    Adjusted to account for the new export_free() helper.
     
-    The existing behavior of using the -v command line option as the
-    mon_name argument is preserved, but we now prevent sending an IP
-    presentation address, as some non-Linux implementations don't
-    recognize addresses as valid mon_names.
+    Also, e_uuid points to memory that is always allocated with strdup(3),
+    not with xstrdup().  Thus it must be freed via free(3) and not via
+    xfree().
     
+    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
     Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-    Reviewed-by: Jeff Layton <jlayton@redhat.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 70c59e231e7257ac93b68ba4b844f8d10a6af4a8
-Author: J. Bruce Fields <bfields@citi.umich.edu>
-Date:   Mon Mar 8 15:02:26 2010 -0500
+commit 656028f9925f5817c5a37565d27159973db84ec3
+Author: Chuck Lever <chuck.lever@oracle.com>
+Date:   Wed Oct 13 11:22:07 2010 -0400
 
-    mountd: trivial: name parameters for clarity
+    libnfs.a: Allow multiple RPC listeners to share    listener port number
     
-    Part of the reason for the previous bug was confusion between "subpath"
-    and "path"; which is the shorter path, and which the longer?
+    Normally, when "-p" is not specified on the mountd command line, the
+    TI-RPC library chooses random port numbers for each listener.  If a
+    port number _is_ specified on the command line, all the listeners
+    will get the same port number, so SO_REUSEADDR needs to be set on
+    each socket.
     
-    "child" and "parent" seem less ambiguous.
+    Thus we can't let TI-RPC create the listener sockets for us in this
+    case; we must create them ourselves and then set SO_REUSEADDR (and
+    other socket options) by hand.
     
-    Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
-    Signed-off-by: Steve Dickson <steved@redhat.com>
-
-commit a064fde8c2615333227de97d159bb338d4ac640d
-Author: J. Bruce Fields <bfields@citi.umich.edu>
-Date:   Mon Mar 8 14:59:01 2010 -0500
-
-    mountd: fix path comparison for v4 crossmnt
+    Different versions of the same RPC program have to share the same
+    listener and SVCXPRT, so we have to cache xprts we create, and re-use
+    them when additional requests for registration come from the
+    application.
     
-    This was obviously wrong, since path[strlen(path)] == '\0'
-    should always be true.
+    Though it doesn't look like it, this fix was "copied" from the legacy
+    rpc_init() function.  It's more complicated for TI-RPC, of course,
+    since a TI-RPC application can set up listeners with a nearly
+    arbitrary number of address families and socket types, not just the
+    two listeners that legacy RPC applications can set up (one for AF_INET
+    UDP and one for AF_INET TCP).
     
-    Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
+    See:
+      https://bugzilla.linux-nfs.org/show_bug.cgi?id=190
+    
+    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 6ca440c2661dccb05ae74ffb65817e9c30f05c8a
+commit 1296be71ebae4c0d7da61cc1077d97562d3bc549
 Author: Steve Dickson <steved@redhat.com>
-Date:   Mon Mar 8 11:22:46 2010 -0500
+Date:   Wed Oct 13 10:17:58 2010 -0400
 
-    mountd: fix --manage-gids hang due to int/uint bug
-    
-    A uid or gid should be represented as unsigned, not signed.
+    nfs-utils: Fixed typo in NFS man page
     
-    The conversion to signed here could cause a hang on access by an unknown
-    user to a server running mountd with --manage-gids; such a user is
-    likely to be mapped to 232-1, which may be converted to 231-1 when
-    represented as an int, resulting in a downcall for uid 231-1, hence the
-    original rpc hanging forever waiting for a cache downcall for 232-1.
+    Chuck pointed out there was a grammar typo in addition to the spelling
+    typo.  Here is a revised version of the patch.
     
-    Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
+    Signed-off-by: Jim Rees <rees@umich.edu>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 84346b7d7e69c113d6dbf03f2646a47b0e74a6b8
+commit 9afbdbad4436df6f7a5a501c6e4db04c3a5bbb08
 Author: Steve Dickson <steved@redhat.com>
-Date:   Mon Mar 8 10:24:44 2010 -0500
+Date:   Wed Oct 13 10:15:12 2010 -0400
 
-    Use authunix_create() instead of authsys_create() to fix regression.
+    Fix style nits in atomicio.c
     
-    Commit 409b8 introduced a regression when the --disable-tirpc
-    configuration flag is set. The authsys_create() interface, which
-    was introduced, does not exist in the legacy glibc library.
-    
-    Since the authsys_create() interface is a redefined of the
-    authunix_create() interface, which is defined in glibc, using
-    authunix_create() resolves the regression,
-    
-    Acked-by: Jeff Layton <jlayton@redhat.com>
+    Signed-off-by: Jim Rees <rees@umich.edu>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 409b89cc7106154780400c6b2bdce46bc9d5db4b
-Author: Jeff Layton <jlayton@redhat.com>
-Date:   Mon Mar 1 08:07:34 2010 -0500
+commit c117b7a1f29db65d139824ba5bab2a58bf5609e2
+Author: Steve Dickson <steved@redhat.com>
+Date:   Wed Oct 13 10:09:53 2010 -0400
 
-    nfs-utils: add and use nfs_authsys_create
-    
-    The current mount, umount and showmount code uses
-    authunix_create_default to get an auth handle. The one provided by glibc
-    returned a truncated list of groups when there were more than 16 groups.
-    libtirpc however currently does an abort() in this case, which causes
-    the program to crash and dump core.
+    nfs-utils: Move common code into support
     
-    nfs-utils just uses these auth handles for the MNT protocol, so the
-    group list doesn't make a lot of difference here. Add a new function
-    that creates an auth handle with a supplemental gids list that consists
-    only of the primary gid. Have nfs-utils use that function anywhere that
-    it currently uses authunix_create_default. Also, have the caller
-    properly check for a NULL return from that function.
+    There are several source files and headers present in the ./utils/idmapd
+    directory which are also usable in a doimapd daemon. Because of this we
+    move that support into the support directory such that it can be shared by
+    both daemons.
     
-    Signed-off-by: Jeff Layton <jlayton@redhat.com>
+    Signed-off-by: Jim Rees <rees@umich.edu>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 9c8c2cd50d3cf0316c2a1bdf6cb9efc7e1a20be9
-Author: Trond Myklebust <Trond.Myklebust@netapp.com>
-Date:   Mon Mar 1 07:37:49 2010 -0500
+commit 8c217b9623c8304608196aeb2f7360abfdf987c8
+Author: Suresh Jayaraman <sjayaraman@suse.de>
+Date:   Wed Sep 29 07:14:14 2010 -0400
 
-    Fix a typo in commit 6d5ac3fa (nfsd: Disble NFS 4.1 functionality by
-    default).
-    
-    We did not really intend to make NFSv4.0 support conditional on NFSv4.1
-    being enabled.
+    The kernel 2.6.37 has a add new mount option: local_lock.
+    Document the new option in the nfs(5) man page.
     
+    Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
     Signed-off-by: Steve Dickson <steved@redhat.com>
 
-commit 639b63394c6dd66e06423bfe810366277955c570
+commit 554df6bc8456c6971c1c597f70d3b9131e4e5e11
 Author: Steve Dickson <steved@redhat.com>
-Date:   Thu Feb 18 07:35:00 2010 -0500
+Date:   Tue Sep 28 08:24:16 2010 -0400
 
-    Release 1.2.2
+    Revert "nfs-iostat.py: don't wait for an extra interval when given a count"
     
-    Signed-off-by: Steve Dickson <steved@redhat.com>
+    This reverts commit 837796686ad8f9178c7b6855ada728a53ae511e3.
diff --git a/aclocal/keyutils.m4 b/aclocal/keyutils.m4
new file mode 100644 (file)
index 0000000..84bc112
--- /dev/null
@@ -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], ,
+                  [AC_MSG_ERROR([keyutils.h header not found.])])
+])dnl
index cfcde2f8fafc1594295ded6079e2c1463e0b9973..4faa923f190c2b14df663ee93697e42b9ecf4b75 100644 (file)
@@ -14,4 +14,8 @@ AC_DEFUN([AC_LIBNFSIDMAP], [
                [AC_DEFINE([HAVE_NFS4_SET_DEBUG], 1,
                           [Define to 1 if you have the `nfs4_set_debug' function.])])
 
+  dnl only enable nfsidmap when libnfsidmap supports it
+  AC_CHECK_LIB([nfsidmap], [nfs4_owner_to_uid], [enable_nfsidmap=yes],
+               [enable_nfsidmap=no])
+
 ])dnl
index 3058be6cfcafa2632a374c9d63e4ba1995faefdd..ca12f9ea455231e0c1a43370ff038cfe517c936b 100644 (file)
@@ -1,6 +1,6 @@
 dnl Process this file with autoconf to produce a configure script.
 dnl
-AC_INIT([linux nfs-utils],[1.2.3],[linux-nfs@vger.kernel.org],[nfs-utils])
+AC_INIT([linux nfs-utils],[1.2.4],[linux-nfs@vger.kernel.org],[nfs-utils])
 AC_CANONICAL_BUILD([])
 AC_CANONICAL_HOST([])
 AC_CONFIG_MACRO_DIR(aclocal)
@@ -132,11 +132,20 @@ AC_ARG_ENABLE(mount,
        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=yes,
+               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='yes')
+       enable_tirpc='')
 AC_ARG_ENABLE(ipv6,
        [AC_HELP_STRING([--enable-ipv6],
                         [enable support for IPv6 @<:@default=no@:>@])],
@@ -247,6 +256,12 @@ if test "$enable_nfsv4" = yes; then
   dnl check for nfsidmap libraries and headers
   AC_LIBNFSIDMAP
 
+  dnl enable nfsidmap when its support by libnfsidmap
+  AM_CONDITIONAL(CONFIG_NFSIDMAP, [test "$enable_nfsidmap" = "yes"])
+
+  dnl check for the keyutils libraries and headers
+  AC_KEYUTILS
+
   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
@@ -279,6 +294,13 @@ AC_SUBST(LIBCRYPT)
 AC_SUBST(LIBBSD)
 AC_SUBST(LIBBLKID)
 
+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])])
@@ -435,6 +457,7 @@ AC_CONFIG_FILES([
        utils/mountd/Makefile
        utils/nfsd/Makefile
        utils/nfsstat/Makefile
+       utils/nfsidmap/Makefile
        utils/showmount/Makefile
        utils/statd/Makefile
        tests/Makefile
index dbfc2b1449bfe251a74f5e8d08026e5e2ba63d40..ba2db8fa3ac8a5eb480158aab023c818e36eda18 100644 (file)
@@ -178,6 +178,7 @@ out_badprefix:
 static int
 init_netmask6(nfs_client *UNUSED(clp), const char *UNUSED(slash))
 {
+       return 0;
 }
 #endif /* IPV6_SUPPORTED */
 
index f528603b686bb541a47a823b71b3dbdac8ff4ec6..4fda30a799169e232e42b56d63579e315748c3c9 100644 (file)
@@ -38,6 +38,7 @@ export_free(nfs_export *exp)
        xfree(exp->m_export.e_sqgids);
        free(exp->m_export.e_mountpoint);
        free(exp->m_export.e_fslocdata);
+       free(exp->m_export.e_uuid);
 
        xfree(exp->m_export.e_hostname);
        xfree(exp);
index 3c55ce7ef4bf6261c28b62f23a5f701552ee441b..3e949a18fe52255b51a4d77713f28b1679f16b75 100644 (file)
 #include "sockaddr.h"
 #include "exportfs.h"
 
-#ifndef HAVE_DECL_AI_ADDRCONFIG
-#define AI_ADDRCONFIG  0
-#endif
-
 /**
  * host_ntop - generate presentation address given a sockaddr
  * @sap: pointer to socket address
@@ -170,7 +166,7 @@ host_addrinfo(const char *hostname)
 #endif
                /* don't return duplicates */
                .ai_protocol    = (int)IPPROTO_UDP,
-               .ai_flags       = AI_ADDRCONFIG | AI_CANONNAME,
+               .ai_flags       = AI_CANONNAME,
        };
        int error;
 
@@ -262,17 +258,19 @@ host_canonname(const struct sockaddr *sap)
  * @sap: pointer to socket address to look up
  *
  * Reverse and forward lookups are performed to ensure the address has
- * proper forward and reverse mappings.
+ * matching forward and reverse mappings.
  *
- * Returns address info structure with ai_canonname filled in, or NULL
- * if no information is available for @sap.  Caller must free the returned
- * structure with freeaddrinfo(3).
+ * 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;
+       struct addrinfo *ai, *a;
        char *hostname;
 
        hostname = host_canonname(sap);
@@ -280,9 +278,31 @@ host_reliable_addrinfo(const struct sockaddr *sap)
                return NULL;
 
        ai = host_addrinfo(hostname);
+       if (!ai)
+               goto out_free_hostname;
 
-       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;
 }
 
 /**
index f89c644a81c119e93d00ab5b8c60e0b49228c5e9..2950a90e8a6f2f55998e104e1f54e9d0c84489dc 100644 (file)
@@ -78,7 +78,7 @@ cltsetup(struct nfsctl_client *cltarg, nfs_client *clp)
        str_tolower(cltarg->cl_ident);
 
        j = 0;
-       for (i = 0; i < cltarg->cl_naddr && i < NFSCLNT_ADDRMAX; i++) {
+       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;
index 3cf1ee82b9461bd20d5b3c16b7dc7cd929b34f36..01e87ddc289252e818f50ab375d9fc25969a8c9f 100644 (file)
@@ -100,6 +100,7 @@ typedef struct mexport {
 } nfs_export;
 
 #define HASH_TABLE_SIZE 1021
+#define DEFAULT_TTL    (30 * 60)
 
 typedef struct _exp_hash_entry {
        nfs_export * p_first;
index bc5ba235e15dd0fa1931b1f2e9542ca681db113b..eedc1feaf4eaa712e0b725c77bb9a732c83bb38b 100644 (file)
@@ -17,4 +17,7 @@ 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 */
index 3db5bec879f429ed5fae5e3272013ea23da2898e..73f3c20cd6c9db64096cd9d53192cd799b9755a8 100644 (file)
 #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
@@ -89,6 +95,7 @@ struct exportent {
        char *          e_fslocdata;
        char *          e_uuid;
        struct sec_entry e_secinfo[SECFLAVOR_COUNT+1];
+       unsigned int    e_ttl;
 };
 
 struct rmtabent {
@@ -163,6 +170,12 @@ 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))
 
index c5847fa261fd2635a6499ec1323d8a8b5bbf34e2..0b06457bbb74d1d8386fd4c343fd825caa804be8 100644 (file)
@@ -31,7 +31,7 @@ struct rpc_dentry {
 
 struct rpc_dtable {
        struct rpc_dentry *entries;
-       int             nproc;
+       rpcproc_t               nproc;
 };
 
 #define dtable_ent(func, vers, arg_type, res_type) \
index 60400b2530e08342a866f195cad95617e0251c78..05c2fc456b1300a5f3f0c316848792bce251339a 100644 (file)
@@ -5,7 +5,7 @@ libnfs_a_SOURCES = exports.c rmtab.c xio.c rpcmisc.c rpcdispatch.c \
                   xlog.c xcommon.c wildmat.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
+                  svc_create.c atomicio.c strlcpy.c strlcat.c
 
 MAINTAINERCLEANFILES = Makefile.in
 
diff --git a/support/nfs/atomicio.c b/support/nfs/atomicio.c
new file mode 100644 (file)
index 0000000..5e760e6
--- /dev/null
@@ -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;
+}
index 24640f4a2c3923759ff3818acefb24a5dbaeb600..fa0dc6b792da8bb5fc8a6e4f8d461e6556002d39 100644 (file)
@@ -251,6 +251,7 @@ conf_parse_line(int trans, char *line, size_t sz)
                }
                /* Strip off any blanks before ']' */
                val = line;
+               j=0;
                while (*val && !isblank(*val)) 
                        val++, j++;
                if (*val)
@@ -271,9 +272,9 @@ conf_parse_line(int trans, char *line, size_t sz)
                if (ptr == NULL)
                        return;
                line = ++ptr;
-               while (*ptr && *ptr != '"')
+               while (*ptr && *ptr != '"' && *ptr != ']')
                        ptr++;
-               if (*ptr == '\0') {
+               if (*ptr == '\0' || *ptr == ']') {
                        xlog_warn("config file error: line %d: "
                                "non-matched '\"', ignoring until next section", ln);
                }  else {
index a93941caf0ca6a87fea44d134d7591ee31106aac..c250383a1b2fe2ada93bc5c8bf172fc02e3ad49b 100644 (file)
@@ -107,6 +107,7 @@ static void init_exportent (struct exportent *ee, int fromkernel)
        ee->e_nsquids = 0;
        ee->e_nsqgids = 0;
        ee->e_uuid = NULL;
+       ee->e_ttl = DEFAULT_TTL;
 }
 
 struct exportent *
@@ -141,9 +142,14 @@ getexportent(int fromkernel, int fromexports)
                return NULL;
        }
        first = 0;
-               
-       /* Check for default options */
-       if (exp[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;
                
@@ -332,6 +338,8 @@ dupexportent(struct exportent *dst, struct exportent *src)
                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;
 }
 
index a5216fcf829cdf2e7e1c5524e0bb750eaa53fa43..a2118a27a172fa54ba5657c0b31c2ad50d14ac38 100644 (file)
@@ -12,6 +12,7 @@
 #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"
@@ -127,9 +128,11 @@ 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);
@@ -143,6 +146,12 @@ nfs_addmntent (mntFILE *mfp, struct mntent *mnt) {
        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;
 }
 
index 984c646710a97f10d5d1fb443a7d4a3eba55e0c7..f7c27c985d0c04248f48245fab03b98a052fbac6 100644 (file)
@@ -32,7 +32,12 @@ rpc_dispatch(struct svc_req *rqstp, SVCXPRT *transp,
                return;
        }
        dtable += (rqstp->rq_vers - 1);
-       if (((int)rqstp->rq_proc) > dtable->nproc) {
+       if (rqstp->rq_proc > dtable->nproc) {
+               svcerr_noproc(transp);
+               return;
+       }
+
+       if (dtable->nproc <= rqstp->rq_proc) {
                svcerr_noproc(transp);
                return;
        }
diff --git a/support/nfs/strlcat.c b/support/nfs/strlcat.c
new file mode 100644 (file)
index 0000000..daedd7a
--- /dev/null
@@ -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/support/nfs/strlcpy.c b/support/nfs/strlcpy.c
new file mode 100644 (file)
index 0000000..a2653ee
--- /dev/null
@@ -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 */
+}
index 59ba505b48bfc2adc243de2eb97c259220c382d3..b3f75edc2f9608577da0ea5734011d719c827bc5 100644 (file)
@@ -27,6 +27,7 @@
 #include <memory.h>
 #include <signal.h>
 #include <unistd.h>
+#include <errno.h>
 #include <netdb.h>
 
 #include <netinet/in.h>
 #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.
  *
@@ -98,17 +156,113 @@ svc_create_bindaddr(struct netconfig *nconf, const uint16_t port)
        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(const char *name, const rpcprog_t program,
+svc_create_nconf_rand_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 netconfig *nconf)
 {
        struct t_bind bindaddr;
        struct addrinfo *ai;
        SVCXPRT *xprt;
 
-       ai = svc_create_bindaddr(nconf, port);
+       ai = svc_create_bindaddr(nconf, 0);
        if (ai == NULL)
                return 0;
 
@@ -119,7 +273,7 @@ svc_create_nconf(const char *name, const rpcprog_t program,
        freeaddrinfo(ai);
        if (xprt == NULL) {
                xlog(D_GENERAL, "Failed to create listener xprt "
-                               "(%s, %u, %s)", name, version, nconf->nc_netid);
+                       "(%s, %u, %s)", name, version, nconf->nc_netid);
                return 0;
        }
 
@@ -133,6 +287,93 @@ svc_create_nconf(const char *name, const rpcprog_t program,
        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
@@ -145,8 +386,7 @@ svc_create_nconf(const char *name, const rpcprog_t program,
  * the RPC dispatcher.  Returns the number of started network transports.
  */
 unsigned int
-nfs_svc_create(__attribute__((unused)) char *name,
-               const rpcprog_t program, const rpcvers_t version,
+nfs_svc_create(char *name, const rpcprog_t program, const rpcvers_t version,
                void (*dispatch)(struct svc_req *, SVCXPRT *),
                const uint16_t port)
 {
index f4baeb9f9a0b17fffab66e3bf969755868190077..98b47bf8bd9f0b4dae29861b446d7ab3f137d134 100644 (file)
@@ -126,7 +126,7 @@ exact_error_check(const ssize_t len, const size_t buflen)
  * containing an appropriate pathname, or NULL if an error
  * occurs.  Caller must free the returned result with free(3).
  */
-__attribute_malloc__
+__attribute__((__malloc__))
 static char *
 nsm_make_record_pathname(const char *directory, const char *hostname)
 {
@@ -174,7 +174,7 @@ nsm_make_record_pathname(const char *directory, const char *hostname)
  * containing an appropriate pathname, or NULL if an error
  * occurs.  Caller must free the returned result with free(3).
  */
-__attribute_malloc__
+__attribute__((__malloc__))
 static char *
 nsm_make_pathname(const char *directory)
 {
@@ -204,7 +204,7 @@ nsm_make_pathname(const char *directory)
  * containing an appropriate pathname, or NULL if an error
  * occurs.  Caller must free the returned result with free(3).
  */
-__attribute_malloc__
+__attribute__((__malloc__))
 static char *
 nsm_make_temp_pathname(const char *pathname)
 {
@@ -421,7 +421,7 @@ nsm_drop_privileges(const int pidfd)
         */
         if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) {
                 xlog(L_ERROR, "prctl(PR_SET_KEEPCAPS) failed: %m");
-               return 0;
+               return false;
        }
 
        if (setgroups(0, NULL) == -1) {
@@ -568,9 +568,8 @@ nsm_retire_monitored_hosts(void)
 
        while ((de = readdir(dir)) != NULL) {
                char *src, *dst;
+               struct stat stb;
 
-               if (de->d_type != (unsigned char)DT_REG)
-                       continue;
                if (de->d_name[0] == '.')
                        continue;
 
@@ -580,6 +579,20 @@ nsm_retire_monitored_hosts(void)
                        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);
@@ -634,7 +647,7 @@ nsm_priv_to_hex(const char *priv, char *buf, const size_t buflen)
 /*
  * Returns the length in bytes of the created record.
  */
-__attribute_noinline__
+__attribute__((__noinline__))
 static size_t
 nsm_create_monitor_record(char *buf, const size_t buflen,
                const struct sockaddr *sap, const struct mon *m)
@@ -784,7 +797,7 @@ out:
        return result;
 }
 
-__attribute_noinline__
+__attribute__((__noinline__))
 static _Bool
 nsm_parse_line(char *line, struct sockaddr_in *sin, struct mon *m)
 {
@@ -846,7 +859,7 @@ nsm_read_line(const char *hostname, const time_t timestamp, char *line,
 }
 
 /*
- * Given a filename, reads data from a file under NSM_MONITOR_DIR
+ * Given a filename, reads data from a file under "directory"
  * and invokes @func so caller can populate their in-core
  * database with this data.
  */
@@ -863,10 +876,15 @@ nsm_load_host(const char *directory, const char *filename, nsm_populate_t func)
        if (path == NULL)
                goto out_err;
 
-       if (stat(path, &stb) == -1) {
+       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) {
@@ -913,8 +931,6 @@ nsm_load_dir(const char *directory, nsm_populate_t func)
        }
 
        while ((de = readdir(dir)) != NULL) {
-               if (de->d_type != (unsigned char)DT_REG)
-                       continue;
                if (de->d_name[0] == '.')
                        continue;
 
index 0d1159a8f12ca173d1b679139c501bda1bd5eda8..0fa3422d95dae5077b6c292231b47acc16c8a21c 100644 (file)
@@ -205,7 +205,7 @@ nsm_client_get_rpcclient(const char *node)
 {
        unsigned short          port;
        struct addrinfo         *ai;
-       struct addrinfo         hints = { .ai_flags     = AI_ADDRCONFIG };
+       struct addrinfo         hints = { };
        int                     err;
        CLIENT                  *client = NULL;
 
index 86651833cb57e5cf69a99aa4e1a89c7c86a48c44..a0ea11629a1e6e8bc32a22e7754db1006aff5a69 100644 (file)
@@ -4,6 +4,9 @@ OPTDIRS =
 
 if CONFIG_NFSV4
 OPTDIRS += idmapd
+if CONFIG_NFSIDMAP
+OPTDIRS += nfsidmap
+endif
 endif
 
 if CONFIG_GSS
index b78957f249f44ae6c2226984e241ed6a2eb0fded..b107c7c9e0d856c1f3678cf4faa70879ce79929f 100644 (file)
@@ -25,6 +25,7 @@
 #include <fcntl.h>
 #include <netdb.h>
 #include <errno.h>
+#include <dirent.h>
 
 #include "sockaddr.h"
 #include "misc.h"
@@ -41,6 +42,7 @@ static void   error(nfs_export *exp, int err);
 static void    usage(const char *progname);
 static void    validate_export(nfs_export *exp);
 static int     matchhostname(const char *hostname1, const char *hostname2);
+static void    export_d_read(const char *dname);
 
 int
 main(int argc, char **argv)
@@ -127,8 +129,10 @@ main(int argc, char **argv)
                        return 0;
                }
        }
-       if (f_export && ! f_ignore)
+       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);
@@ -246,7 +250,7 @@ static void
 exportfs(char *arg, char *options, int verbose)
 {
        struct exportent *eep;
-       nfs_export      *exp;
+       nfs_export      *exp = NULL;
        struct addrinfo *ai = NULL;
        char            *path;
        char            *hname = arg;
@@ -485,6 +489,59 @@ out:
        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)
+               xlog(L_NOTICE, "scandir %s: %s\n", 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\n", 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, ...)
 {
index 089f75bd9603679890347c9e8b62b78e8aad88e9..364f247f350a1d6b91aefe14b405039b7007460b 100644 (file)
@@ -37,11 +37,15 @@ 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.
@@ -92,17 +96,24 @@ Specify a list of export options in the same manner as in
 .B -i
 Ignore the
 .I /etc/exports
-file.  Only default options and options given on the command line are used.
+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 .
+.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, and removes any entries from the
+.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
@@ -130,6 +141,8 @@ 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.
@@ -149,7 +162,9 @@ several sources.
 The default export options are
 .BR sync,ro,root_squash,wdelay .
 These can be overridden by entries in
-.IR /etc/exports .
+.IR /etc/exports 
+or files under
+.IR /etc/exports.d .
 .PP
 A system administrator may override options from these sources using the
 .B -o
@@ -188,6 +203,8 @@ 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:
@@ -215,7 +232,9 @@ directory:
 .fi
 .PP
 To unexport all exports listed in
-.IR /etc/exports :
+.IR /etc/exports 
+and files under
+.IR /etc/exports.d :
 .PP
 .nf
 .B "# exportfs -au
@@ -238,6 +257,13 @@ if they themselves are no longer valid they will be removed.
 .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
index c726dd995b5b4bdeec3515b1820c677bf482127c..b202583ddfae72dc5fa82664a3b12162429bed28 100644 (file)
@@ -45,22 +45,11 @@ or restart the NFS server.
 .SS Machine Name Formats
 NFS clients may be specified in a number of ways:
 .IP "single host
-This is the most common format. You may specify a host either by an
+You may specify a host either by an
 abbreviated name recognized be the resolver, the fully qualified domain
-name, or an IP address.
-.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 "wildcards
-Machine names may contain the wildcard characters \fI*\fR and \fI?\fR.
-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.
+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
@@ -69,9 +58,28 @@ as
 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. Wildcard characters generally do not work on IP addresses, though they
+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
@@ -92,6 +100,12 @@ may work by accident when reverse DNS lookups fail.
 '''.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
@@ -145,7 +159,9 @@ storage (see
 .IR async
 above).
 
-In releases of nfs-utils up to and including 1.0.0, this option was the
+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
@@ -375,20 +391,6 @@ 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 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
@@ -456,6 +458,24 @@ 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 under 
+.I /etc/exports.d. 
+directory as extra export tables.
+.B exportfs
+regards only a file which name is ended with 
+.I .exports
+and
+not started with 
+.I . 
+as an extra export file. A file which name
+is not met this condition is just ignored.
+The format for extra export tables is the same as 
+.I /etc/exports
+.
 .IP
 .SH EXAMPLE
 .PP
@@ -468,6 +488,8 @@ is supposedly that of user joe).
 /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
@@ -483,7 +505,9 @@ 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.
+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
@@ -501,6 +525,7 @@ all three mounts with the `sync' option enabled.
 '''entry.
 .SH FILES
 /etc/exports
+/etc/exports.d
 .SH SEE ALSO
 .BR exportfs (8),
 .BR netgroup (5),
index 95a2bd0f8c6cc21247d71549680b04a52f01772e..d7888ad63d2b0bd827c9ca1892bc3dd62b8d92c0 100644 (file)
@@ -51,7 +51,9 @@ svcgssd_SOURCES = \
        svcgssd_main_loop.c \
        svcgssd_mech2file.c \
        svcgssd_proc.c \
+       svcgssd_krb5.c \
        \
+       svcgssd_krb5.h \
        svcgssd.h
 
 svcgssd_LDADD = \
index 8fe1e9be316929f8a29072d576c678eb03352089..0e327b04d87250f6a037670aee825fb8db6887d5 100644 (file)
@@ -138,6 +138,83 @@ display_status_1(char *m, u_int32_t code, int type, const gss_OID mech)
        }
 }
 #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)
@@ -175,8 +252,9 @@ display_status_2(char *m, u_int32_t major, u_int32_t minor, const gss_OID mech)
 
        if (major == GSS_S_CREDENTIALS_EXPIRED)
                msg_verbosity = 1;
-       printerr(msg_verbosity, "ERROR: GSS-API: error in %s(): %s - %s\n",
-                m, maj, min);
+
+       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);
@@ -199,20 +277,25 @@ gssd_acquire_cred(char *server_name, const gss_OID oid)
        u_int32_t ignore_maj_stat, ignore_min_stat;
        gss_buffer_desc pbuf;
 
-       name.value = (void *)server_name;
-       name.length = strlen(server_name);
+       /* 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);
+               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);
+               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, 0,
-                       GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
+       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) {
index 0a23cd6316745926d30d6237e399383564a10c5c..073379d37597103e7d416307e90061d5a043c5c8 100644 (file)
@@ -52,6 +52,8 @@ used only "nfs/*" keys found within the keytab.
 To be more consistent with other implementations, we now look for
 specific keytab entries.  The search order for keytabs to be used
 for "machine credentials" is now:
+.br
+  <HOSTNAME>$@<REALM>
 .br
   root/<hostname>@<REALM>
 .br
@@ -64,6 +66,9 @@ for "machine credentials" is now:
   nfs/<anyname>@<REALM>
 .br
   host/<anyname>@<REALM>
+.IP
+If this search order does not use the correct key then provide a
+keytab file that contains only correct keys.
 .TP
 .B -p path
 Tells
index c301d467d26c88e039570153deb7137bdf979aba..41328c9b18483e8f7f5d9a2edc8eb9bce9465e30 100644 (file)
@@ -1245,7 +1245,7 @@ handle_gssd_upcall(struct clnt_info *clp)
                        goto out;
                if (sscanf(p, "enctypes=%s", enctypes) != 1) {
                        printerr(0, "WARNING: handle_gssd_upcall: "
-                                   "failed to parse target name "
+                                   "failed to parse encryption types "
                                    "in upcall string '%s'\n", lbuf);
                        goto out;
                }
index f071600de4adbfb0667b6cf81f02c892ca9884aa..4b13fa1f5c2ac2e1fd64d2036fe0c6c6ad1a0e63 100644 (file)
@@ -768,6 +768,7 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *hostname,
        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;
@@ -789,6 +790,14 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *hostname,
                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)
+               myhostad[i] = toupper(myhostad[i]);
+       myhostad[i] = '$';
+       myhostad[i+1] = 0;
+
        retval = get_full_hostname(myhostname, myhostname, sizeof(myhostname));
        if (retval)
                goto out;
@@ -833,32 +842,47 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *hostname,
                if (strcmp(realm, default_realm) == 0)
                        tried_default = 1;
                for (j = 0; svcnames[j] != NULL; j++) {
-                       code = krb5_build_principal_ext(context, &princ,
-                                                       strlen(realm),
-                                                       realm,
-                                                       strlen(svcnames[j]),
-                                                       svcnames[j],
-                                                       strlen(myhostname),
-                                                       myhostname,
-                                                       NULL);
+                       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 {
+                               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/%s@%s'\n", k5err, svcnames[j],
-                                        myhostname, realm);
+                               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/%s@%s'\n", k5err, svcnames[j],
-                                        myhostname, realm);
+                               printerr(3, "%s while getting keytab entry for '%s'\n",
+                                        k5err, spn);
                        } else {
-                               printerr(3, "Success getting keytab entry for "
-                                        "'%s/%s@%s'\n",
-                                        svcnames[j], myhostname, realm);
+                               printerr(3, "Success getting keytab entry for '%s'\n",spn);
                                retval = 0;
                                goto out;
                        }
@@ -870,6 +894,8 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *hostname,
                 */
                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) {
@@ -1160,7 +1186,7 @@ gssd_refresh_krb5_machine_credential(char *hostname,
        krb5_keytab kt = NULL;;
        int retval = 0;
        char *k5err = NULL;
-       const char *svcnames[4] = { "root", "nfs", "host", NULL };
+       const char *svcnames[5] = { "$", "root", "nfs", "host", NULL };
 
        /*
         * If a specific service name was specified, use it.
index 9b463f3723ab066a228e62a24cd45313798c6440..1afff9e5a4935c3a9be76b4ccaf2d02f3463e74c 100644 (file)
@@ -262,11 +262,19 @@ main(int argc, char *argv[])
                                "/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();
 
+       nfs4_init_name_mapping(NULL); /* XXX: should only do this once */
        gssd_run();
        printerr(0, "gssd_run returned!\n");
        abort();
index 1c7bb32bf564e98d9d8e354bd513f6520391d7c2..7b2de6b1ab91a7261823dfe496c5ffc9446cf380 100644 (file)
@@ -6,7 +6,7 @@
 .SH NAME
 rpc.svcgssd \- server-side rpcsec_gss daemon
 .SH SYNOPSIS
-.B "rpc.svcgssd [-v] [-r] [-i] [-f] [-p principal]"
+.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
@@ -37,7 +37,14 @@ 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 nfs/host.domain.
+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
diff --git a/utils/gssd/svcgssd_krb5.c b/utils/gssd/svcgssd_krb5.c
new file mode 100644 (file)
index 0000000..fc67a6f
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * 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 <gssapi/gssapi.h>
+#include <krb5.h>
+
+#include "gss_util.h"
+#include "gss_oids.h"
+#include "err_util.h"
+#include "svcgssd_krb5.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;
+
+       /* 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 default_enctypes[] = { ENCTYPE_DES_CBC_CRC,
+                                           ENCTYPE_DES_CBC_MD5,
+                                           ENCTYPE_DES_CBC_MD4 };
+       int default_num_enctypes =
+               sizeof(default_enctypes) / sizeof(default_enctypes[0]);
+       krb5_enctype *enctypes;
+       int num_enctypes;
+
+       get_kernel_supported_enctypes();
+
+       if (parsed_enctypes != NULL) {
+               enctypes = parsed_enctypes;
+               num_enctypes = parsed_num_enctypes;
+       } else {
+               enctypes = default_enctypes;
+               num_enctypes = default_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/utils/gssd/svcgssd_krb5.h b/utils/gssd/svcgssd_krb5.h
new file mode 100644 (file)
index 0000000..07d5eb9
--- /dev/null
@@ -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 */
index 3894078e81568e4f78d0a18bef8cb5e2e7528191..c714d99dd654aaff3b3369bebcbc0df0946284dd 100644 (file)
@@ -56,7 +56,9 @@
 #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"
@@ -70,6 +72,7 @@ struct svc_cred {
        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,
@@ -91,6 +94,7 @@ do_svc_downcall(gss_buffer_desc *out_handle, struct svc_cred *cred,
                             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 */
@@ -241,7 +245,7 @@ get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred)
                        "file for name '%s'\n", sname);
                goto out_free;
        }
-       nfs4_init_name_mapping(NULL); /* XXX: should only do this once */
+
        res = nfs4_gss_princ_to_ids(secname, sname, &uid, &gid);
        if (res < 0) {
                /*
@@ -443,6 +447,10 @@ handle_nullreq(FILE *f) {
                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);
index 421804883383736dcfb5c3e5986193df2d779ecd..4328e4183b2d0e9eb7da337f5016e42ba273feb7 100644 (file)
@@ -11,12 +11,8 @@ EXTRA_DIST = \
        idmapd.conf
 
 idmapd_SOURCES = \
-       atomicio.c \
        idmapd.c \
-       strlcat.c \
-       strlcpy.c \
        \
-       cfg.h \
        nfs_idmap.h \
        queue.h
 
diff --git a/utils/idmapd/atomicio.c b/utils/idmapd/atomicio.c
deleted file mode 100644 (file)
index 1fb1ff9..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif /* HAVE_CONFIG_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;
-       size_t pos = 0;
-
-       while (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);
-}
index b76607a4d8fa437eea010e8638bc3c31f2b93778..76a56ef6b58f7a8f0d5efa8c7f2f6350f81e3a14 100644 (file)
@@ -158,10 +158,6 @@ static int nfsdopenone(struct idmap_client *);
 static void nfsdreopen_one(struct idmap_client *);
 static void nfsdreopen(void);
 
-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);
 void    mydaemon(int, int);
 void    release_parent(void);
 
diff --git a/utils/idmapd/strlcat.c b/utils/idmapd/strlcat.c
deleted file mode 100644 (file)
index daedd7a..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*     $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/utils/idmapd/strlcpy.c b/utils/idmapd/strlcpy.c
deleted file mode 100644 (file)
index a2653ee..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*     $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 */
-}
index 299384a3aef1b73eef63971f0baad6070ddfc16c..7bc3e2bf5b00731289905b229dfc258612c95159 100644 (file)
@@ -9,17 +9,16 @@ man5_MANS     = nfs.man
 
 sbin_PROGRAMS  = mount.nfs
 EXTRA_DIST = nfsmount.x $(man8_MANS) $(man5_MANS)
-mount_nfs_SOURCES = mount.c error.c network.c fstab.c token.c \
+mount_common = error.c network.c token.c \
                    parse_opt.c parse_dev.c \
                    nfsmount.c nfs4mount.c stropts.c\
-                   nfsumount.c \
-                   mount_constants.h error.h network.h fstab.h token.h \
+                   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
+                   mount_config.h utils.c utils.h
 
 if MOUNT_CONFIG
-mount_nfs_SOURCES += configfile.c
+mount_common += configfile.c
 man5_MANS += nfsmount.conf.man
 EXTRA_DIST += nfsmount.conf
 endif
@@ -27,6 +26,16 @@ endif
 mount_nfs_LDADD = ../../support/nfs/libnfs.a \
                  ../../support/export/libexport.a
 
+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:
index 051fa38c872503e37dfaca9e5c89c4ec4f2f7738..1fc9efe8e24410152c171b5a279c6cbb077565fb 100644 (file)
@@ -331,16 +331,43 @@ lock_mtab (void) {
                int sig = 0;
                struct sigaction sa;
 
-               sa.sa_handler = handler;
                sa.sa_flags = 0;
                sigfillset (&sa.sa_mask);
   
-               while (sigismember (&sa.sa_mask, ++sig) != -1
-                      && sig != SIGCHLD) {
-                       if (sig == SIGALRM)
+               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;
-                       else
+                               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;
@@ -364,19 +391,22 @@ lock_mtab (void) {
        /* Repeat until it was us who made the link */
        while (!we_created_lockfile) {
                struct flock flock;
-               int errsv, j;
+               int j;
 
                j = link(linktargetfile, MOUNTED_LOCK);
-               errsv = errno;
 
-               if (j == 0)
-                       we_created_lockfile = 1;
+               {
+                       int errsv = errno;
 
-               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));
+                       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);
@@ -414,7 +444,7 @@ lock_mtab (void) {
                        }
                        (void) unlink(linktargetfile);
                } else {
-                       static int tries = 0;
+                       static int retries = 0;
 
                        /* Someone else made the link. Wait. */
                        alarm(LOCK_TIMEOUT);
@@ -428,10 +458,10 @@ lock_mtab (void) {
                        alarm(0);
                        /* Limit the number of iterations - maybe there
                           still is some old /etc/mtab~ */
-                       ++tries;
-                       if (tries % 200 == 0)
+                       ++retries;
+                       if (retries % 200 == 0)
                           usleep(30);
-                       if (tries > 100000) {
+                       if (retries > 100000) {
                                (void) unlink(linktargetfile);
                                close(lockfile_fd);
                                die (EX_FILEIO, _("Cannot create link %s\n"
index 82b9169a10462dad5f1efbdb55596878f17db10f..eea00afe2679f28e3e4f10ea11c0553f5f51f712 100644 (file)
@@ -47,7 +47,7 @@
 #include "mount.h"
 #include "error.h"
 #include "stropts.h"
-#include "version.h"
+#include "utils.h"
 
 char *progname;
 int nfs_mount_data_version;
@@ -149,49 +149,6 @@ static const struct opt_map opt_map[] = {
 
 static void parse_opts(const char *options, int *flags, char **extra_opts);
 
-/*
- * 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
- */
-static void discover_nfs_mount_data_version(void)
-{
-       unsigned int kernel_version = linux_version_code();
-
-       if (kernel_version) {
-               if (kernel_version < MAKE_VERSION(2, 1, 32))
-                       nfs_mount_data_version = 1;
-               else if (kernel_version < MAKE_VERSION(2, 2, 18))
-                       nfs_mount_data_version = 3;
-               else if (kernel_version < MAKE_VERSION(2, 3, 0))
-                       nfs_mount_data_version = 4;
-               else if (kernel_version < MAKE_VERSION(2, 3, 99))
-                       nfs_mount_data_version = 3;
-               else if (kernel_version < MAKE_VERSION(2, 6, 3))
-                       nfs_mount_data_version = 4;
-               else
-                       nfs_mount_data_version = 6;
-       }
-       if (nfs_mount_data_version > NFS_MOUNT_VERSION)
-               nfs_mount_data_version = NFS_MOUNT_VERSION;
-       else
-               if (kernel_version > MAKE_VERSION(2, 6, 22))
-                       string++;
-}
-
-static 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);
-}
-
 /*
  * Build a canonical mount option string for /etc/mtab.
  */
@@ -209,7 +166,7 @@ static char *fix_opts_string(int flags, const char *extra_opts)
        }
        if (flags & MS_USERS)
                new_opts = xstrconcat3(new_opts, ",users", "");
-       
+
        for (om = opt_map; om->opt != NULL; om++) {
                if (om->skip)
                        continue;
@@ -224,6 +181,20 @@ static char *fix_opts_string(int flags, const char *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) {
@@ -245,11 +216,8 @@ create_mtab (void) {
        if ((fstab = getfsfile ("/")) || (fstab = getfsfile ("root"))) {
                char *extra_opts;
                parse_opts (fstab->m.mnt_opts, &flags, &extra_opts);
-               mnt.mnt_dir = "/";
-               mnt.mnt_fsname = xstrdup(fstab->m.mnt_fsname);
-               mnt.mnt_type = fstab->m.mnt_type;
-               mnt.mnt_opts = fix_opts_string (flags, extra_opts);
-               mnt.mnt_freq = mnt.mnt_passno = 0;
+               init_mntent(&mnt, xstrdup(fstab->m.mnt_fsname), "/",
+                               fstab->m.mnt_type, flags, extra_opts);
                free(extra_opts);
 
                if (nfs_addmntent (mfp, &mnt) == 1) {
@@ -273,17 +241,12 @@ create_mtab (void) {
 }
 
 static int add_mtab(char *spec, char *mount_point, char *fstype,
-                       int flags, char *opts, int freq, int pass)
+                       int flags, char *opts)
 {
        struct mntent ment;
        int result = EX_SUCCESS;
 
-       ment.mnt_fsname = spec;
-       ment.mnt_dir = mount_point;
-       ment.mnt_type = fstype;
-       ment.mnt_opts = fix_opts_string(flags, opts);
-       ment.mnt_freq = freq;
-       ment.mnt_passno = pass;
+       init_mntent(&ment, spec, mount_point, fstype, flags, opts);
 
        if (!nomtab && mtab_does_not_exist()) {
                if (verbose > 1)
@@ -321,23 +284,7 @@ static int add_mtab(char *spec, char *mount_point, char *fstype,
        return result;
 }
 
-void mount_usage(void)
-{
-       printf(_("usage: %s remotetarget dir [-rvVwfnsih] [-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"));
-}
-
-static void parse_opt(const char *opt, int *mask, char *extra_opts, int len)
+static void parse_opt(const char *opt, int *mask, char *extra_opts, size_t len)
 {
        const struct opt_map *om;
 
@@ -371,7 +318,7 @@ static void parse_opts(const char *options, int *flags, char **extra_opts)
        if (options != NULL) {
                char *opts = xstrdup(options);
                char *opt, *p;
-               int len = strlen(opts) + 1;     /* include room for a null */
+               size_t len = strlen(opts) + 1;  /* include room for a null */
                int open_quote = 0;
 
                *extra_opts = xmalloc(len);
@@ -397,26 +344,6 @@ static void parse_opts(const char *options, int *flags, char **extra_opts)
        }
 }
 
-static int chk_mountpoint(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 (access(mount_point, X_OK) < 0) {
-               mount_error(NULL, mount_point, errno);
-               return 1;
-       }
-
-       return 0;
-}
-
 static int try_mount(char *spec, char *mount_point, int flags,
                        char *fs_type, char **extra_opts, char *mount_opts,
                        int fake, int bg)
@@ -441,45 +368,31 @@ static int try_mount(char *spec, char *mount_point, int flags,
        if (!fake)
                print_one(spec, mount_point, fs_type, mount_opts);
 
-       ret = add_mtab(spec, mount_point, fs_type, flags, *extra_opts,
-                       0, 0 /* these are always zero for NFS */ );
-       return ret;
+       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, *mount_point, *fs_type = "nfs";
+       char *spec = NULL, *mount_point = NULL, *fs_type = "nfs";
        char *extra_opts = NULL, *mount_opts = NULL;
        uid_t uid = getuid();
 
        progname = basename(argv[0]);
 
-       discover_nfs_mount_data_version();
+       nfs_mount_data_version = discover_nfs_mount_data_version(&string);
 
        if(!strncmp(progname, "umount", strlen("umount")))
                exit(nfsumount(argc, argv));
 
-       if (argv[1] && argv[1][0] == '-') {
-               if(argv[1][1] == 'V')
-                       printf("%s ("PACKAGE_STRING")\n", progname);
-               else
-                       mount_usage();
-               exit(EX_SUCCESS);
-       }
-
        if ((argc < 3)) {
                mount_usage();
                exit(EX_USAGE);
        }
 
-       spec = argv[1];
-       mount_point = argv[2];
-
        mount_config_init(progname);
 
-       argv[2] = argv[0]; /* so that getopt error messages are correct */
-       while ((c = getopt_long(argc - 2, argv + 2, "rvVwfno:hs",
+       while ((c = getopt_long(argc, argv, "rvVwfno:hs",
                                longopts, NULL)) != -1) {
                switch (c) {
                case 'r':
@@ -522,6 +435,14 @@ int main(int argc, char *argv[])
        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)
index 3023306e5446248b2e00047a222400903aaad58e..69ffd1ef7927762f2d694e889cfa72486193ae69 100644 (file)
@@ -1,7 +1,7 @@
-#ifndef _LINUX_MOUNT__CONFIG_H
-#define _LINUX_MOUNT_CONFIG__H
+#ifndef _LINUX_MOUNT_CONFIG_H
+#define _LINUX_MOUNT_CONFIG_H
 /*
- * mount_config.h -- mount configuration file routines 
+ * 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
  *
  */
 
-inline void mount_config_init(char *);
-
 #ifdef MOUNT_CONFIG
 #include "conffile.h"
 #include "xlog.h"
 
 extern char *conf_get_mntopts(char *, char *, char *);
 
-inline void mount_config_init(char *program)
+static inline void mount_config_init(char *program)
 {
        xlog_open(program);
        /*
@@ -32,19 +30,22 @@ inline void mount_config_init(char *program)
         */
        conf_init();
 }
-inline char *mount_config_opts(char *spec, 
+
+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 */
 
-inline void mount_config_init(char *program) { }
+static inline void mount_config_init(__attribute__ ((unused)) char *program) { }
 
-inline char *mount_config_opts(char *spec, 
-               char *mount_point, char *mount_opts)
+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
+
+#endif /* _LINUX_MOUNT_CONFIG_H */
index cbfb099df99a0458fcd12ff0d180573a78814bdf..4d050d8819e4953a8f79c69c2a3a245ce70c2b5f 100644 (file)
@@ -64,4 +64,8 @@ if we have a stack or plain mount - mount atop of it, forming a stack. */
 #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/utils/mount/mount_libmount.c b/utils/mount/mount_libmount.c
new file mode 100644 (file)
index 0000000..6dd6484
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, 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 *opts)
+{
+       mnt_fs_set_fs_options(fs, opts);        /* for mtab */
+       mnt_fs_set_attributes(fs, opts);        /* for non-mtab systems */
+}
+
+/*
+ * 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 = 0 , unknown = 1 */
+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 = 1;
+
+       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 = 0;
+       }
+       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;
+
+       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;
+       if (mnt_context_set_fstype_pattern(cxt, "nfs,nfs4"))    /* restrict filesystems */
+               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;
+       }
+
+       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");
+       }
+
+       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;
+       }
+
+       free(opts);
+       return EX_SUCCESS;
+err:
+       free(opts);
+       return EX_FAIL;
+}
+
+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;
+       /*
+        * 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;
+}
index d61242798f6a7153472cb132fb54927a602cb4d1..d1f91dc0b32c9c501d9253cbe6a576363f7e00f0 100644 (file)
@@ -59,6 +59,8 @@
 #define CONNECT_TIMEOUT        (20)
 #define MOUNT_TIMEOUT  (30)
 
+#define SAFE_SOCKADDR(x)       (struct sockaddr *)(char *)(x)
+
 extern int nfs_mount_data_version;
 extern char *progname;
 extern int verbose;
@@ -208,9 +210,6 @@ int nfs_lookup(const char *hostname, const sa_family_t family,
 {
        struct addrinfo *gai_results;
        struct addrinfo gai_hint = {
-#ifdef HAVE_DECL_AI_ADDRCONFIG
-               .ai_flags       = AI_ADDRCONFIG,
-#endif /* HAVE_DECL_AI_ADDRCONFIG */
                .ai_family      = family,
        };
        socklen_t len = *salen;
@@ -428,12 +427,12 @@ static int get_socket(struct sockaddr_in *saddr, unsigned int p_prot,
                if (bindresvport(so, &laddr) < 0)
                        goto err_bindresvport;
        } else {
-               cc = bind(so, (struct sockaddr *)&laddr, namelen);
+               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, (struct sockaddr *)saddr, namelen,
+               cc = connect_to(so, SAFE_SOCKADDR(saddr), namelen,
                                timeout);
                if (cc < 0)
                        goto err_connect;
@@ -756,11 +755,12 @@ int nfs_probe_bothports(const struct sockaddr *mnt_saddr,
  */
 int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
 {
-       return nfs_probe_bothports((struct sockaddr *)&mnt_server->saddr,
-                                       sizeof(mnt_server->saddr),
+       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,
-                                       (struct sockaddr *)&nfs_server->saddr,
-                                       sizeof(nfs_server->saddr),
+                                       nfs_addr, sizeof(nfs_server->saddr),
                                        &nfs_server->pmap);
 }
 
@@ -772,7 +772,7 @@ static int nfs_probe_statd(void)
        };
        rpcprog_t program = nfs_getrpcbyname(NSMPROG, nfs_ns_pgmtbl);
 
-       return nfs_getport_ping((struct sockaddr *)&addr, sizeof(addr),
+       return nfs_getport_ping(SAFE_SOCKADDR(&addr), sizeof(addr),
                                program, (rpcvers_t)1, IPPROTO_UDP);
 }
 
@@ -901,7 +901,7 @@ int nfs_advise_umount(const struct sockaddr *sap, const socklen_t salen,
  */
 int nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp)
 {
-       struct sockaddr *sap = (struct sockaddr *)&mnt_server->saddr;
+       struct sockaddr *sap = SAFE_SOCKADDR(&mnt_server->saddr);
        socklen_t salen = sizeof(mnt_server->saddr);
        struct pmap *pmap = &mnt_server->pmap;
        CLIENT *clnt;
@@ -1011,11 +1011,11 @@ int clnt_ping(struct sockaddr_in *saddr, const unsigned long prog,
                struct sockaddr_in *caddr)
 {
        CLIENT *clnt = NULL;
-       int sock, stat;
+       int sock, status;
        static char clnt_res;
        struct sockaddr dissolve;
 
-       rpc_createerr.cf_stat = stat = 0;
+       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) {
@@ -1058,18 +1058,18 @@ int clnt_ping(struct sockaddr_in *saddr, const unsigned long prog,
                return 0;
        }
        memset(&clnt_res, 0, sizeof(clnt_res));
-       stat = clnt_call(clnt, NULLPROC,
+       status = clnt_call(clnt, NULLPROC,
                         (xdrproc_t)xdr_void, (caddr_t)NULL,
                         (xdrproc_t)xdr_void, (caddr_t)&clnt_res,
                         TIMEOUT);
-       if (stat) {
+       if (status) {
                clnt_geterr(clnt, &rpc_createerr.cf_error);
-               rpc_createerr.cf_stat = stat;
+               rpc_createerr.cf_stat = status;
        }
        clnt_destroy(clnt);
        close(sock);
 
-       if (stat == RPC_SUCCESS)
+       if (status == RPC_SUCCESS)
                return 1;
        else
                return 0;
@@ -1095,7 +1095,7 @@ static int nfs_ca_sockname(const struct sockaddr *sap, const socklen_t salen,
                .sin6_family            = AF_INET6,
                .sin6_addr              = IN6ADDR_ANY_INIT,
        };
-       int sock;
+       int sock, result = 0;
 
        sock = socket(sap->sa_family, SOCK_DGRAM, IPPROTO_UDP);
        if (sock < 0)
@@ -1103,28 +1103,26 @@ static int nfs_ca_sockname(const struct sockaddr *sap, const socklen_t salen,
 
        switch (sap->sa_family) {
        case AF_INET:
-               if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
-                       close(sock);
-                       return 0;
-               }
+               if (bind(sock, SAFE_SOCKADDR(&sin), sizeof(sin)) < 0)
+                       goto out;
                break;
        case AF_INET6:
-               if (bind(sock, (struct sockaddr *)&sin6, sizeof(sin6)) < 0) {
-                       close(sock);
-                       return 0;
-               }
+               if (bind(sock, SAFE_SOCKADDR(&sin6), sizeof(sin6)) < 0)
+                       goto out;
                break;
        default:
                errno = EAFNOSUPPORT;
-               return 0;
+               goto out;
        }
 
-       if (connect(sock, sap, salen) < 0) {
-               close(sock);
-               return 0;
-       }
+       if (connect(sock, sap, salen) < 0)
+               goto out;
 
-       return !getsockname(sock, buf, buflen);
+       result = !getsockname(sock, buf, buflen);
+
+out:
+       close(sock);
+       return result;
 }
 
 /*
@@ -1346,7 +1344,7 @@ nfs_nfs_port(struct mount_options *options, unsigned long *port)
        case PO_NOT_FOUND:
                break;
        case PO_FOUND:
-               if (tmp >= 1 && tmp <= 65535) {
+               if (tmp >= 0 && tmp <= 65535) {
                        *port = tmp;
                        return 1;
                }
@@ -1518,7 +1516,11 @@ nfs_mount_protocol(struct mount_options *options, unsigned long *protocol)
         * set @protocol to zero.  The pmap protocol value will
         * be filled in later by an rpcbind query in this case.
         */
-       return nfs_nfs_protocol(options, protocol);
+       if (!nfs_nfs_protocol(options, protocol))
+               return 0;
+       if (*protocol == NFSPROTO_RDMA)
+               *protocol = IPPROTO_TCP;
+       return 1;
 }
 
 /*
@@ -1534,7 +1536,7 @@ nfs_mount_port(struct mount_options *options, unsigned long *port)
        case PO_NOT_FOUND:
                break;
        case PO_FOUND:
-               if (tmp >= 1 && tmp <= 65535) {
+               if (tmp >= 0 && tmp <= 65535) {
                        *port = tmp;
                        return 1;
                }
@@ -1622,3 +1624,71 @@ int nfs_options2pmap(struct mount_options *options,
 
        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;
+}
index 2a3a1105498df483adbd5722ae226e32763fb1dd..81c6f22590eba3e39f152deb79293bc5b705992e 100644 (file)
@@ -75,4 +75,7 @@ int nfs_advise_umount(const struct sockaddr *, const socklen_t,
 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 */
index 55d4b553b480bd4c4859c4815c99d4d3cbb3a1b9..be91a252150c37dda50610abcff10c7de70d17c4 100644 (file)
@@ -69,10 +69,9 @@ for details on specifying raw IPv6 addresses.
 .P
 The
 .I fstype
-field contains "nfs", for whatever version of the protocol.
-The
-.B nfs
-allow several mount options, which are described below.
+field contains "nfs".  Use of the "nfs4" fstype in
+.I /etc/fstab
+is deprecated.
 .SH "MOUNT OPTIONS"
 Refer to
 .BR mount (8)
@@ -464,9 +463,9 @@ 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.
-.SS "Options for versions 2 and 3 only"
+.SS "Options for NFS versions 2 and 3 only"
 Use these options, along with the options in the above subsection,
-for NFSv2/v3 only. They will be ignored for newer versions.
+for NFS versions 2 and 3 only.
 .TP 1.5i
 .BI proto= netid
 The transport protocol name and protocol family the NFS client uses
@@ -619,7 +618,7 @@ in such cases.
 .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 negociate a suitable version with
+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
@@ -717,9 +716,53 @@ If this option is not specified, the NFS client uses READDIRPLUS requests
 on NFS version 3 mounts to read small directories.
 Some applications perform better if the client uses only READDIR requests
 for all directories.
-.SS "Options for version 4 only"
+.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 NFSv4 only. They will be ignored with older versions.
+for NFS version 4 and newer.
 .TP 1.5i
 .BI proto= netid
 The transport protocol name and protocol family the NFS client uses
@@ -1480,32 +1523,54 @@ 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 FILES
-.TP 1.5i
-.I /etc/fstab
-file system table
-.SH BUGS
-The generic
-.B remount
-option is not fully supported.
-Generic options, such as
-.BR rw " and " ro
-can be modified using the
-.B remount
-option,
-but NFS-specific options are not all supported.
+.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 mixture of a generic option,
+option is a combination of the generic option
 .BR sync ,
-and an NFS-specific option
+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 2.5i
+       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
index 151434050d68641e189b6877174dceb50b215f4c..8cd28528b1a01d4c4b86b3306189088b6a927d2a 100644 (file)
 #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 */
@@ -109,7 +114,7 @@ static int del_mtab(const char *spec, const char *node)
                        res = try_remount(spec, node);
                        if (res)
                                goto writemtab;
-                       return 0;
+                       return EX_SUCCESS;
                } else
                        umnt_err = errno;
        }
@@ -127,7 +132,7 @@ static int del_mtab(const char *spec, const char *node)
        }
 
        if (res >= 0)
-               return 0;
+               return EX_SUCCESS;
 
        if (umnt_err)
                umount_error(umnt_err, node);
@@ -135,110 +140,88 @@ static int del_mtab(const char *spec, const char *node)
 }
 
 /*
- * 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.
- */
-static int nfs_umount_do_umnt(struct mount_options *options,
-                             char **hostname, char **dirname)
-{
-       union {
-               struct sockaddr         sa;
-               struct sockaddr_in      s4;
-               struct sockaddr_in6     s6;
-       } 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;
-}
-
-/*
- * 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.
+ * Detect NFSv4 mounts.
  *
- * 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.
+ * Consult /proc/mounts to determine if the mount point
+ * is an NFSv4 mount.  The kernel is authoritative about
+ * what type of mount this is.
  *
- * 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.
+ * Returns 1 if "mc" is an NFSv4 mount, zero if not, and
+ * -1 if some error occurred.
  */
-static int nfs_umount23(const char *devname, char *string)
+static int nfs_umount_is_vers4(const struct mntentchn *mc)
 {
-       char *hostname, *dirname;
-       struct mount_options *options;
-       int result = EX_FAIL;
+       char buffer[LINELEN], *next;
+       int retval;
+       FILE *f;
+
+       if ((f = fopen(MOUNTSFILE, "r")) == NULL) {
+               fprintf(stderr, "%s: %s\n",
+                       MOUNTSFILE, strerror(errno));
+               return -1;
+       }
 
-       if (!nfs_parse_devname(devname, &hostname, &dirname))
-               return EX_USAGE;
+       retval = -1;
+       while (fgets(buffer, sizeof(buffer), f) != NULL) {
+               char *device, *mntdir, *type, *flags;
+               struct mount_options *options;
+               char *line = buffer;
+
+               next = strchr(line, '\n');
+               if (next != NULL)
+                       *next = '\0';
+
+               device = strtok(line, " \t");
+               if (device == NULL)
+                       continue;
+               mntdir = strtok(NULL, " \t");
+               if (mntdir == NULL)
+                       continue;
+               if (strcmp(device, mc->m.mnt_fsname) != 0 &&
+                   strcmp(mntdir, mc->m.mnt_dir) != 0)
+                       continue;
+
+               type = strtok(NULL, " \t");
+               if (type == NULL)
+                       continue;
+               if (strcmp(type, "nfs4") == 0)
+                       goto out_nfs4;
+
+               flags = strtok(NULL, " \t");
+               if (flags == NULL)
+                       continue;
+               options = po_split(flags);
+               if (options != NULL) {
+                       unsigned long version;
+                       int rc;
+
+                       rc = nfs_nfs_version(options, &version);
+                       po_destroy(options);
+                       if (rc && version == 4)
+                               goto out_nfs4;
+               }
 
-       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);
+               goto out_nfs;
+       }
+       if (retval == -1)
+               fprintf(stderr, "%s was not found in %s\n",
+                       mc->m.mnt_dir, MOUNTSFILE);
 
-       free(hostname);
-       free(dirname);
-       return result;
+out:
+       fclose(f);
+       return retval;
+
+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;
+       goto out;
 }
 
 static struct option umount_longopts[] =
@@ -251,17 +234,6 @@ static struct option umount_longopts[] =
   { NULL, 0, 0, 0 }
 };
 
-static 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 nfsumount(int argc, char *argv[])
 {
        int c, ret;
@@ -362,16 +334,25 @@ int nfsumount(int argc, char *argv[])
                }
        }
 
-       ret = 0;
+       ret = EX_SUCCESS;
        if (mc) {
-               if (!lazy && strcmp(mc->m.mnt_type, "nfs4") != 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);
-               ret = del_mtab(mc->m.mnt_fsname, mc->m.mnt_dir) ?: ret;
+               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");
index f0918f7fe264063caa59c23ad438bff2b2720693..ab869d901d12ba66d0b26b1ac46a23e0d5d90f4e 100644 (file)
@@ -508,7 +508,7 @@ po_found_t po_get_numeric(struct mount_options *options, char *keyword, long *va
 int po_rightmost(struct mount_options *options, const char *keys[])
 {
        struct mount_option *option;
-       unsigned int i;
+       int i;
 
        if (options) {
                for (option = options->tail; option; option = option->prev) {
index 50a1a2a06626a72ba2c09fe656df3331e66a85b1..f1aa5030062e2cb7bee232d6f14ea880ace688b0 100644 (file)
 #include "parse_dev.h"
 #include "conffile.h"
 
-#ifndef HAVE_DECL_AI_ADDRCONFIG
-#define AI_ADDRCONFIG  0
-#endif
-
 #ifndef NFS_PROGRAM
 #define NFS_PROGRAM    (100003)
 #endif
@@ -114,7 +110,7 @@ static void nfs_default_version(struct nfsmount_info *mi)
        }
 }
 #else
-inline void nfs_default_version(struct nfsmount_info *mi) {}
+inline void nfs_default_version(__attribute__ ((unused)) struct nfsmount_info *mi) {}
 #endif /* MOUNT_CONFIG */
 
 /*
@@ -123,10 +119,12 @@ inline void nfs_default_version(struct nfsmount_info *mi) {}
  * Returns a time_t timeout timestamp, in seconds.
  */
 static time_t nfs_parse_retry_option(struct mount_options *options,
-                                    unsigned int timeout_minutes)
+                                    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;
@@ -135,6 +133,7 @@ static time_t nfs_parse_retry_option(struct mount_options *options,
                        timeout_minutes = tmp;
                        break;
                }
+               /*FALLTHROUGH*/
        case PO_BAD_VALUE:
                if (verbose)
                        nfs_error(_("%s: invalid retry timeout was specified; "
@@ -142,7 +141,7 @@ static time_t nfs_parse_retry_option(struct mount_options *options,
                break;
        }
 
-       return time(NULL) + (time_t)(timeout_minutes * 60);
+       return time(NULL) + (timeout_minutes * 60);
 }
 
 /*
@@ -343,7 +342,6 @@ static int nfs_validate_options(struct nfsmount_info *mi)
 {
        struct addrinfo hint = {
                .ai_protocol    = (int)IPPROTO_UDP,
-               .ai_flags       = AI_ADDRCONFIG,
        };
        sa_family_t family;
        int error;
@@ -570,16 +568,18 @@ 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;
        }
 
-       if (mi->fake)
-               return 1;
-
        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));
@@ -650,7 +650,7 @@ out_fail:
 static int nfs_try_mount_v3v2(struct nfsmount_info *mi)
 {
        struct addrinfo *ai;
-       int ret;
+       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);
@@ -737,7 +737,7 @@ out_fail:
 static int nfs_try_mount_v4(struct nfsmount_info *mi)
 {
        struct addrinfo *ai;
-       int ret;
+       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);
diff --git a/utils/mount/utils.c b/utils/mount/utils.c
new file mode 100644 (file)
index 0000000..298db39
--- /dev/null
@@ -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., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, 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 [-rvVwfnsih] [-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 (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/utils/mount/utils.h b/utils/mount/utils.h
new file mode 100644 (file)
index 0000000..3fcd504
--- /dev/null
@@ -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., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, 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 */
index 46552a1775be5682b602a85e30f3d25823d118dd..af61a6f3295996b8d7f160e25fb8e134bbae8751 100644 (file)
@@ -42,9 +42,9 @@ static inline unsigned int linux_version_code(void)
        if (uname(&my_utsname))
                return 0;
 
-       p = atoi(strtok(my_utsname.release, "."));
-       q = atoi(strtok(NULL, "."));
-       r = atoi(strtok(NULL, "."));
+       p = (unsigned int)atoi(strtok(my_utsname.release, "."));
+       q = (unsigned int)atoi(strtok(NULL, "."));
+       r = (unsigned int)atoi(strtok(NULL, "."));
        return MAKE_VERSION(p, q, r);
 }
 
index f70f4d6e81a7e1ee7b57061f34b7d1c6d68ba162..d2ae4563d31a1ebe855e34053ac99cda6c56cc09 100644 (file)
@@ -64,6 +64,7 @@ enum nfsd_fsid {
  */
 static int cache_export_ent(char *domain, struct exportent *exp, char *p);
 
+#define INITIAL_MANAGED_GROUPS 100
 
 char *lbuf  = NULL;
 int lbuflen = 0;
@@ -114,7 +115,7 @@ static void auth_unix_ip(FILE *f)
 
        qword_print(f, "nfsd");
        qword_print(f, ipaddr);
-       qword_printint(f, time(0)+30*60);
+       qword_printuint(f, time(0) + DEFAULT_TTL);
        if (use_ipaddr)
                qword_print(f, ipaddr);
        else if (client)
@@ -134,11 +135,23 @@ static void auth_unix_gid(FILE *f)
         */
        uid_t uid;
        struct passwd *pw;
-       gid_t glist[100], *groups = glist;
-       int ngroups = 100;
+       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;
 
@@ -151,17 +164,20 @@ static void auth_unix_gid(FILE *f)
                rv = -1;
        else {
                rv = getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
-               if (rv == -1 && ngroups >= 100) {
-                       groups = malloc(sizeof(gid_t)*ngroups);
-                       if (!groups)
+               if (rv == -1 && ngroups >= groups_len) {
+                       more_groups = realloc(groups, sizeof(gid_t)*ngroups);
+                       if (!more_groups)
                                rv = -1;
-                       else
+                       else {
+                               groups = more_groups;
+                               groups_len = ngroups;
                                rv = getgrouplist(pw->pw_name, pw->pw_gid,
                                                  groups, &ngroups);
+                       }
                }
        }
        qword_printuint(f, uid);
-       qword_printuint(f, time(0)+30*60);
+       qword_printuint(f, time(0) + DEFAULT_TTL);
        if (rv >= 0) {
                qword_printuint(f, ngroups);
                for (i=0; i<ngroups; i++)
@@ -169,9 +185,6 @@ static void auth_unix_gid(FILE *f)
        } else
                qword_printuint(f, 0);
        qword_eol(f);
-
-       if (groups != glist)
-               free(groups);
 }
 
 #if USE_BLKID
@@ -328,63 +341,49 @@ static char *next_mnt(void **v, char *p)
        return me->mnt_dir;
 }
 
-static void nfsd_fh(FILE *f)
+/* True iff e1 is a child of e2 and e2 has crossmnt set: */
+static bool subexport(struct exportent *e1, struct exportent *e2)
 {
-       /* 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;
-       unsigned int dev, major=0, minor=0;
-       unsigned int inode=0;
-       unsigned long long inode64;
-       unsigned int fsidnum=0;
-       char fsid[32];
-       struct exportent *found = NULL;
-       struct addrinfo *ai = NULL;
-       char *found_path = NULL;
-       nfs_export *exp;
-       int i;
-       int dev_missing = 0;
-       int uuidlen = 0;
-       char *fhuuid = NULL;
+       char *p1 = e1->e_path, *p2 = e2->e_path;
+       int l2 = strlen(p2);
 
-       if (readline(fileno(f), &lbuf, &lbuflen) != 1)
-               return;
+       return e2->e_flags & NFSEXP_CROSSMOUNT
+              && strncmp(p1, p2, l2) == 0
+              && p1[l2] == '/';
+}
 
-       xlog(D_CALL, "nfsd_fh: inbuf '%s'", lbuf);
+struct parsed_fsid {
+       int fsidtype;
+       /* We could use a union for this, but it would be more
+        * complicated; why bother? */
+       unsigned int inode;
+       unsigned int minor;
+       unsigned int major;
+       unsigned int fsidnum;
+       int uuidlen;
+       char *fhuuid;
+};
 
-       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;
+int parse_fsid(int fsidtype, int fsidlen, char *fsid, struct parsed_fsid *parsed)
+{
+       unsigned int dev;
+       unsigned long long inode64;
+
+       parsed->fsidtype = fsidtype;
        switch(fsidtype) {
        case FSID_DEV: /* 4 bytes: 2 major, 2 minor, 4 inode */
                if (fsidlen != 8)
-                       goto out;
+                       return -1;
                memcpy(&dev, fsid, 4);
-               memcpy(&inode, fsid+4, 4);
-               major = ntohl(dev)>>16;
-               minor = ntohl(dev) & 0xFFFF;
+               memcpy(&parsed->inode, fsid+4, 4);
+               parsed->major = ntohl(dev)>>16;
+               parsed->minor = ntohl(dev) & 0xFFFF;
                break;
 
        case FSID_NUM: /* 4 bytes - fsid */
                if (fsidlen != 4)
-                       goto out;
-               memcpy(&fsidnum, fsid, 4);
+                       return -1;
+               memcpy(&parsed->fsidnum, fsid, 4);
                break;
 
        case FSID_MAJOR_MINOR: /* 12 bytes: 4 major, 4 minor, 4 inode 
@@ -392,10 +391,12 @@ static void nfsd_fh(FILE *f)
                 * an historical accident
                 */
                if (fsidlen != 12)
-                       goto out;
-               memcpy(&dev, fsid, 4); major = ntohl(dev);
-               memcpy(&dev, fsid+4, 4); minor = ntohl(dev);
-               memcpy(&inode, fsid+8, 4);
+                       return -1;
+               memcpy(&dev, fsid, 4);
+               parsed->major = ntohl(dev);
+               memcpy(&dev, fsid+4, 4);
+               parsed->minor = ntohl(dev);
+               memcpy(&parsed->inode, fsid+8, 4);
                break;
 
        case FSID_ENCODE_DEV: /* 8 bytes: 4 byte packed device number, 4 inode */
@@ -403,41 +404,137 @@ static void nfsd_fh(FILE *f)
                 * no-one outside this host has any business interpreting it
                 */
                if (fsidlen != 8)
-                       goto out;
+                       return -1;
                memcpy(&dev, fsid, 4);
-               memcpy(&inode, fsid+4, 4);
-               major = (dev & 0xfff00) >> 8;
-               minor = (dev & 0xff) | ((dev >> 12) & 0xfff00);
+               memcpy(&parsed->inode, fsid+4, 4);
+               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)
-                       goto out;
-               memcpy(&inode, fsid, 4);
-               uuidlen = 4;
-               fhuuid = fsid+4;
+                       return -1;
+               memcpy(&parsed->inode, fsid, 4);
+               parsed->uuidlen = 4;
+               parsed->fhuuid = fsid+4;
                break;
        case FSID_UUID8: /* 8 byte uuid */
                if (fsidlen != 8)
-                       goto out;
-               uuidlen = 8;
-               fhuuid = fsid;
+                       return -1;
+               parsed->uuidlen = 8;
+               parsed->fhuuid = fsid;
                break;
        case FSID_UUID16: /* 16 byte uuid */
                if (fsidlen != 16)
-                       goto out;
-               uuidlen = 16;
-               fhuuid = fsid;
+                       return -1;
+               parsed->uuidlen = 16;
+               parsed->fhuuid = fsid;
                break;
        case FSID_UUID16_INUM: /* 8 byte inode number and 16 byte uuid */
                if (fsidlen != 24)
-                       goto out;
+                       return -1;
                memcpy(&inode64, fsid, 8);
-               inode = inode64;
-               uuidlen = 16;
-               fhuuid = fsid+8;
+               parsed->inode = inode64;
+               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 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();
 
@@ -445,10 +542,7 @@ static void nfsd_fh(FILE *f)
        for (i=0 ; i < MCL_MAXTYPES; i++) {
                nfs_export *next_exp;
                for (exp = exportlist[i].p_head; exp; exp = next_exp) {
-                       struct stat stb;
-                       char u[16];
                        char *path;
-                       int type;
 
                        if (exp->m_export.e_flags & NFSEXP_CROSSMOUNT) {
                                static nfs_export *prev = NULL;
@@ -481,50 +575,9 @@ static void nfsd_fh(FILE *f)
                                           exp->m_export.e_mountpoint:
                                           exp->m_export.e_path))
                                dev_missing ++;
-                       if (stat(path, &stb) != 0)
-                               continue;
-                       if (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode)) {
+
+                       if (!match_fsid(&parsed, exp, path))
                                continue;
-                       }
-                       switch(fsidtype){
-                       case FSID_DEV:
-                       case FSID_MAJOR_MINOR:
-                       case FSID_ENCODE_DEV:
-                               if (stb.st_ino != inode)
-                                       continue;
-                               if (major != major(stb.st_dev) ||
-                                   minor != minor(stb.st_dev))
-                                       continue;
-                               break;
-                       case FSID_NUM:
-                               if (((exp->m_export.e_flags & NFSEXP_FSID) == 0 ||
-                                    exp->m_export.e_fsid != fsidnum))
-                                       continue;
-                               break;
-                       case FSID_UUID4_INUM:
-                       case FSID_UUID16_INUM:
-                               if (stb.st_ino != inode)
-                                       continue;
-                               goto check_uuid;
-                       case FSID_UUID8:
-                       case FSID_UUID16:
-                               if (!is_mountpoint(path))
-                                       continue;
-                       check_uuid:
-                               if (exp->m_export.e_uuid)
-                                       get_uuid(exp->m_export.e_uuid,
-                                                uuidlen, u);
-                               else
-                                       for (type = 0;
-                                            uuid_by_path(path, type, uuidlen, u);
-                                            type++)
-                                               if (memcmp(u, fhuuid, uuidlen) == 0)
-                                                       break;
-
-                               if (memcmp(u, fhuuid, uuidlen) != 0)
-                                       continue;
-                               break;
-                       }
                        if (use_ipaddr) {
                                if (ai == NULL) {
                                        struct addrinfo *tmp;
@@ -537,13 +590,14 @@ static void nfsd_fh(FILE *f)
                                if (!client_check(exp->m_client, ai))
                                        continue;
                        }
-                       /* It's a match !! */
-                       if (!found) {
+                       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)
+                       } else if (strcmp(found->e_path, exp->m_export.e_path)
+                                  && !subexport(found, &exp->m_export))
                        {
                                xlog(L_WARNING, "%s and %s have same filehandle for %s, using first",
                                     found_path, path, dom);
@@ -644,11 +698,11 @@ static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *ex
 {
        qword_print(f, domain);
        qword_print(f, path);
-       qword_printint(f, time(0)+30*60);
        if (exp) {
                int different_fs = strcmp(path, exp->e_path) != 0;
                int flag_mask = different_fs ? ~NFSEXP_FSID : ~0;
 
+               qword_printuint(f, time(0) + exp->e_ttl);
                qword_printint(f, exp->e_flags & flag_mask);
                qword_printint(f, exp->e_anonuid);
                qword_printint(f, exp->e_anongid);
@@ -667,7 +721,8 @@ static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *ex
                        qword_print(f, "uuid");
                        qword_printhex(f, u, 16);
                }
-       }
+       } else
+               qword_printuint(f, time(0) + DEFAULT_TTL);
        return qword_eol(f);
 }
 
@@ -813,12 +868,13 @@ 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 }
+       { "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;
@@ -836,6 +892,10 @@ void cache_open(void)
                        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);
+               }
        }
 }
 
@@ -874,8 +934,8 @@ int cache_process_req(fd_set *readfds)
 
 /*
  * Give IP->domain and domain+path->options to kernel
- * % echo nfsd $IP  $[now+30*60] $domain > /proc/net/rpc/auth.unix.ip/channel
- * % echo $domain $path $[now+30*60] $options $anonuid $anongid $fsid > /proc/net/rpc/nfsd.export/channel
+ * % 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)
@@ -955,7 +1015,7 @@ int cache_export(nfs_export *exp, char *path)
        qword_print(f, "nfsd");
        qword_print(f,
                host_ntop(get_addrlist(exp->m_client, 0), buf, sizeof(buf)));
-       qword_printint(f, time(0)+30*60);
+       qword_printuint(f, time(0) + exp->m_export.e_ttl);
        qword_print(f, exp->m_client->m_hostname);
        err = qword_eol(f);
        
index d3099506d5c97e50e6bafba718123806e0f39e2a..035624c447ccfa68355332802eecdb6eb4069c61 100644 (file)
@@ -99,12 +99,9 @@ static int version_any(void)
 static void
 unregister_services (void)
 {
-       if (version2()) {
-               nfs_svc_unregister(MOUNTPROG, MOUNTVERS);
-               nfs_svc_unregister(MOUNTPROG, MOUNTVERS_POSIX);
-       }
-       if (version3())
-               nfs_svc_unregister(MOUNTPROG, MOUNTVERS_NFSV3);
+       nfs_svc_unregister(MOUNTPROG, MOUNTVERS);
+       nfs_svc_unregister(MOUNTPROG, MOUNTVERS_POSIX);
+       nfs_svc_unregister(MOUNTPROG, MOUNTVERS_NFSV3);
 }
 
 static void
@@ -840,6 +837,7 @@ main(int argc, char **argv)
        if (new_cache)
                cache_open();
 
+       unregister_services();
        if (version2()) {
                listeners += nfs_svc_create("mountd", MOUNTPROG,
                                        MOUNTVERS, mount_dispatch, port);
index 4bb96e8046c2fefc3870faa825cb2b208dc1c4f8..016a357d67e31f9e73f6e726242bca34f902b396 100644 (file)
@@ -106,11 +106,11 @@ 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 and the newer version 3. If the
-NFS kernel module was compiled without support for NFSv3,
+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 3" .
+.B "\-\-no-nfs-version <vers>" .
 .TP
 .B \-n " or " \-\-no-tcp
 Don't advertise TCP for mount.
index d3392968ab6b4c18b3422f9f7edf6c693b17d9c0..527377f8cd408c3e5899ab6040e295e76a69ea78 100644 (file)
@@ -205,6 +205,7 @@ mountlist_list(void)
        }
        if (stb.st_mtime != last_mtime) {
                mountlist_freeall(mlist);
+               mlist = NULL;
                last_mtime = stb.st_mtime;
 
                setrmtabent("r");
index 7fd6af3dd4592462addb005c3986031d8f5020ad..c33a5a9eb79d690580e81825de197d799d214ded 100644 (file)
@@ -144,8 +144,11 @@ static int v4root_add_parents(nfs_export *exp)
        char *ptr;
 
        path = strdup(exp->m_export.e_path);
-       if (!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 + 1; ptr; ptr = strchr(ptr, '/')) {
                int ret;
                char saved;
@@ -173,7 +176,7 @@ void
 v4root_set()
 {
        nfs_export      *exp;
-       int     i, ret;
+       int     i;
 
        if (!v4root_needed)
                return;
@@ -189,7 +192,7 @@ v4root_set()
                                 */
                                continue;
 
-                       ret = v4root_add_parents(exp);
+                       v4root_add_parents(exp);
                        /* XXX: error handling! */
                }
        }
index ea36399261b5d23f969269a141f0f6d67159ef67..f60721450dc7b40054306d9717bff3417f04aa2a 100644 (file)
@@ -174,8 +174,13 @@ nfssvc_setfds(const struct addrinfo *hints, const char *node, const char *port)
                sockfd = socket(addr->ai_family, addr->ai_socktype,
                                addr->ai_protocol);
                if (sockfd < 0) {
-                       xlog(L_ERROR, "unable to create %s %s socket: "
-                               "errno %d (%m)", family, proto, errno);
+                       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;
                }
diff --git a/utils/nfsidmap/Makefile.am b/utils/nfsidmap/Makefile.am
new file mode 100644 (file)
index 0000000..f837b91
--- /dev/null
@@ -0,0 +1,9 @@
+## Process this file with automake to produce Makefile.in
+
+man8_MANS = nfsidmap.man
+
+sbin_PROGRAMS  = nfsidmap
+nfsidmap_SOURCES = nfsidmap.c
+nfsidmap_LDADD = -lnfsidmap -lkeyutils
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/utils/nfsidmap/nfsidmap.c b/utils/nfsidmap/nfsidmap.c
new file mode 100644 (file)
index 0000000..2d87381
--- /dev/null
@@ -0,0 +1,118 @@
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <pwd.h>
+#include <grp.h>
+#include <keyutils.h>
+#include <nfsidmap.h>
+
+#include <syslog.h>
+
+/* gcc nfsidmap.c -o nfsidmap -l nfsidmap -l keyutils */
+
+#define MAX_ID_LEN   11
+#define IDMAP_NAMESZ 128
+#define USER  1
+#define GROUP 0
+
+
+/*
+ * 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)
+               rc = keyctl_instantiate(key, id, strlen(id) + 1, 0);
+
+       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) {
+               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)
+               rc = keyctl_instantiate(key, &name, strlen(name), 0);
+
+out:
+       return rc;
+}
+
+int main(int argc, char **argv)
+{
+       char *arg;
+       char *value;
+       char *type;
+       int rc = 1;
+       int timeout = 600;
+       key_serial_t key;
+
+       if (argc < 3)
+               return 1;
+
+       arg = malloc(sizeof(char) * strlen(argv[2]) + 1);
+       strcpy(arg, argv[2]);
+       type = strtok(arg, ":");
+       value = strtok(NULL, ":");
+
+       if (argc == 4) {
+               timeout = atoi(argv[3]);
+               if (timeout < 0)
+                       timeout = 0;
+       }
+
+       key = strtol(argv[1], NULL, 10);
+
+       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 5 (600 seconds) minutes */
+       if (rc == 0)
+               keyctl_set_timeout(key, timeout);
+
+       free(arg);
+       return rc;
+}
diff --git a/utils/nfsidmap/nfsidmap.man b/utils/nfsidmap/nfsidmap.man
new file mode 100644 (file)
index 0000000..6c1a2d4
--- /dev/null
@@ -0,0 +1,60 @@
+.\"
+.\"@(#)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 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
+should only be called by request-key, and will perform the translation and
+initialize a key with the resulting information.
+.PP
+NFS_USE_NEW_IDMAPPER must be selected when configuring the kernel to use this
+feature.
+.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 nfs_idmap       *       *       /usr/sbin/nfsidmap %k %d 600
+.PP
+This will direct all nfs_idmap requests to the program
+.I /usr/sbin/nfsidmap
+The last parameter, 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 nfs_idmap       uid:*   *       /some/other/program %k %d 600
+.br
+create nfs_idmap       *               *       /usr/sbin/nfsidmap %k %d 600
+.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>
index bacef8e8353402b2136e4fef098b4f41d5a39e0b..70f8d103fa022ec893ddc21c5d87c524490f4b6e 100644 (file)
@@ -46,7 +46,7 @@ static unsigned int   cltproc3info[CLTPROC3_SZ+2],
 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] == 48) */
+                       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
@@ -118,7 +118,7 @@ static const char * nfscltproc4name[CLTPROC4_SZ] = {
        "remove",    "rename",    "link",    "symlink",     "create",      "pathconf",
        "statfs",    "readlink",  "readdir", "server_caps", "delegreturn", "getacl",
        "setacl",    "fs_locations",
-       "rel_lkowner",
+       "rel_lkowner", "secinfo",
        /* nfsv4.1 client ops */
        "exchange_id",
        "create_ses",
@@ -127,13 +127,10 @@ static const char *       nfscltproc4name[CLTPROC4_SZ] = {
        "get_lease_t",
        "reclaim_comp",
        "layoutget",
+       "getdevinfo",
        "layoutcommit",
        "layoutreturn",
        "getdevlist",
-       "getdevinfo",
-       /* nfsv4.1 pnfs client ops to data server only */
-       "ds_write",
-       "ds_commit",
 };
 
 static const char *     nfssrvproc4opname[SRVPROC4OPS_SZ] = {
@@ -221,8 +218,8 @@ DECLARE_CLT(cltinfo);
 DECLARE_CLT(cltinfo, _old);
 
 static void            print_all_stats(int, int, int);
-static void            print_server_stats(int, int);
-static void            print_client_stats(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);
@@ -239,7 +236,7 @@ static int          mounts(const char *);
 
 static void            get_stats(const char *, struct statinfo *, int *, int,
                                        int);
-static int             has_stats(const unsigned 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);
@@ -468,7 +465,7 @@ main(int argc, char **argv)
                pause();
        }
 
-       if (opt_since || opt_sleep) {
+       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);
@@ -516,16 +513,16 @@ main(int argc, char **argv)
 static void
 print_all_stats (int opt_srv, int opt_clt, int opt_prt)
 {
-       print_server_stats(opt_srv, opt_prt);
-       print_client_stats(opt_clt, 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_srv, int opt_prt) 
+print_server_stats(int opt_prt) 
 {
-       if (!opt_srv)
-               return;
-
        if (opt_prt & PRNT_NET) {
                if (opt_sleep && !has_rpcstats(srvnetinfo, 4)) {
                } else {
@@ -540,7 +537,7 @@ print_server_stats(int opt_srv, int opt_prt)
                        ;
                } else {
                        print_numbers(LABEL_srvrpc
-                               "calls      badcalls   badauth    badclnt    xdrcall\n",
+                               "calls      badcalls   badclnt    badauth    xdrcall\n",
                                srvrpcinfo, 5);
                        printf("\n");
                }
@@ -582,31 +579,29 @@ print_server_stats(int opt_srv, int opt_prt)
                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_stats(srvproc2info))) {
-                       if (opt_sleep && !has_stats(srvproc2info)) {
-                               ;
-                       } else {
+                               ((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_stats(srvproc3info))) {
-                       if (opt_sleep && !has_stats(srvproc3info)) {
-                               ;
-                       } else {
+                               ((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_stats(srvproc4info))) {
-                       if (opt_sleep && !has_stats(srvproc4info)) {
-                               ;
-                       } else {
+                               ((opt_prt & PRNT_AUTO) && has_v4_stats)) {
+                       if (!opt_sleep || has_v4_stats) {
                                print_callstats( LABEL_srvproc4,
                                        nfssrvproc4name, srvproc4info + 1, 
                                        sizeof(nfssrvproc4name)/sizeof(char *));
@@ -618,11 +613,8 @@ print_server_stats(int opt_srv, int opt_prt)
        }
 }
 static void
-print_client_stats(int opt_clt, int opt_prt) 
+print_client_stats(int opt_prt) 
 {
-       if (!opt_clt)
-               return;
-
        if (opt_prt & PRNT_NET) {
                if (opt_sleep && !has_rpcstats(cltnetinfo, 4)) {
                        ;
@@ -644,31 +636,28 @@ print_client_stats(int opt_clt, 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_stats(cltproc2info))) {
-                       if (opt_sleep && !has_stats(cltproc2info)) {
-                               ;
-                       } else {
+                               ((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_stats(cltproc3info))) {
-                       if (opt_sleep && !has_stats(cltproc3info)) {
-                               ;
-                       } else {
+                               ((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_stats(cltproc4info))) {
-                       if (opt_sleep && !has_stats(cltproc4info)) {
-                               ;
-                       } else {
+                               ((opt_prt & PRNT_AUTO) && has_v4_stats)) {
+                       if (!opt_sleep || has_v4_stats) {
                                print_callstats(LABEL_cltproc4,
                                        nfscltproc4name, cltproc4info + 1,  
                                        sizeof(nfscltproc4name)/sizeof(char *));
@@ -681,34 +670,28 @@ 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_stats(cltproc2info))) {
-                       if (opt_sleep && !has_stats(cltproc2info)) {
-                               ;
-                       } else {
+                               ((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_stats(cltproc3info))) {
-                       if (opt_sleep && !has_stats(cltproc3info)) {
-                               ;
-                       } else { 
+                               ((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_stats(cltproc4info))) {
-                       if (opt_sleep && !has_stats(cltproc4info)) {
-                               ;
-                       } else {
-                               print_callstats_list("nfs v4 ops",
-                                       nfssrvproc4opname, srvproc4opsinfo + 1, 
-                                       sizeof(nfssrvproc4opname)/sizeof(char *));
+                               ((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 *));
@@ -720,32 +703,32 @@ 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_stats(srvproc2info))) {
-                       if (opt_sleep && !has_stats(srvproc2info)) {
-                               ;
-                       } else {
+                               ((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_stats(srvproc3info))) {
-                       if (opt_sleep && !has_stats(srvproc3info)) {
-                               ;
-                       } else {
+                               ((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_stats(srvproc4opsinfo))) {
-                       if (opt_sleep && !has_stats(srvproc4info)) {
-                               ;
-                       } else {
-                               print_callstats_list("nfs v4 ops",
+                               ((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 *));
                        }
@@ -1054,9 +1037,9 @@ out:
  * there are stats if the sum's greater than the entry-count.
  */
 static int
-has_stats(const unsigned int *info)
+has_stats(const unsigned int *info, int nr)
 {
-       return (info[0] && info[info[0] + 1] > info[0]);
+       return (info[0] && info[nr-1] > info[0]);
 }
 static int
 has_rpcstats(const unsigned int *info, int size)
index 52215a9293a5ff90915517a715e381230be9aa91..cd573b071ee68ef3f1d957a56fe33c6a6912db87 100644 (file)
@@ -30,10 +30,12 @@ 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. 
+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. 
+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.
index 38f22650c61e50f3447ba4aebf64b57936584325..616a3cbf45e2668ea57efe69c5aacf6995f80cd5 100644 (file)
 #include "statd.h"
 #include "xlog.h"
 
-#ifndef HAVE_DECL_AI_ADDRCONFIG
-#define AI_ADDRCONFIG  0
-#endif
-
 /**
  * statd_present_address - convert sockaddr to presentation address
  * @sap: pointer to socket address to convert
index 437e37a6b49de679f72b9663324faad4b346723d..1f490b0e6b7832baadf963f10c5839c846f4e1e9 100644 (file)
@@ -34,8 +34,9 @@
 #include "nsm.h"
 #include "nfsrpc.h"
 
-#ifndef HAVE_DECL_AI_ADDRCONFIG
-#define AI_ADDRCONFIG  0
+/* glibc before 2.3.4 */
+#ifndef AI_NUMERICSERV
+#define AI_NUMERICSERV 0
 #endif
 
 #define NSM_TIMEOUT    2
@@ -78,7 +79,6 @@ smn_lookup(const char *name)
 {
        struct addrinfo *ai = NULL;
        struct addrinfo hint = {
-               .ai_flags       = AI_ADDRCONFIG,
                .ai_family      = (nsm_family == AF_INET ? AF_INET: AF_UNSPEC),
                .ai_protocol    = (int)IPPROTO_UDP,
        };
@@ -253,6 +253,7 @@ smn_bind_address(const char *srcaddr, const char *srcport)
        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
index ca00e24af6ede8cc68aca9c17aea27528aea54d2..b72236c74b8a0573de88bd848e37003cbd0f3c49 100644 (file)
@@ -12,7 +12,7 @@
 .SH NAME
 rpc.statd \- NSM service daemon
 .SH SYNOPSIS
-.BI "rpc.statd [-dh?FLNvVw] [-H " prog "] [-n " my-name "] [-o " outgoing-port "] [-p " listener-port "] [-P " path " ]
+.BI "rpc.statd [-dh?FLNvV] [-H " prog "] [-n " my-name "] [-o " outgoing-port "] [-p " listener-port "] [-P " path " ]
 .SH DESCRIPTION
 File locks are not part of persistent file system state.
 Lock state is thus lost when a host reboots.