2 /* $Id: nfs_socket.c,v 1.12 2003/11/05 14:59:01 rees Exp $ */
6 * the regents of the university of michigan
9 * permission is granted to use, copy, create derivative works and redistribute
10 * this software and such derivative works for any purpose, so long as the name
11 * of the university of michigan is not used in any advertising or publicity
12 * pertaining to the use or distribution of this software without specific,
13 * written prior authorization. if the above copyright notice or any other
14 * identification of the university of michigan is included in any copy of any
15 * portion of this software, then the disclaimer below must also be included.
17 * this software is provided as is, without representation from the university
18 * of michigan as to its fitness for any purpose, and without warranty by the
19 * university of michigan of any kind, either express or implied, including
20 * without limitation the implied warranties of merchantability and fitness for
21 * a particular purpose. the regents of the university of michigan shall not be
22 * liable for any damages, including special, indirect, incidental, or
23 * consequential damages, with respect to any claim arising out of or in
24 * connection with the use of the software, even if it has been or is hereafter
25 * advised of the possibility of such damages.
29 * Copyright (c) 1989, 1991, 1993, 1995
30 * The Regents of the University of California. All rights reserved.
32 * This code is derived from software contributed to Berkeley by
33 * Rick Macklem at The University of Guelph.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 4. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * @(#)nfs_socket.c 8.5 (Berkeley) 3/30/95
62 #include <sys/cdefs.h>
63 __FBSDID("$FreeBSD$");
66 * Socket operations for use by nfs
69 #include "opt_inet6.h"
71 #include <sys/param.h>
72 #include <sys/systm.h>
73 #include <sys/kernel.h>
75 #include <sys/malloc.h>
77 #include <sys/mount.h>
78 #include <sys/mutex.h>
80 #include <sys/protosw.h>
81 #include <sys/signalvar.h>
82 #include <sys/socket.h>
83 #include <sys/socketvar.h>
84 #include <sys/syslog.h>
85 #include <sys/vnode.h>
87 #include <netinet/in.h>
88 #include <netinet/tcp.h>
90 #include <rpc/rpcclnt.h>
92 #include <nfs/rpcv2.h>
93 #include <nfs/nfsproto.h>
94 #include <nfsclient/nfs.h>
95 #include <nfs4client/nfs4.h>
96 #include <nfs/xdr_subs.h>
97 #include <nfsclient/nfsm_subs.h>
98 #include <nfsclient/nfsmount.h>
100 #ifdef NFS4_USE_RPCCLNT
101 #include <rpc/rpcclnt.h>
102 #include <rpc/rpcm_subs.h>
105 #ifdef NFS4_USE_RPCCLNT
106 static struct rpc_program nfs_program = {
107 NFS_PROG, NFS_VER4, "NFSv4"
117 { NFSERR_PERM, EPERM },
118 { NFSERR_NOENT, ENOENT },
120 { NFSERR_NXIO, ENXIO },
121 { NFSERR_ACCES, EACCES },
122 { NFSERR_EXIST, EEXIST },
123 { NFSERR_XDEV, EXDEV },
124 { NFSERR_MLINK, EMLINK },
125 { NFSERR_NODEV, ENODEV },
126 { NFSERR_NOTDIR, ENOTDIR },
127 { NFSERR_ISDIR, EISDIR },
128 { NFSERR_INVAL, EINVAL },
129 { NFSERR_FBIG, EFBIG },
130 { NFSERR_NOSPC, ENOSPC },
131 { NFSERR_ROFS, EROFS },
132 { NFSERR_MLINK, EMLINK },
133 { NFSERR_NAMETOL, ENAMETOOLONG },
134 { NFSERR_NOTEMPTY, ENOTEMPTY },
135 { NFSERR_NOTSUPP, EOPNOTSUPP },
137 { NFSERR_DQUOT, EDQUOT },
139 { NFSERR_STALE, ESTALE },
140 { NFSERR_DENIED, EAGAIN },
141 { NFSERR_SYMLINK, ELOOP },
142 { NFSERR_BADXDR, EBADRPC },
143 { NFSERR_WRONGSEC, EPERM },
148 nfs4_nfserr_to_syserr(int nfserr)
152 /* XXX : not the optimal algorithm, but will do for now! */
153 for (i = 0; nfs_errtbl[i].nfserr != -1; i++) {
154 if (nfs_errtbl[i].nfserr == nfserr)
157 #ifdef NFS4_MAP_UNKNOWN_ERR
158 syserr = nfs_errtbl[i].syserr;
160 if (nfs_errtbl[i].nfserr != -1)
161 syserr = nfs_errtbl[i].syserr;
169 nfs4_connect(struct nfsmount *nmp)
171 struct rpcclnt * rpc = &nmp->nm_rpcclnt;
172 struct rpc_auth * auth;
178 struct proc * td = curproc;
180 struct thread * td = curthread;
183 MALLOC(auth, struct rpc_auth *, sizeof(struct rpc_auth), M_TEMP, M_WAITOK);
184 auth->auth_type = RPCAUTH_UNIX;
186 /* translate nfs flags -> rpcclnt flags */
187 if (nmp->nm_flag & NFSMNT_SOFT)
188 flag |= RPCCLNT_SOFT;
190 if (nmp->nm_flag & NFSMNT_INT)
193 if (nmp->nm_flag & NFSMNT_NOCONN)
194 flag |= RPCCLNT_NOCONN;
196 if (nmp->nm_flag & NFSMNT_DUMBTIMR)
197 flag |= RPCCLNT_DUMBTIMR;
199 /* rpc->rc_servername = nmp->nm_mountp->mnt_stat.f_mntfromname; */
201 error = rpcclnt_setup(rpc, &nfs_program, nmp->nm_nam, nmp->nm_sotype,
202 nmp->nm_soproto, auth,
203 /* XXX: check nmp->nm_flag to make sure these are set */
204 (nmp->nm_rsize > nmp->nm_readdirsize) ? nmp->nm_rsize : nmp->nm_readdirsize,
205 nmp->nm_wsize, flag);
207 /* set deadthresh, timeo, retry */
208 rpc->rc_deadthresh = nmp->nm_deadthresh;
209 rpc->rc_timeo = nmp->nm_timeo;
210 rpc->rc_retry = nmp->nm_retry;
216 return rpcclnt_connect(rpc, td);
220 * NFS disconnect. Clean up and unlink.
223 nfs4_disconnect(struct nfsmount *nmp)
225 rpcclnt_disconnect(&nmp->nm_rpcclnt);
229 nfs4_safedisconnect(struct nfsmount *nmp)
231 rpcclnt_safedisconnect(&nmp->nm_rpcclnt);
235 * nfs_request - goes something like this
236 * - fill in request struct
237 * - links it into list
238 * - calls nfs_send() for first transmit
239 * - calls nfs_receive() to get reply
240 * - break down rpc header and return with nfs reply pointed to
242 * nb: always frees up mreq mbuf list
244 /* XXX overloaded before */
245 #define NQ_TRYLATERDEL 15 /* Initial try later delay (sec) */
248 nfs4_request(struct vnode *vp, struct mbuf *mrest, int procnum,
249 struct thread *td, struct ucred *cred, struct mbuf **mrp,
250 struct mbuf **mdp, caddr_t *dposp)
254 error = nfs4_request_mnt(VFSTONFS(vp->v_mount), mrest, procnum,
255 td, cred, mrp, mdp, dposp);
258 ** If the File Handle was stale, invalidate the
259 ** lookup cache, just in case.
269 nfs4_request_mnt(struct nfsmount *nmp, struct mbuf *mrest, int procnum,
270 struct thread *td, struct ucred *cred, struct mbuf **mrp,
271 struct mbuf **mdp, caddr_t *dposp)
275 struct rpcclnt * clnt = &nmp->nm_rpcclnt;
276 struct mbuf *md, *mrep;
278 struct rpc_reply reply;
280 if ((error = rpcclnt_request(clnt, mrest, procnum, td, cred,
285 /* XXX: don't free mrest if an error occured, to allow caller to retry*/
288 md = reply.result_md;
289 dpos = reply.result_dpos;
291 tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
293 error = fxdr_unsigned(int, *tl);
295 if ((nmp->nm_flag & NFSMNT_NFSV3) &&
296 error == NFSERR_TRYLATER) {
299 waituntil = time_second + trylater_delay;
300 while (time_second < waituntil)
301 (void) tsleep(&lbolt, PSOCK, "nqnfstry", 0);
302 trylater_delay *= nfs_backoff[trylater_cnt];
303 if (trylater_cnt < NFS_NBACKOFF - 1)
320 return (nfs4_nfserr_to_syserr(error));
325 * Mark all of an nfs mount's outstanding requests with R_SOFTTERM and
326 * wait for all requests to complete. This is used by forced unmounts
327 * to terminate any outstanding RPCs.
330 nfs4_nmcancelreqs(nmp)
331 struct nfsmount *nmp;
333 return rpcclnt_cancelreqs(&nmp->nm_rpcclnt);
337 * Test for a termination condition pending on the process.
338 * This is used for NFSMNT_INT mounts.
341 nfs4_sigintr(struct nfsmount *nmp, struct nfsreq *rep, struct thread *td)
344 printf("nfs_sigintr: attempting to use nfsreq != NULL\n");
347 return rpcclnt_sigintr(&nmp->nm_rpcclnt, NULL, td);