summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2001-06-23 19:57:20 +0000
committeriedowse <iedowse@FreeBSD.org>2001-06-23 19:57:20 +0000
commit5ad8ec82779efbd25afbdaef579349c343a9da04 (patch)
treeb253d2edfaf50db0a93b5a5c8f4507d99233da3a /sbin
parentdd53c9014eb416417cb746063d7cd8385096ce35 (diff)
downloadFreeBSD-src-5ad8ec82779efbd25afbdaef579349c343a9da04.zip
FreeBSD-src-5ad8ec82779efbd25afbdaef579349c343a9da04.tar.gz
Use the new CLSET_CONNECT clnt_control() request on UDP clients to
ensure that we never proceed with the mount() syscall if the server is replying from the wrong source address. Previously the userland RPC call to the remote nfsd would succeed, but the kernel uses connect() so it would not see the replies, resulting in a hung mount.
Diffstat (limited to 'sbin')
-rw-r--r--sbin/mount_nfs/mount_nfs.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/sbin/mount_nfs/mount_nfs.c b/sbin/mount_nfs/mount_nfs.c
index 1be9944..b6667c5 100644
--- a/sbin/mount_nfs/mount_nfs.c
+++ b/sbin/mount_nfs/mount_nfs.c
@@ -764,7 +764,7 @@ nfs_tryproto(struct nfs_args *nfsargsp, struct addrinfo *ai, char *hostp,
CLIENT *clp;
struct netconfig *nconf, *nconf_mnt;
char *netid, *netid_mnt;
- int nfsvers, mntvers;
+ int doconnect, nfsvers, mntvers;
enum clnt_stat stat;
enum mountmode trymntmode;
@@ -843,6 +843,22 @@ tryagain:
return (returncode(rpc_createerr.cf_stat,
&rpc_createerr.cf_error));
}
+ if (nfsargsp->sotype == SOCK_DGRAM) {
+ /*
+ * Use connect(), to match what the kernel does. This
+ * catches cases where the server responds from the
+ * wrong source address.
+ */
+ doconnect = 1;
+ if (!clnt_control(clp, CLSET_CONNECT, (char *)&doconnect)) {
+ clnt_destroy(clp);
+ snprintf(errbuf, sizeof errbuf,
+ "[%s] %s:%s: CLSET_CONNECT failed", netid, hostp,
+ spec);
+ return (TRYRET_LOCALERR);
+ }
+ }
+
try.tv_sec = 10;
try.tv_usec = 0;
stat = clnt_call(clp, NFSPROC_NULL, xdr_void, NULL, xdr_void, NULL,
@@ -935,6 +951,9 @@ returncode(enum clnt_stat stat, struct rpc_err *rpcerr)
case RPC_PMAPFAILURE:
case RPC_PROGNOTREGISTERED:
case RPC_PROGVERSMISMATCH:
+ /* XXX, these can be local or remote. */
+ case RPC_CANTSEND:
+ case RPC_CANTRECV:
return (TRYRET_REMOTEERR);
case RPC_SYSTEMERROR:
switch (rpcerr->re_errno) {
OpenPOWER on IntegriCloud