]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/mount/network.c
mount.nfs: fix hang when getport() uses TCP against unavailable servers
[nfs-utils.git] / utils / mount / network.c
index b04491c7e38605c8a0056803eb4bea962d4eccef..565330281c940f94a5ab03bd7c945778934d1398 100644 (file)
@@ -38,7 +38,6 @@
 #include "xcommon.h"
 #include "mount.h"
 #include "nls.h"
-#include "nfsumount.h"
 #include "nfs_mount.h"
 #include "mount_constants.h"
 #include "network.h"
@@ -136,8 +135,23 @@ unsigned short getport(struct sockaddr_in *saddr, unsigned long prog,
        struct pmap parms;
        enum clnt_stat stat;
 
-       saddr->sin_port = htons (PMAPPORT);
-       socket = get_socket(saddr, prot, FALSE, FALSE);
+       saddr->sin_port = htons(PMAPPORT);
+
+       /*
+        * Try to get a socket with a non-privileged port.
+        * clnt*create() will create one anyway if this
+        * fails.
+        */
+       socket = get_socket(saddr, proto, FALSE, FALSE);
+       if (socket == RPC_ANYSOCK) {
+               if (proto == IPPROTO_TCP && errno == ETIMEDOUT) {
+                       /*
+                        * TCP SYN timed out, so exit now.
+                        */
+                       rpc_createerr.cf_stat = RPC_TIMEDOUT;
+               }
+               return 0;
+       }
 
        switch (prot) {
        case IPPROTO_UDP:
@@ -363,6 +377,17 @@ int start_statd(void)
        return 0;
 }
 
+/*
+ * nfs_call_umount - ask the server to remove a share from it's rmtab
+ * @mnt_server: address of RPC MNT program server
+ * @argp: directory path of share to "unmount"
+ *
+ * Returns one if the unmount call succeeded; zero if the unmount
+ * failed for any reason.
+ *
+ * Note that a side effect of calling this function is that rpccreateerr
+ * is set.
+ */
 int nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp)
 {
        CLIENT *clnt;
@@ -374,22 +399,24 @@ int nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp)
        case 2:
        case 1:
                if (!probe_mntport(mnt_server))
-                       goto out_bad;
+                       return 0;
                clnt = mnt_openclnt(mnt_server, &msock);
                if (!clnt)
-                       goto out_bad;
+                       return 0;
                res = clnt_call(clnt, MOUNTPROC_UMNT,
-                               (xdrproc_t) xdr_dirpath, (caddr_t)argp,
-                               (xdrproc_t) xdr_void, NULL,
+                               (xdrproc_t)xdr_dirpath, (caddr_t)argp,
+                               (xdrproc_t)xdr_void, NULL,
                                TIMEOUT);
                mnt_closeclnt(clnt, msock);
                if (res == RPC_SUCCESS)
                        return 1;
                break;
        default:
-               res = 1;
+               res = RPC_SUCCESS;
                break;
        }
- out_bad:
-       return res;
+
+       if (res == RPC_SUCCESS)
+               return 1;
+       return 0;
 }