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.
This commit is contained in:
parent
32de72d27f
commit
eca1c24e5a
@ -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 @@ nfs_tryproto(struct nfs_args *nfsargsp, struct addrinfo *ai, char *hostp,
|
||||
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) {
|
||||
|
Loading…
Reference in New Issue
Block a user