diff options
author | iedowse <iedowse@FreeBSD.org> | 2001-06-23 19:57:20 +0000 |
---|---|---|
committer | iedowse <iedowse@FreeBSD.org> | 2001-06-23 19:57:20 +0000 |
commit | 5ad8ec82779efbd25afbdaef579349c343a9da04 (patch) | |
tree | b253d2edfaf50db0a93b5a5c8f4507d99233da3a /sbin/mount_nfs | |
parent | dd53c9014eb416417cb746063d7cd8385096ce35 (diff) | |
download | FreeBSD-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/mount_nfs')
-rw-r--r-- | sbin/mount_nfs/mount_nfs.c | 21 |
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) { |