nfs_nfsdserv.c revision 1.2.10.2 1 1.2.10.2 tls /* $NetBSD: nfs_nfsdserv.c,v 1.2.10.2 2014/08/20 00:04:27 tls Exp $ */
2 1.2.10.2 tls /*-
3 1.2.10.2 tls * Copyright (c) 1989, 1993
4 1.2.10.2 tls * The Regents of the University of California. All rights reserved.
5 1.2.10.2 tls *
6 1.2.10.2 tls * This code is derived from software contributed to Berkeley by
7 1.2.10.2 tls * Rick Macklem at The University of Guelph.
8 1.2.10.2 tls *
9 1.2.10.2 tls * Redistribution and use in source and binary forms, with or without
10 1.2.10.2 tls * modification, are permitted provided that the following conditions
11 1.2.10.2 tls * are met:
12 1.2.10.2 tls * 1. Redistributions of source code must retain the above copyright
13 1.2.10.2 tls * notice, this list of conditions and the following disclaimer.
14 1.2.10.2 tls * 2. Redistributions in binary form must reproduce the above copyright
15 1.2.10.2 tls * notice, this list of conditions and the following disclaimer in the
16 1.2.10.2 tls * documentation and/or other materials provided with the distribution.
17 1.2.10.2 tls * 4. Neither the name of the University nor the names of its contributors
18 1.2.10.2 tls * may be used to endorse or promote products derived from this software
19 1.2.10.2 tls * without specific prior written permission.
20 1.2.10.2 tls *
21 1.2.10.2 tls * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 1.2.10.2 tls * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 1.2.10.2 tls * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 1.2.10.2 tls * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 1.2.10.2 tls * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 1.2.10.2 tls * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 1.2.10.2 tls * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 1.2.10.2 tls * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 1.2.10.2 tls * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 1.2.10.2 tls * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 1.2.10.2 tls * SUCH DAMAGE.
32 1.2.10.2 tls *
33 1.2.10.2 tls */
34 1.2.10.2 tls
35 1.2.10.2 tls #include <sys/cdefs.h>
36 1.2.10.2 tls /* __FBSDID("FreeBSD: head/sys/fs/nfsserver/nfs_nfsdserv.c 245613 2013-01-18 19:42:08Z delphij "); */
37 1.2.10.2 tls __RCSID("$NetBSD: nfs_nfsdserv.c,v 1.2.10.2 2014/08/20 00:04:27 tls Exp $");
38 1.2.10.2 tls
39 1.2.10.2 tls /*
40 1.2.10.2 tls * nfs version 2, 3 and 4 server calls to vnode ops
41 1.2.10.2 tls * - these routines generally have 3 phases
42 1.2.10.2 tls * 1 - break down and validate rpc request in mbuf list
43 1.2.10.2 tls * 2 - do the vnode ops for the request, usually by calling a nfsvno_XXX()
44 1.2.10.2 tls * function in nfsd_port.c
45 1.2.10.2 tls * 3 - build the rpc reply in an mbuf list
46 1.2.10.2 tls * For nfsv4, these functions are called for each Op within the Compound RPC.
47 1.2.10.2 tls */
48 1.2.10.2 tls
49 1.2.10.2 tls #ifndef APPLEKEXT
50 1.2.10.2 tls #include <fs/nfs/nfsport.h>
51 1.2.10.2 tls
52 1.2.10.2 tls /* Global vars */
53 1.2.10.2 tls extern u_int32_t newnfs_false, newnfs_true;
54 1.2.10.2 tls extern enum vtype nv34tov_type[8];
55 1.2.10.2 tls extern struct timeval nfsboottime;
56 1.2.10.2 tls extern int nfs_rootfhset;
57 1.2.10.2 tls extern int nfsrv_enable_crossmntpt;
58 1.2.10.2 tls #endif /* !APPLEKEXT */
59 1.2.10.2 tls
60 1.2.10.2 tls static int nfs_async = 0;
61 1.2.10.2 tls SYSCTL_DECL(_vfs_nfsd);
62 1.2.10.2 tls SYSCTL_INT(_vfs_nfsd, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0,
63 1.2.10.2 tls "Tell client that writes were synced even though they were not");
64 1.2.10.2 tls
65 1.2.10.2 tls /*
66 1.2.10.2 tls * This list defines the GSS mechanisms supported.
67 1.2.10.2 tls * (Don't ask me how you get these strings from the RFC stuff like
68 1.2.10.2 tls * iso(1), org(3)... but someone did it, so I don't need to know.)
69 1.2.10.2 tls */
70 1.2.10.2 tls static struct nfsgss_mechlist nfsgss_mechlist[] = {
71 1.2.10.2 tls { 9, "\052\206\110\206\367\022\001\002\002", 11 },
72 1.2.10.2 tls { 0, "", 0 },
73 1.2.10.2 tls };
74 1.2.10.2 tls
75 1.2.10.2 tls /* local functions */
76 1.2.10.2 tls static void nfsrvd_symlinksub(struct nfsrv_descript *nd, struct nameidata *ndp,
77 1.2.10.2 tls struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp,
78 1.2.10.2 tls vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp,
79 1.2.10.2 tls int *diraft_retp, nfsattrbit_t *attrbitp,
80 1.2.10.2 tls NFSACL_T *aclp, NFSPROC_T *p, struct nfsexstuff *exp, char *pathcp,
81 1.2.10.2 tls int pathlen);
82 1.2.10.2 tls static void nfsrvd_mkdirsub(struct nfsrv_descript *nd, struct nameidata *ndp,
83 1.2.10.2 tls struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp,
84 1.2.10.2 tls vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp,
85 1.2.10.2 tls int *diraft_retp, nfsattrbit_t *attrbitp, NFSACL_T *aclp,
86 1.2.10.2 tls NFSPROC_T *p, struct nfsexstuff *exp);
87 1.2.10.2 tls
88 1.2.10.2 tls /*
89 1.2.10.2 tls * nfs access service (not a part of NFS V2)
90 1.2.10.2 tls */
91 1.2.10.2 tls APPLESTATIC int
92 1.2.10.2 tls nfsrvd_access(struct nfsrv_descript *nd, __unused int isdgram,
93 1.2.10.2 tls vnode_t vp, NFSPROC_T *p, struct nfsexstuff *exp)
94 1.2.10.2 tls {
95 1.2.10.2 tls u_int32_t *tl;
96 1.2.10.2 tls int getret, error = 0;
97 1.2.10.2 tls struct nfsvattr nva;
98 1.2.10.2 tls u_int32_t testmode, nfsmode, supported = 0;
99 1.2.10.2 tls accmode_t deletebit;
100 1.2.10.2 tls
101 1.2.10.2 tls if (nd->nd_repstat) {
102 1.2.10.2 tls nfsrv_postopattr(nd, 1, &nva);
103 1.2.10.2 tls goto out;
104 1.2.10.2 tls }
105 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
106 1.2.10.2 tls nfsmode = fxdr_unsigned(u_int32_t, *tl);
107 1.2.10.2 tls if ((nd->nd_flag & ND_NFSV4) &&
108 1.2.10.2 tls (nfsmode & ~(NFSACCESS_READ | NFSACCESS_LOOKUP |
109 1.2.10.2 tls NFSACCESS_MODIFY | NFSACCESS_EXTEND | NFSACCESS_DELETE |
110 1.2.10.2 tls NFSACCESS_EXECUTE))) {
111 1.2.10.2 tls nd->nd_repstat = NFSERR_INVAL;
112 1.2.10.2 tls vput(vp);
113 1.2.10.2 tls goto out;
114 1.2.10.2 tls }
115 1.2.10.2 tls if (nfsmode & NFSACCESS_READ) {
116 1.2.10.2 tls supported |= NFSACCESS_READ;
117 1.2.10.2 tls if (nfsvno_accchk(vp, VREAD, nd->nd_cred, exp, p,
118 1.2.10.2 tls NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported))
119 1.2.10.2 tls nfsmode &= ~NFSACCESS_READ;
120 1.2.10.2 tls }
121 1.2.10.2 tls if (nfsmode & NFSACCESS_MODIFY) {
122 1.2.10.2 tls supported |= NFSACCESS_MODIFY;
123 1.2.10.2 tls if (nfsvno_accchk(vp, VWRITE, nd->nd_cred, exp, p,
124 1.2.10.2 tls NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported))
125 1.2.10.2 tls nfsmode &= ~NFSACCESS_MODIFY;
126 1.2.10.2 tls }
127 1.2.10.2 tls if (nfsmode & NFSACCESS_EXTEND) {
128 1.2.10.2 tls supported |= NFSACCESS_EXTEND;
129 1.2.10.2 tls if (nfsvno_accchk(vp, VWRITE | VAPPEND, nd->nd_cred, exp, p,
130 1.2.10.2 tls NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported))
131 1.2.10.2 tls nfsmode &= ~NFSACCESS_EXTEND;
132 1.2.10.2 tls }
133 1.2.10.2 tls if (nfsmode & NFSACCESS_DELETE) {
134 1.2.10.2 tls supported |= NFSACCESS_DELETE;
135 1.2.10.2 tls if (vp->v_type == VDIR)
136 1.2.10.2 tls deletebit = VDELETE_CHILD;
137 1.2.10.2 tls else
138 1.2.10.2 tls deletebit = VDELETE;
139 1.2.10.2 tls if (nfsvno_accchk(vp, deletebit, nd->nd_cred, exp, p,
140 1.2.10.2 tls NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported))
141 1.2.10.2 tls nfsmode &= ~NFSACCESS_DELETE;
142 1.2.10.2 tls }
143 1.2.10.2 tls if (vnode_vtype(vp) == VDIR)
144 1.2.10.2 tls testmode = NFSACCESS_LOOKUP;
145 1.2.10.2 tls else
146 1.2.10.2 tls testmode = NFSACCESS_EXECUTE;
147 1.2.10.2 tls if (nfsmode & testmode) {
148 1.2.10.2 tls supported |= (nfsmode & testmode);
149 1.2.10.2 tls if (nfsvno_accchk(vp, VEXEC, nd->nd_cred, exp, p,
150 1.2.10.2 tls NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported))
151 1.2.10.2 tls nfsmode &= ~testmode;
152 1.2.10.2 tls }
153 1.2.10.2 tls nfsmode &= supported;
154 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3) {
155 1.2.10.2 tls getret = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1);
156 1.2.10.2 tls nfsrv_postopattr(nd, getret, &nva);
157 1.2.10.2 tls }
158 1.2.10.2 tls vput(vp);
159 1.2.10.2 tls if (nd->nd_flag & ND_NFSV4) {
160 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
161 1.2.10.2 tls *tl++ = txdr_unsigned(supported);
162 1.2.10.2 tls } else
163 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
164 1.2.10.2 tls *tl = txdr_unsigned(nfsmode);
165 1.2.10.2 tls
166 1.2.10.2 tls out:
167 1.2.10.2 tls NFSEXITCODE2(0, nd);
168 1.2.10.2 tls return (0);
169 1.2.10.2 tls nfsmout:
170 1.2.10.2 tls vput(vp);
171 1.2.10.2 tls NFSEXITCODE2(error, nd);
172 1.2.10.2 tls return (error);
173 1.2.10.2 tls }
174 1.2.10.2 tls
175 1.2.10.2 tls /*
176 1.2.10.2 tls * nfs getattr service
177 1.2.10.2 tls */
178 1.2.10.2 tls APPLESTATIC int
179 1.2.10.2 tls nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram,
180 1.2.10.2 tls vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp)
181 1.2.10.2 tls {
182 1.2.10.2 tls struct nfsvattr nva;
183 1.2.10.2 tls fhandle_t fh;
184 1.2.10.2 tls int at_root = 0, error = 0, supports_nfsv4acls;
185 1.2.10.2 tls struct nfsreferral *refp;
186 1.2.10.2 tls nfsattrbit_t attrbits, tmpbits;
187 1.2.10.2 tls struct mount *mp;
188 1.2.10.2 tls struct vnode *tvp = NULL;
189 1.2.10.2 tls struct vattr va;
190 1.2.10.2 tls uint64_t mounted_on_fileno = 0;
191 1.2.10.2 tls accmode_t accmode;
192 1.2.10.2 tls
193 1.2.10.2 tls if (nd->nd_repstat)
194 1.2.10.2 tls goto out;
195 1.2.10.2 tls if (nd->nd_flag & ND_NFSV4) {
196 1.2.10.2 tls error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
197 1.2.10.2 tls if (error) {
198 1.2.10.2 tls vput(vp);
199 1.2.10.2 tls goto out;
200 1.2.10.2 tls }
201 1.2.10.2 tls
202 1.2.10.2 tls /*
203 1.2.10.2 tls * Check for a referral.
204 1.2.10.2 tls */
205 1.2.10.2 tls refp = nfsv4root_getreferral(vp, NULL, 0);
206 1.2.10.2 tls if (refp != NULL) {
207 1.2.10.2 tls (void) nfsrv_putreferralattr(nd, &attrbits, refp, 1,
208 1.2.10.2 tls &nd->nd_repstat);
209 1.2.10.2 tls vput(vp);
210 1.2.10.2 tls goto out;
211 1.2.10.2 tls }
212 1.2.10.2 tls if (nd->nd_repstat == 0) {
213 1.2.10.2 tls accmode = 0;
214 1.2.10.2 tls NFSSET_ATTRBIT(&tmpbits, &attrbits);
215 1.2.10.2 tls if (NFSISSET_ATTRBIT(&tmpbits, NFSATTRBIT_ACL)) {
216 1.2.10.2 tls NFSCLRBIT_ATTRBIT(&tmpbits, NFSATTRBIT_ACL);
217 1.2.10.2 tls accmode |= VREAD_ACL;
218 1.2.10.2 tls }
219 1.2.10.2 tls if (NFSNONZERO_ATTRBIT(&tmpbits))
220 1.2.10.2 tls accmode |= VREAD_ATTRIBUTES;
221 1.2.10.2 tls if (accmode != 0)
222 1.2.10.2 tls nd->nd_repstat = nfsvno_accchk(vp, accmode,
223 1.2.10.2 tls nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE,
224 1.2.10.2 tls NFSACCCHK_VPISLOCKED, NULL);
225 1.2.10.2 tls }
226 1.2.10.2 tls }
227 1.2.10.2 tls if (!nd->nd_repstat)
228 1.2.10.2 tls nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1);
229 1.2.10.2 tls if (!nd->nd_repstat) {
230 1.2.10.2 tls if (nd->nd_flag & ND_NFSV4) {
231 1.2.10.2 tls if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_FILEHANDLE))
232 1.2.10.2 tls nd->nd_repstat = nfsvno_getfh(vp, &fh, p);
233 1.2.10.2 tls if (!nd->nd_repstat)
234 1.2.10.2 tls nd->nd_repstat = nfsrv_checkgetattr(nd, vp,
235 1.2.10.2 tls &nva, &attrbits, nd->nd_cred, p);
236 1.2.10.2 tls if (nd->nd_repstat == 0) {
237 1.2.10.2 tls supports_nfsv4acls = nfs_supportsnfsv4acls(vp);
238 1.2.10.2 tls mp = vp->v_mount;
239 1.2.10.2 tls if (nfsrv_enable_crossmntpt != 0 &&
240 1.2.10.2 tls vp->v_type == VDIR &&
241 1.2.10.2 tls (vp->v_vflag & VV_ROOT) != 0 &&
242 1.2.10.2 tls vp != rootvnode) {
243 1.2.10.2 tls tvp = mp->mnt_vnodecovered;
244 1.2.10.2 tls VREF(tvp);
245 1.2.10.2 tls at_root = 1;
246 1.2.10.2 tls } else
247 1.2.10.2 tls at_root = 0;
248 1.2.10.2 tls vfs_ref(mp);
249 1.2.10.2 tls NFSVOPUNLOCK(vp, 0);
250 1.2.10.2 tls if (at_root != 0) {
251 1.2.10.2 tls if ((nd->nd_repstat =
252 1.2.10.2 tls NFSVOPLOCK(tvp, LK_SHARED)) == 0) {
253 1.2.10.2 tls nd->nd_repstat = VOP_GETATTR(
254 1.2.10.2 tls tvp, &va, nd->nd_cred);
255 1.2.10.2 tls vput(tvp);
256 1.2.10.2 tls } else
257 1.2.10.2 tls vrele(tvp);
258 1.2.10.2 tls if (nd->nd_repstat == 0)
259 1.2.10.2 tls mounted_on_fileno = (uint64_t)
260 1.2.10.2 tls va.va_fileid;
261 1.2.10.2 tls else
262 1.2.10.2 tls at_root = 0;
263 1.2.10.2 tls }
264 1.2.10.2 tls if (nd->nd_repstat == 0)
265 1.2.10.2 tls nd->nd_repstat = vfs_busy(mp, 0);
266 1.2.10.2 tls vfs_rel(mp);
267 1.2.10.2 tls if (nd->nd_repstat == 0) {
268 1.2.10.2 tls (void)nfsvno_fillattr(nd, mp, vp, &nva,
269 1.2.10.2 tls &fh, 0, &attrbits, nd->nd_cred, p,
270 1.2.10.2 tls isdgram, 1, supports_nfsv4acls,
271 1.2.10.2 tls at_root, mounted_on_fileno);
272 1.2.10.2 tls vfs_unbusy(mp);
273 1.2.10.2 tls }
274 1.2.10.2 tls vrele(vp);
275 1.2.10.2 tls } else
276 1.2.10.2 tls vput(vp);
277 1.2.10.2 tls } else {
278 1.2.10.2 tls nfsrv_fillattr(nd, &nva);
279 1.2.10.2 tls vput(vp);
280 1.2.10.2 tls }
281 1.2.10.2 tls } else {
282 1.2.10.2 tls vput(vp);
283 1.2.10.2 tls }
284 1.2.10.2 tls
285 1.2.10.2 tls out:
286 1.2.10.2 tls NFSEXITCODE2(error, nd);
287 1.2.10.2 tls return (error);
288 1.2.10.2 tls }
289 1.2.10.2 tls
290 1.2.10.2 tls /*
291 1.2.10.2 tls * nfs setattr service
292 1.2.10.2 tls */
293 1.2.10.2 tls APPLESTATIC int
294 1.2.10.2 tls nfsrvd_setattr(struct nfsrv_descript *nd, __unused int isdgram,
295 1.2.10.2 tls vnode_t vp, NFSPROC_T *p, struct nfsexstuff *exp)
296 1.2.10.2 tls {
297 1.2.10.2 tls struct nfsvattr nva, nva2;
298 1.2.10.2 tls u_int32_t *tl;
299 1.2.10.2 tls int preat_ret = 1, postat_ret = 1, gcheck = 0, error = 0;
300 1.2.10.2 tls struct timespec guard = { 0, 0 };
301 1.2.10.2 tls nfsattrbit_t attrbits, retbits;
302 1.2.10.2 tls nfsv4stateid_t stateid;
303 1.2.10.2 tls NFSACL_T *aclp = NULL;
304 1.2.10.2 tls
305 1.2.10.2 tls if (nd->nd_repstat) {
306 1.2.10.2 tls nfsrv_wcc(nd, preat_ret, &nva2, postat_ret, &nva);
307 1.2.10.2 tls goto out;
308 1.2.10.2 tls }
309 1.2.10.2 tls #ifdef NFS4_ACL_EXTATTR_NAME
310 1.2.10.2 tls aclp = acl_alloc(M_WAITOK);
311 1.2.10.2 tls aclp->acl_cnt = 0;
312 1.2.10.2 tls #endif
313 1.2.10.2 tls NFSVNO_ATTRINIT(&nva);
314 1.2.10.2 tls NFSZERO_ATTRBIT(&retbits);
315 1.2.10.2 tls if (nd->nd_flag & ND_NFSV4) {
316 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
317 1.2.10.2 tls stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
318 1.2.10.2 tls NFSBCOPY((caddr_t)tl,(caddr_t)stateid.other,NFSX_STATEIDOTHER);
319 1.2.10.2 tls }
320 1.2.10.2 tls error = nfsrv_sattr(nd, &nva, &attrbits, aclp, p);
321 1.2.10.2 tls if (error)
322 1.2.10.2 tls goto nfsmout;
323 1.2.10.2 tls preat_ret = nfsvno_getattr(vp, &nva2, nd->nd_cred, p, 1);
324 1.2.10.2 tls if (!nd->nd_repstat)
325 1.2.10.2 tls nd->nd_repstat = preat_ret;
326 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3) {
327 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
328 1.2.10.2 tls gcheck = fxdr_unsigned(int, *tl);
329 1.2.10.2 tls if (gcheck) {
330 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
331 1.2.10.2 tls fxdr_nfsv3time(tl, &guard);
332 1.2.10.2 tls }
333 1.2.10.2 tls if (!nd->nd_repstat && gcheck &&
334 1.2.10.2 tls (nva2.na_ctime.tv_sec != guard.tv_sec ||
335 1.2.10.2 tls nva2.na_ctime.tv_nsec != guard.tv_nsec))
336 1.2.10.2 tls nd->nd_repstat = NFSERR_NOT_SYNC;
337 1.2.10.2 tls if (nd->nd_repstat) {
338 1.2.10.2 tls vput(vp);
339 1.2.10.2 tls #ifdef NFS4_ACL_EXTATTR_NAME
340 1.2.10.2 tls acl_free(aclp);
341 1.2.10.2 tls #endif
342 1.2.10.2 tls nfsrv_wcc(nd, preat_ret, &nva2, postat_ret, &nva);
343 1.2.10.2 tls goto out;
344 1.2.10.2 tls }
345 1.2.10.2 tls } else if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV4))
346 1.2.10.2 tls nd->nd_repstat = nfsrv_checkuidgid(nd, &nva);
347 1.2.10.2 tls
348 1.2.10.2 tls /*
349 1.2.10.2 tls * Now that we have all the fields, lets do it.
350 1.2.10.2 tls * If the size is being changed write access is required, otherwise
351 1.2.10.2 tls * just check for a read only file system.
352 1.2.10.2 tls */
353 1.2.10.2 tls if (!nd->nd_repstat) {
354 1.2.10.2 tls if (NFSVNO_NOTSETSIZE(&nva)) {
355 1.2.10.2 tls if (NFSVNO_EXRDONLY(exp) ||
356 1.2.10.2 tls (vfs_flags(vnode_mount(vp)) & MNT_RDONLY))
357 1.2.10.2 tls nd->nd_repstat = EROFS;
358 1.2.10.2 tls } else {
359 1.2.10.2 tls if (vnode_vtype(vp) != VREG)
360 1.2.10.2 tls nd->nd_repstat = EINVAL;
361 1.2.10.2 tls else if (nva2.na_uid != nd->nd_cred->cr_uid ||
362 1.2.10.2 tls NFSVNO_EXSTRICTACCESS(exp))
363 1.2.10.2 tls nd->nd_repstat = nfsvno_accchk(vp,
364 1.2.10.2 tls VWRITE, nd->nd_cred, exp, p,
365 1.2.10.2 tls NFSACCCHK_NOOVERRIDE,
366 1.2.10.2 tls NFSACCCHK_VPISLOCKED, NULL);
367 1.2.10.2 tls }
368 1.2.10.2 tls }
369 1.2.10.2 tls if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV4))
370 1.2.10.2 tls nd->nd_repstat = nfsrv_checksetattr(vp, nd, &stateid,
371 1.2.10.2 tls &nva, &attrbits, exp, p);
372 1.2.10.2 tls
373 1.2.10.2 tls if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV4)) {
374 1.2.10.2 tls /*
375 1.2.10.2 tls * For V4, try setting the attrbutes in sets, so that the
376 1.2.10.2 tls * reply bitmap will be correct for an error case.
377 1.2.10.2 tls */
378 1.2.10.2 tls if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_OWNER) ||
379 1.2.10.2 tls NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_OWNERGROUP)) {
380 1.2.10.2 tls NFSVNO_ATTRINIT(&nva2);
381 1.2.10.2 tls NFSVNO_SETATTRVAL(&nva2, uid, nva.na_uid);
382 1.2.10.2 tls NFSVNO_SETATTRVAL(&nva2, gid, nva.na_gid);
383 1.2.10.2 tls nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p,
384 1.2.10.2 tls exp);
385 1.2.10.2 tls if (!nd->nd_repstat) {
386 1.2.10.2 tls if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_OWNER))
387 1.2.10.2 tls NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_OWNER);
388 1.2.10.2 tls if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_OWNERGROUP))
389 1.2.10.2 tls NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_OWNERGROUP);
390 1.2.10.2 tls }
391 1.2.10.2 tls }
392 1.2.10.2 tls if (!nd->nd_repstat &&
393 1.2.10.2 tls NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_SIZE)) {
394 1.2.10.2 tls NFSVNO_ATTRINIT(&nva2);
395 1.2.10.2 tls NFSVNO_SETATTRVAL(&nva2, size, nva.na_size);
396 1.2.10.2 tls nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p,
397 1.2.10.2 tls exp);
398 1.2.10.2 tls if (!nd->nd_repstat)
399 1.2.10.2 tls NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_SIZE);
400 1.2.10.2 tls }
401 1.2.10.2 tls if (!nd->nd_repstat &&
402 1.2.10.2 tls (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESSSET) ||
403 1.2.10.2 tls NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFYSET))) {
404 1.2.10.2 tls NFSVNO_ATTRINIT(&nva2);
405 1.2.10.2 tls NFSVNO_SETATTRVAL(&nva2, atime, nva.na_atime);
406 1.2.10.2 tls NFSVNO_SETATTRVAL(&nva2, mtime, nva.na_mtime);
407 1.2.10.2 tls if (nva.na_vaflags & VA_UTIMES_NULL) {
408 1.2.10.2 tls nva2.na_vaflags |= VA_UTIMES_NULL;
409 1.2.10.2 tls NFSVNO_SETACTIVE(&nva2, vaflags);
410 1.2.10.2 tls }
411 1.2.10.2 tls nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p,
412 1.2.10.2 tls exp);
413 1.2.10.2 tls if (!nd->nd_repstat) {
414 1.2.10.2 tls if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESSSET))
415 1.2.10.2 tls NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_TIMEACCESSSET);
416 1.2.10.2 tls if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFYSET))
417 1.2.10.2 tls NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_TIMEMODIFYSET);
418 1.2.10.2 tls }
419 1.2.10.2 tls }
420 1.2.10.2 tls if (!nd->nd_repstat &&
421 1.2.10.2 tls NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODE)) {
422 1.2.10.2 tls NFSVNO_ATTRINIT(&nva2);
423 1.2.10.2 tls NFSVNO_SETATTRVAL(&nva2, mode, nva.na_mode);
424 1.2.10.2 tls nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p,
425 1.2.10.2 tls exp);
426 1.2.10.2 tls if (!nd->nd_repstat)
427 1.2.10.2 tls NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_MODE);
428 1.2.10.2 tls }
429 1.2.10.2 tls
430 1.2.10.2 tls #ifdef NFS4_ACL_EXTATTR_NAME
431 1.2.10.2 tls if (!nd->nd_repstat && aclp->acl_cnt > 0 &&
432 1.2.10.2 tls NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_ACL)) {
433 1.2.10.2 tls nd->nd_repstat = nfsrv_setacl(vp, aclp, nd->nd_cred, p);
434 1.2.10.2 tls if (!nd->nd_repstat)
435 1.2.10.2 tls NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_ACL);
436 1.2.10.2 tls }
437 1.2.10.2 tls #endif
438 1.2.10.2 tls } else if (!nd->nd_repstat) {
439 1.2.10.2 tls nd->nd_repstat = nfsvno_setattr(vp, &nva, nd->nd_cred, p,
440 1.2.10.2 tls exp);
441 1.2.10.2 tls }
442 1.2.10.2 tls if (nd->nd_flag & (ND_NFSV2 | ND_NFSV3)) {
443 1.2.10.2 tls postat_ret = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1);
444 1.2.10.2 tls if (!nd->nd_repstat)
445 1.2.10.2 tls nd->nd_repstat = postat_ret;
446 1.2.10.2 tls }
447 1.2.10.2 tls vput(vp);
448 1.2.10.2 tls #ifdef NFS4_ACL_EXTATTR_NAME
449 1.2.10.2 tls acl_free(aclp);
450 1.2.10.2 tls #endif
451 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
452 1.2.10.2 tls nfsrv_wcc(nd, preat_ret, &nva2, postat_ret, &nva);
453 1.2.10.2 tls else if (nd->nd_flag & ND_NFSV4)
454 1.2.10.2 tls (void) nfsrv_putattrbit(nd, &retbits);
455 1.2.10.2 tls else if (!nd->nd_repstat)
456 1.2.10.2 tls nfsrv_fillattr(nd, &nva);
457 1.2.10.2 tls
458 1.2.10.2 tls out:
459 1.2.10.2 tls NFSEXITCODE2(0, nd);
460 1.2.10.2 tls return (0);
461 1.2.10.2 tls nfsmout:
462 1.2.10.2 tls vput(vp);
463 1.2.10.2 tls #ifdef NFS4_ACL_EXTATTR_NAME
464 1.2.10.2 tls acl_free(aclp);
465 1.2.10.2 tls #endif
466 1.2.10.2 tls if (nd->nd_flag & ND_NFSV4) {
467 1.2.10.2 tls /*
468 1.2.10.2 tls * For all nd_repstat, the V4 reply includes a bitmap,
469 1.2.10.2 tls * even NFSERR_BADXDR, which is what this will end up
470 1.2.10.2 tls * returning.
471 1.2.10.2 tls */
472 1.2.10.2 tls (void) nfsrv_putattrbit(nd, &retbits);
473 1.2.10.2 tls }
474 1.2.10.2 tls NFSEXITCODE2(error, nd);
475 1.2.10.2 tls return (error);
476 1.2.10.2 tls }
477 1.2.10.2 tls
478 1.2.10.2 tls /*
479 1.2.10.2 tls * nfs lookup rpc
480 1.2.10.2 tls * (Also performs lookup parent for v4)
481 1.2.10.2 tls */
482 1.2.10.2 tls APPLESTATIC int
483 1.2.10.2 tls nfsrvd_lookup(struct nfsrv_descript *nd, __unused int isdgram,
484 1.2.10.2 tls vnode_t dp, vnode_t *vpp, fhandle_t *fhp, NFSPROC_T *p,
485 1.2.10.2 tls struct nfsexstuff *exp)
486 1.2.10.2 tls {
487 1.2.10.2 tls struct nameidata named;
488 1.2.10.2 tls vnode_t vp, dirp = NULL;
489 1.2.10.2 tls int error = 0, dattr_ret = 1;
490 1.2.10.2 tls struct nfsvattr nva, dattr;
491 1.2.10.2 tls char *bufp;
492 1.2.10.2 tls u_long *hashp;
493 1.2.10.2 tls
494 1.2.10.2 tls if (nd->nd_repstat) {
495 1.2.10.2 tls nfsrv_postopattr(nd, dattr_ret, &dattr);
496 1.2.10.2 tls goto out;
497 1.2.10.2 tls }
498 1.2.10.2 tls
499 1.2.10.2 tls /*
500 1.2.10.2 tls * For some reason, if dp is a symlink, the error
501 1.2.10.2 tls * returned is supposed to be NFSERR_SYMLINK and not NFSERR_NOTDIR.
502 1.2.10.2 tls */
503 1.2.10.2 tls if (dp->v_type == VLNK && (nd->nd_flag & ND_NFSV4)) {
504 1.2.10.2 tls nd->nd_repstat = NFSERR_SYMLINK;
505 1.2.10.2 tls vrele(dp);
506 1.2.10.2 tls goto out;
507 1.2.10.2 tls }
508 1.2.10.2 tls
509 1.2.10.2 tls NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP,
510 1.2.10.2 tls LOCKLEAF | SAVESTART);
511 1.2.10.2 tls nfsvno_setpathbuf(&named, &bufp, &hashp);
512 1.2.10.2 tls error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
513 1.2.10.2 tls if (error) {
514 1.2.10.2 tls vrele(dp);
515 1.2.10.2 tls nfsvno_relpathbuf(&named);
516 1.2.10.2 tls goto out;
517 1.2.10.2 tls }
518 1.2.10.2 tls if (!nd->nd_repstat) {
519 1.2.10.2 tls nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp);
520 1.2.10.2 tls } else {
521 1.2.10.2 tls vrele(dp);
522 1.2.10.2 tls nfsvno_relpathbuf(&named);
523 1.2.10.2 tls }
524 1.2.10.2 tls if (nd->nd_repstat) {
525 1.2.10.2 tls if (dirp) {
526 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
527 1.2.10.2 tls dattr_ret = nfsvno_getattr(dirp, &dattr,
528 1.2.10.2 tls nd->nd_cred, p, 0);
529 1.2.10.2 tls vrele(dirp);
530 1.2.10.2 tls }
531 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
532 1.2.10.2 tls nfsrv_postopattr(nd, dattr_ret, &dattr);
533 1.2.10.2 tls goto out;
534 1.2.10.2 tls }
535 1.2.10.2 tls if (named.ni_startdir)
536 1.2.10.2 tls vrele(named.ni_startdir);
537 1.2.10.2 tls nfsvno_relpathbuf(&named);
538 1.2.10.2 tls vp = named.ni_vp;
539 1.2.10.2 tls if ((nd->nd_flag & ND_NFSV4) != 0 && !NFSVNO_EXPORTED(exp) &&
540 1.2.10.2 tls vp->v_type != VDIR && vp->v_type != VLNK)
541 1.2.10.2 tls /*
542 1.2.10.2 tls * Only allow lookup of VDIR and VLNK for traversal of
543 1.2.10.2 tls * non-exported volumes during NFSv4 mounting.
544 1.2.10.2 tls */
545 1.2.10.2 tls nd->nd_repstat = ENOENT;
546 1.2.10.2 tls if (nd->nd_repstat == 0)
547 1.2.10.2 tls nd->nd_repstat = nfsvno_getfh(vp, fhp, p);
548 1.2.10.2 tls if (!(nd->nd_flag & ND_NFSV4) && !nd->nd_repstat)
549 1.2.10.2 tls nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1);
550 1.2.10.2 tls if (vpp != NULL && nd->nd_repstat == 0)
551 1.2.10.2 tls *vpp = vp;
552 1.2.10.2 tls else
553 1.2.10.2 tls vput(vp);
554 1.2.10.2 tls if (dirp) {
555 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
556 1.2.10.2 tls dattr_ret = nfsvno_getattr(dirp, &dattr, nd->nd_cred,
557 1.2.10.2 tls p, 0);
558 1.2.10.2 tls vrele(dirp);
559 1.2.10.2 tls }
560 1.2.10.2 tls if (nd->nd_repstat) {
561 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
562 1.2.10.2 tls nfsrv_postopattr(nd, dattr_ret, &dattr);
563 1.2.10.2 tls goto out;
564 1.2.10.2 tls }
565 1.2.10.2 tls if (nd->nd_flag & ND_NFSV2) {
566 1.2.10.2 tls (void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 0);
567 1.2.10.2 tls nfsrv_fillattr(nd, &nva);
568 1.2.10.2 tls } else if (nd->nd_flag & ND_NFSV3) {
569 1.2.10.2 tls (void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 0);
570 1.2.10.2 tls nfsrv_postopattr(nd, 0, &nva);
571 1.2.10.2 tls nfsrv_postopattr(nd, dattr_ret, &dattr);
572 1.2.10.2 tls }
573 1.2.10.2 tls
574 1.2.10.2 tls out:
575 1.2.10.2 tls NFSEXITCODE2(error, nd);
576 1.2.10.2 tls return (error);
577 1.2.10.2 tls }
578 1.2.10.2 tls
579 1.2.10.2 tls /*
580 1.2.10.2 tls * nfs readlink service
581 1.2.10.2 tls */
582 1.2.10.2 tls APPLESTATIC int
583 1.2.10.2 tls nfsrvd_readlink(struct nfsrv_descript *nd, __unused int isdgram,
584 1.2.10.2 tls vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp)
585 1.2.10.2 tls {
586 1.2.10.2 tls u_int32_t *tl;
587 1.2.10.2 tls mbuf_t mp = NULL, mpend = NULL;
588 1.2.10.2 tls int getret = 1, len;
589 1.2.10.2 tls struct nfsvattr nva;
590 1.2.10.2 tls
591 1.2.10.2 tls if (nd->nd_repstat) {
592 1.2.10.2 tls nfsrv_postopattr(nd, getret, &nva);
593 1.2.10.2 tls goto out;
594 1.2.10.2 tls }
595 1.2.10.2 tls if (vnode_vtype(vp) != VLNK) {
596 1.2.10.2 tls if (nd->nd_flag & ND_NFSV2)
597 1.2.10.2 tls nd->nd_repstat = ENXIO;
598 1.2.10.2 tls else
599 1.2.10.2 tls nd->nd_repstat = EINVAL;
600 1.2.10.2 tls }
601 1.2.10.2 tls if (!nd->nd_repstat)
602 1.2.10.2 tls nd->nd_repstat = nfsvno_readlink(vp, nd->nd_cred, p,
603 1.2.10.2 tls &mp, &mpend, &len);
604 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
605 1.2.10.2 tls getret = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1);
606 1.2.10.2 tls vput(vp);
607 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
608 1.2.10.2 tls nfsrv_postopattr(nd, getret, &nva);
609 1.2.10.2 tls if (nd->nd_repstat)
610 1.2.10.2 tls goto out;
611 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
612 1.2.10.2 tls *tl = txdr_unsigned(len);
613 1.2.10.2 tls mbuf_setnext(nd->nd_mb, mp);
614 1.2.10.2 tls nd->nd_mb = mpend;
615 1.2.10.2 tls nd->nd_bpos = NFSMTOD(mpend, caddr_t) + mbuf_len(mpend);
616 1.2.10.2 tls
617 1.2.10.2 tls out:
618 1.2.10.2 tls NFSEXITCODE2(0, nd);
619 1.2.10.2 tls return (0);
620 1.2.10.2 tls }
621 1.2.10.2 tls
622 1.2.10.2 tls /*
623 1.2.10.2 tls * nfs read service
624 1.2.10.2 tls */
625 1.2.10.2 tls APPLESTATIC int
626 1.2.10.2 tls nfsrvd_read(struct nfsrv_descript *nd, __unused int isdgram,
627 1.2.10.2 tls vnode_t vp, NFSPROC_T *p, struct nfsexstuff *exp)
628 1.2.10.2 tls {
629 1.2.10.2 tls u_int32_t *tl;
630 1.2.10.2 tls int error = 0, cnt, getret = 1, reqlen, eof = 0;
631 1.2.10.2 tls mbuf_t m2, m3;
632 1.2.10.2 tls struct nfsvattr nva;
633 1.2.10.2 tls off_t off = 0x0;
634 1.2.10.2 tls struct nfsstate st, *stp = &st;
635 1.2.10.2 tls struct nfslock lo, *lop = &lo;
636 1.2.10.2 tls nfsv4stateid_t stateid;
637 1.2.10.2 tls nfsquad_t clientid;
638 1.2.10.2 tls
639 1.2.10.2 tls if (nd->nd_repstat) {
640 1.2.10.2 tls nfsrv_postopattr(nd, getret, &nva);
641 1.2.10.2 tls goto out;
642 1.2.10.2 tls }
643 1.2.10.2 tls if (nd->nd_flag & ND_NFSV2) {
644 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
645 1.2.10.2 tls off = (off_t)fxdr_unsigned(u_int32_t, *tl++);
646 1.2.10.2 tls reqlen = fxdr_unsigned(int, *tl);
647 1.2.10.2 tls } else if (nd->nd_flag & ND_NFSV3) {
648 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
649 1.2.10.2 tls off = fxdr_hyper(tl);
650 1.2.10.2 tls tl += 2;
651 1.2.10.2 tls reqlen = fxdr_unsigned(int, *tl);
652 1.2.10.2 tls } else {
653 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + 3*NFSX_UNSIGNED);
654 1.2.10.2 tls reqlen = fxdr_unsigned(int, *(tl + 6));
655 1.2.10.2 tls }
656 1.2.10.2 tls if (reqlen > NFS_SRVMAXDATA(nd)) {
657 1.2.10.2 tls reqlen = NFS_SRVMAXDATA(nd);
658 1.2.10.2 tls } else if (reqlen < 0) {
659 1.2.10.2 tls error = EBADRPC;
660 1.2.10.2 tls goto nfsmout;
661 1.2.10.2 tls }
662 1.2.10.2 tls if (nd->nd_flag & ND_NFSV4) {
663 1.2.10.2 tls stp->ls_flags = (NFSLCK_CHECK | NFSLCK_READACCESS);
664 1.2.10.2 tls lop->lo_flags = NFSLCK_READ;
665 1.2.10.2 tls stp->ls_ownerlen = 0;
666 1.2.10.2 tls stp->ls_op = NULL;
667 1.2.10.2 tls stp->ls_uid = nd->nd_cred->cr_uid;
668 1.2.10.2 tls stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
669 1.2.10.2 tls clientid.lval[0] = stp->ls_stateid.other[0] = *tl++;
670 1.2.10.2 tls clientid.lval[1] = stp->ls_stateid.other[1] = *tl++;
671 1.2.10.2 tls if (nd->nd_flag & ND_IMPLIEDCLID) {
672 1.2.10.2 tls if (nd->nd_clientid.qval != clientid.qval)
673 1.2.10.2 tls printf("EEK! multiple clids\n");
674 1.2.10.2 tls } else {
675 1.2.10.2 tls nd->nd_flag |= ND_IMPLIEDCLID;
676 1.2.10.2 tls nd->nd_clientid.qval = clientid.qval;
677 1.2.10.2 tls }
678 1.2.10.2 tls stp->ls_stateid.other[2] = *tl++;
679 1.2.10.2 tls off = fxdr_hyper(tl);
680 1.2.10.2 tls lop->lo_first = off;
681 1.2.10.2 tls tl += 2;
682 1.2.10.2 tls lop->lo_end = off + reqlen;
683 1.2.10.2 tls /*
684 1.2.10.2 tls * Paranoia, just in case it wraps around.
685 1.2.10.2 tls */
686 1.2.10.2 tls if (lop->lo_end < off)
687 1.2.10.2 tls lop->lo_end = NFS64BITSSET;
688 1.2.10.2 tls }
689 1.2.10.2 tls if (vnode_vtype(vp) != VREG) {
690 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
691 1.2.10.2 tls nd->nd_repstat = EINVAL;
692 1.2.10.2 tls else
693 1.2.10.2 tls nd->nd_repstat = (vnode_vtype(vp) == VDIR) ? EISDIR :
694 1.2.10.2 tls EINVAL;
695 1.2.10.2 tls }
696 1.2.10.2 tls getret = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1);
697 1.2.10.2 tls if (!nd->nd_repstat)
698 1.2.10.2 tls nd->nd_repstat = getret;
699 1.2.10.2 tls if (!nd->nd_repstat &&
700 1.2.10.2 tls (nva.na_uid != nd->nd_cred->cr_uid ||
701 1.2.10.2 tls NFSVNO_EXSTRICTACCESS(exp))) {
702 1.2.10.2 tls nd->nd_repstat = nfsvno_accchk(vp, VREAD,
703 1.2.10.2 tls nd->nd_cred, exp, p,
704 1.2.10.2 tls NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, NULL);
705 1.2.10.2 tls if (nd->nd_repstat)
706 1.2.10.2 tls nd->nd_repstat = nfsvno_accchk(vp, VEXEC,
707 1.2.10.2 tls nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER,
708 1.2.10.2 tls NFSACCCHK_VPISLOCKED, NULL);
709 1.2.10.2 tls }
710 1.2.10.2 tls if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat)
711 1.2.10.2 tls nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid,
712 1.2.10.2 tls &stateid, exp, nd, p);
713 1.2.10.2 tls if (nd->nd_repstat) {
714 1.2.10.2 tls vput(vp);
715 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
716 1.2.10.2 tls nfsrv_postopattr(nd, getret, &nva);
717 1.2.10.2 tls goto out;
718 1.2.10.2 tls }
719 1.2.10.2 tls if (off >= nva.na_size) {
720 1.2.10.2 tls cnt = 0;
721 1.2.10.2 tls eof = 1;
722 1.2.10.2 tls } else if (reqlen == 0)
723 1.2.10.2 tls cnt = 0;
724 1.2.10.2 tls else if ((off + reqlen) >= nva.na_size) {
725 1.2.10.2 tls cnt = nva.na_size - off;
726 1.2.10.2 tls eof = 1;
727 1.2.10.2 tls } else
728 1.2.10.2 tls cnt = reqlen;
729 1.2.10.2 tls m3 = NULL;
730 1.2.10.2 tls if (cnt > 0) {
731 1.2.10.2 tls nd->nd_repstat = nfsvno_read(vp, off, cnt, nd->nd_cred, p,
732 1.2.10.2 tls &m3, &m2);
733 1.2.10.2 tls if (!(nd->nd_flag & ND_NFSV4)) {
734 1.2.10.2 tls getret = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1);
735 1.2.10.2 tls if (!nd->nd_repstat)
736 1.2.10.2 tls nd->nd_repstat = getret;
737 1.2.10.2 tls }
738 1.2.10.2 tls if (nd->nd_repstat) {
739 1.2.10.2 tls vput(vp);
740 1.2.10.2 tls if (m3)
741 1.2.10.2 tls mbuf_freem(m3);
742 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
743 1.2.10.2 tls nfsrv_postopattr(nd, getret, &nva);
744 1.2.10.2 tls goto out;
745 1.2.10.2 tls }
746 1.2.10.2 tls }
747 1.2.10.2 tls vput(vp);
748 1.2.10.2 tls if (nd->nd_flag & ND_NFSV2) {
749 1.2.10.2 tls nfsrv_fillattr(nd, &nva);
750 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
751 1.2.10.2 tls } else {
752 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3) {
753 1.2.10.2 tls nfsrv_postopattr(nd, getret, &nva);
754 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
755 1.2.10.2 tls *tl++ = txdr_unsigned(cnt);
756 1.2.10.2 tls } else
757 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
758 1.2.10.2 tls if (eof)
759 1.2.10.2 tls *tl++ = newnfs_true;
760 1.2.10.2 tls else
761 1.2.10.2 tls *tl++ = newnfs_false;
762 1.2.10.2 tls }
763 1.2.10.2 tls *tl = txdr_unsigned(cnt);
764 1.2.10.2 tls if (m3) {
765 1.2.10.2 tls mbuf_setnext(nd->nd_mb, m3);
766 1.2.10.2 tls nd->nd_mb = m2;
767 1.2.10.2 tls nd->nd_bpos = NFSMTOD(m2, caddr_t) + mbuf_len(m2);
768 1.2.10.2 tls }
769 1.2.10.2 tls
770 1.2.10.2 tls out:
771 1.2.10.2 tls NFSEXITCODE2(0, nd);
772 1.2.10.2 tls return (0);
773 1.2.10.2 tls nfsmout:
774 1.2.10.2 tls vput(vp);
775 1.2.10.2 tls NFSEXITCODE2(error, nd);
776 1.2.10.2 tls return (error);
777 1.2.10.2 tls }
778 1.2.10.2 tls
779 1.2.10.2 tls /*
780 1.2.10.2 tls * nfs write service
781 1.2.10.2 tls */
782 1.2.10.2 tls APPLESTATIC int
783 1.2.10.2 tls nfsrvd_write(struct nfsrv_descript *nd, __unused int isdgram,
784 1.2.10.2 tls vnode_t vp, NFSPROC_T *p, struct nfsexstuff *exp)
785 1.2.10.2 tls {
786 1.2.10.2 tls int i, cnt;
787 1.2.10.2 tls u_int32_t *tl;
788 1.2.10.2 tls mbuf_t mp;
789 1.2.10.2 tls struct nfsvattr nva, forat;
790 1.2.10.2 tls int aftat_ret = 1, retlen, len, error = 0, forat_ret = 1;
791 1.2.10.2 tls int stable = NFSWRITE_FILESYNC;
792 1.2.10.2 tls off_t off;
793 1.2.10.2 tls struct nfsstate st, *stp = &st;
794 1.2.10.2 tls struct nfslock lo, *lop = &lo;
795 1.2.10.2 tls nfsv4stateid_t stateid;
796 1.2.10.2 tls nfsquad_t clientid;
797 1.2.10.2 tls
798 1.2.10.2 tls if (nd->nd_repstat) {
799 1.2.10.2 tls nfsrv_wcc(nd, forat_ret, &forat, aftat_ret, &nva);
800 1.2.10.2 tls goto out;
801 1.2.10.2 tls }
802 1.2.10.2 tls if (nd->nd_flag & ND_NFSV2) {
803 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
804 1.2.10.2 tls off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
805 1.2.10.2 tls tl += 2;
806 1.2.10.2 tls retlen = len = fxdr_unsigned(int32_t, *tl);
807 1.2.10.2 tls } else if (nd->nd_flag & ND_NFSV3) {
808 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
809 1.2.10.2 tls off = fxdr_hyper(tl);
810 1.2.10.2 tls tl += 3;
811 1.2.10.2 tls stable = fxdr_unsigned(int, *tl++);
812 1.2.10.2 tls retlen = len = fxdr_unsigned(int32_t, *tl);
813 1.2.10.2 tls } else {
814 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + 4 * NFSX_UNSIGNED);
815 1.2.10.2 tls stp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS);
816 1.2.10.2 tls lop->lo_flags = NFSLCK_WRITE;
817 1.2.10.2 tls stp->ls_ownerlen = 0;
818 1.2.10.2 tls stp->ls_op = NULL;
819 1.2.10.2 tls stp->ls_uid = nd->nd_cred->cr_uid;
820 1.2.10.2 tls stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
821 1.2.10.2 tls clientid.lval[0] = stp->ls_stateid.other[0] = *tl++;
822 1.2.10.2 tls clientid.lval[1] = stp->ls_stateid.other[1] = *tl++;
823 1.2.10.2 tls if (nd->nd_flag & ND_IMPLIEDCLID) {
824 1.2.10.2 tls if (nd->nd_clientid.qval != clientid.qval)
825 1.2.10.2 tls printf("EEK! multiple clids\n");
826 1.2.10.2 tls } else {
827 1.2.10.2 tls nd->nd_flag |= ND_IMPLIEDCLID;
828 1.2.10.2 tls nd->nd_clientid.qval = clientid.qval;
829 1.2.10.2 tls }
830 1.2.10.2 tls stp->ls_stateid.other[2] = *tl++;
831 1.2.10.2 tls off = fxdr_hyper(tl);
832 1.2.10.2 tls lop->lo_first = off;
833 1.2.10.2 tls tl += 2;
834 1.2.10.2 tls stable = fxdr_unsigned(int, *tl++);
835 1.2.10.2 tls retlen = len = fxdr_unsigned(int32_t, *tl);
836 1.2.10.2 tls lop->lo_end = off + len;
837 1.2.10.2 tls /*
838 1.2.10.2 tls * Paranoia, just in case it wraps around, which shouldn't
839 1.2.10.2 tls * ever happen anyhow.
840 1.2.10.2 tls */
841 1.2.10.2 tls if (lop->lo_end < lop->lo_first)
842 1.2.10.2 tls lop->lo_end = NFS64BITSSET;
843 1.2.10.2 tls }
844 1.2.10.2 tls
845 1.2.10.2 tls /*
846 1.2.10.2 tls * Loop through the mbuf chain, counting how many mbufs are a
847 1.2.10.2 tls * part of this write operation, so the iovec size is known.
848 1.2.10.2 tls */
849 1.2.10.2 tls cnt = 0;
850 1.2.10.2 tls mp = nd->nd_md;
851 1.2.10.2 tls i = NFSMTOD(mp, caddr_t) + mbuf_len(mp) - nd->nd_dpos;
852 1.2.10.2 tls while (len > 0) {
853 1.2.10.2 tls if (i > 0) {
854 1.2.10.2 tls len -= i;
855 1.2.10.2 tls cnt++;
856 1.2.10.2 tls }
857 1.2.10.2 tls mp = mbuf_next(mp);
858 1.2.10.2 tls if (!mp) {
859 1.2.10.2 tls if (len > 0) {
860 1.2.10.2 tls error = EBADRPC;
861 1.2.10.2 tls goto nfsmout;
862 1.2.10.2 tls }
863 1.2.10.2 tls } else
864 1.2.10.2 tls i = mbuf_len(mp);
865 1.2.10.2 tls }
866 1.2.10.2 tls
867 1.2.10.2 tls if (retlen > NFS_MAXDATA || retlen < 0)
868 1.2.10.2 tls nd->nd_repstat = EIO;
869 1.2.10.2 tls if (vnode_vtype(vp) != VREG && !nd->nd_repstat) {
870 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
871 1.2.10.2 tls nd->nd_repstat = EINVAL;
872 1.2.10.2 tls else
873 1.2.10.2 tls nd->nd_repstat = (vnode_vtype(vp) == VDIR) ? EISDIR :
874 1.2.10.2 tls EINVAL;
875 1.2.10.2 tls }
876 1.2.10.2 tls forat_ret = nfsvno_getattr(vp, &forat, nd->nd_cred, p, 1);
877 1.2.10.2 tls if (!nd->nd_repstat)
878 1.2.10.2 tls nd->nd_repstat = forat_ret;
879 1.2.10.2 tls if (!nd->nd_repstat &&
880 1.2.10.2 tls (forat.na_uid != nd->nd_cred->cr_uid ||
881 1.2.10.2 tls NFSVNO_EXSTRICTACCESS(exp)))
882 1.2.10.2 tls nd->nd_repstat = nfsvno_accchk(vp, VWRITE,
883 1.2.10.2 tls nd->nd_cred, exp, p,
884 1.2.10.2 tls NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, NULL);
885 1.2.10.2 tls if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) {
886 1.2.10.2 tls nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid,
887 1.2.10.2 tls &stateid, exp, nd, p);
888 1.2.10.2 tls }
889 1.2.10.2 tls if (nd->nd_repstat) {
890 1.2.10.2 tls vput(vp);
891 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
892 1.2.10.2 tls nfsrv_wcc(nd, forat_ret, &forat, aftat_ret, &nva);
893 1.2.10.2 tls goto out;
894 1.2.10.2 tls }
895 1.2.10.2 tls
896 1.2.10.2 tls /*
897 1.2.10.2 tls * For NFS Version 2, it is not obvious what a write of zero length
898 1.2.10.2 tls * should do, but I might as well be consistent with Version 3,
899 1.2.10.2 tls * which is to return ok so long as there are no permission problems.
900 1.2.10.2 tls */
901 1.2.10.2 tls if (retlen > 0) {
902 1.2.10.2 tls nd->nd_repstat = nfsvno_write(vp, off, retlen, cnt, stable,
903 1.2.10.2 tls nd->nd_md, nd->nd_dpos, nd->nd_cred, p);
904 1.2.10.2 tls error = nfsm_advance(nd, NFSM_RNDUP(retlen), -1);
905 1.2.10.2 tls if (error)
906 1.2.10.2 tls panic("nfsrv_write mbuf");
907 1.2.10.2 tls }
908 1.2.10.2 tls if (nd->nd_flag & ND_NFSV4)
909 1.2.10.2 tls aftat_ret = 0;
910 1.2.10.2 tls else
911 1.2.10.2 tls aftat_ret = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1);
912 1.2.10.2 tls vput(vp);
913 1.2.10.2 tls if (!nd->nd_repstat)
914 1.2.10.2 tls nd->nd_repstat = aftat_ret;
915 1.2.10.2 tls if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
916 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
917 1.2.10.2 tls nfsrv_wcc(nd, forat_ret, &forat, aftat_ret, &nva);
918 1.2.10.2 tls if (nd->nd_repstat)
919 1.2.10.2 tls goto out;
920 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
921 1.2.10.2 tls *tl++ = txdr_unsigned(retlen);
922 1.2.10.2 tls /*
923 1.2.10.2 tls * If nfs_async is set, then pretend the write was FILESYNC.
924 1.2.10.2 tls * Warning: Doing this violates RFC1813 and runs a risk
925 1.2.10.2 tls * of data written by a client being lost when the server
926 1.2.10.2 tls * crashes/reboots.
927 1.2.10.2 tls */
928 1.2.10.2 tls if (stable == NFSWRITE_UNSTABLE && nfs_async == 0)
929 1.2.10.2 tls *tl++ = txdr_unsigned(stable);
930 1.2.10.2 tls else
931 1.2.10.2 tls *tl++ = txdr_unsigned(NFSWRITE_FILESYNC);
932 1.2.10.2 tls /*
933 1.2.10.2 tls * Actually, there is no need to txdr these fields,
934 1.2.10.2 tls * but it may make the values more human readable,
935 1.2.10.2 tls * for debugging purposes.
936 1.2.10.2 tls */
937 1.2.10.2 tls *tl++ = txdr_unsigned(nfsboottime.tv_sec);
938 1.2.10.2 tls *tl = txdr_unsigned(nfsboottime.tv_usec);
939 1.2.10.2 tls } else if (!nd->nd_repstat)
940 1.2.10.2 tls nfsrv_fillattr(nd, &nva);
941 1.2.10.2 tls
942 1.2.10.2 tls out:
943 1.2.10.2 tls NFSEXITCODE2(0, nd);
944 1.2.10.2 tls return (0);
945 1.2.10.2 tls nfsmout:
946 1.2.10.2 tls vput(vp);
947 1.2.10.2 tls NFSEXITCODE2(error, nd);
948 1.2.10.2 tls return (error);
949 1.2.10.2 tls }
950 1.2.10.2 tls
951 1.2.10.2 tls /*
952 1.2.10.2 tls * nfs create service (creates regular files for V2 and V3. Spec. files for V2.)
953 1.2.10.2 tls * now does a truncate to 0 length via. setattr if it already exists
954 1.2.10.2 tls * The core creation routine has been extracted out into nfsrv_creatsub(),
955 1.2.10.2 tls * so it can also be used by nfsrv_open() for V4.
956 1.2.10.2 tls */
957 1.2.10.2 tls APPLESTATIC int
958 1.2.10.2 tls nfsrvd_create(struct nfsrv_descript *nd, __unused int isdgram,
959 1.2.10.2 tls vnode_t dp, NFSPROC_T *p, struct nfsexstuff *exp)
960 1.2.10.2 tls {
961 1.2.10.2 tls struct nfsvattr nva, dirfor, diraft;
962 1.2.10.2 tls struct nfsv2_sattr *sp;
963 1.2.10.2 tls struct nameidata named;
964 1.2.10.2 tls u_int32_t *tl;
965 1.2.10.2 tls int error = 0, tsize, dirfor_ret = 1, diraft_ret = 1;
966 1.2.10.2 tls int how = NFSCREATE_UNCHECKED, exclusive_flag = 0;
967 1.2.10.2 tls NFSDEV_T rdev = 0;
968 1.2.10.2 tls vnode_t vp = NULL, dirp = NULL;
969 1.2.10.2 tls fhandle_t fh;
970 1.2.10.2 tls char *bufp;
971 1.2.10.2 tls u_long *hashp;
972 1.2.10.2 tls enum vtype vtyp;
973 1.2.10.2 tls int32_t cverf[2], tverf[2] = { 0, 0 };
974 1.2.10.2 tls
975 1.2.10.2 tls if (nd->nd_repstat) {
976 1.2.10.2 tls nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
977 1.2.10.2 tls goto out;
978 1.2.10.2 tls }
979 1.2.10.2 tls NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
980 1.2.10.2 tls LOCKPARENT | LOCKLEAF | SAVESTART);
981 1.2.10.2 tls nfsvno_setpathbuf(&named, &bufp, &hashp);
982 1.2.10.2 tls error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
983 1.2.10.2 tls if (error)
984 1.2.10.2 tls goto nfsmout;
985 1.2.10.2 tls if (!nd->nd_repstat) {
986 1.2.10.2 tls NFSVNO_ATTRINIT(&nva);
987 1.2.10.2 tls if (nd->nd_flag & ND_NFSV2) {
988 1.2.10.2 tls NFSM_DISSECT(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
989 1.2.10.2 tls vtyp = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
990 1.2.10.2 tls if (vtyp == VNON)
991 1.2.10.2 tls vtyp = VREG;
992 1.2.10.2 tls NFSVNO_SETATTRVAL(&nva, type, vtyp);
993 1.2.10.2 tls NFSVNO_SETATTRVAL(&nva, mode,
994 1.2.10.2 tls nfstov_mode(sp->sa_mode));
995 1.2.10.2 tls switch (nva.na_type) {
996 1.2.10.2 tls case VREG:
997 1.2.10.2 tls tsize = fxdr_unsigned(int32_t, sp->sa_size);
998 1.2.10.2 tls if (tsize != -1)
999 1.2.10.2 tls NFSVNO_SETATTRVAL(&nva, size,
1000 1.2.10.2 tls (u_quad_t)tsize);
1001 1.2.10.2 tls break;
1002 1.2.10.2 tls case VCHR:
1003 1.2.10.2 tls case VBLK:
1004 1.2.10.2 tls case VFIFO:
1005 1.2.10.2 tls rdev = fxdr_unsigned(NFSDEV_T, sp->sa_size);
1006 1.2.10.2 tls break;
1007 1.2.10.2 tls default:
1008 1.2.10.2 tls break;
1009 1.2.10.2 tls };
1010 1.2.10.2 tls } else {
1011 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1012 1.2.10.2 tls how = fxdr_unsigned(int, *tl);
1013 1.2.10.2 tls switch (how) {
1014 1.2.10.2 tls case NFSCREATE_GUARDED:
1015 1.2.10.2 tls case NFSCREATE_UNCHECKED:
1016 1.2.10.2 tls error = nfsrv_sattr(nd, &nva, NULL, NULL, p);
1017 1.2.10.2 tls if (error)
1018 1.2.10.2 tls goto nfsmout;
1019 1.2.10.2 tls break;
1020 1.2.10.2 tls case NFSCREATE_EXCLUSIVE:
1021 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF);
1022 1.2.10.2 tls cverf[0] = *tl++;
1023 1.2.10.2 tls cverf[1] = *tl;
1024 1.2.10.2 tls exclusive_flag = 1;
1025 1.2.10.2 tls break;
1026 1.2.10.2 tls };
1027 1.2.10.2 tls NFSVNO_SETATTRVAL(&nva, type, VREG);
1028 1.2.10.2 tls }
1029 1.2.10.2 tls }
1030 1.2.10.2 tls if (nd->nd_repstat) {
1031 1.2.10.2 tls nfsvno_relpathbuf(&named);
1032 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3) {
1033 1.2.10.2 tls dirfor_ret = nfsvno_getattr(dp, &dirfor, nd->nd_cred,
1034 1.2.10.2 tls p, 1);
1035 1.2.10.2 tls nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
1036 1.2.10.2 tls &diraft);
1037 1.2.10.2 tls }
1038 1.2.10.2 tls vput(dp);
1039 1.2.10.2 tls goto out;
1040 1.2.10.2 tls }
1041 1.2.10.2 tls
1042 1.2.10.2 tls nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, p, &dirp);
1043 1.2.10.2 tls if (dirp) {
1044 1.2.10.2 tls if (nd->nd_flag & ND_NFSV2) {
1045 1.2.10.2 tls vrele(dirp);
1046 1.2.10.2 tls dirp = NULL;
1047 1.2.10.2 tls } else {
1048 1.2.10.2 tls dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd->nd_cred,
1049 1.2.10.2 tls p, 0);
1050 1.2.10.2 tls }
1051 1.2.10.2 tls }
1052 1.2.10.2 tls if (nd->nd_repstat) {
1053 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
1054 1.2.10.2 tls nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
1055 1.2.10.2 tls &diraft);
1056 1.2.10.2 tls if (dirp)
1057 1.2.10.2 tls vrele(dirp);
1058 1.2.10.2 tls goto out;
1059 1.2.10.2 tls }
1060 1.2.10.2 tls
1061 1.2.10.2 tls if (!(nd->nd_flag & ND_NFSV2)) {
1062 1.2.10.2 tls switch (how) {
1063 1.2.10.2 tls case NFSCREATE_GUARDED:
1064 1.2.10.2 tls if (named.ni_vp)
1065 1.2.10.2 tls nd->nd_repstat = EEXIST;
1066 1.2.10.2 tls break;
1067 1.2.10.2 tls case NFSCREATE_UNCHECKED:
1068 1.2.10.2 tls break;
1069 1.2.10.2 tls case NFSCREATE_EXCLUSIVE:
1070 1.2.10.2 tls if (named.ni_vp == NULL)
1071 1.2.10.2 tls NFSVNO_SETATTRVAL(&nva, mode, 0);
1072 1.2.10.2 tls break;
1073 1.2.10.2 tls };
1074 1.2.10.2 tls }
1075 1.2.10.2 tls
1076 1.2.10.2 tls /*
1077 1.2.10.2 tls * Iff doesn't exist, create it
1078 1.2.10.2 tls * otherwise just truncate to 0 length
1079 1.2.10.2 tls * should I set the mode too ?
1080 1.2.10.2 tls */
1081 1.2.10.2 tls nd->nd_repstat = nfsvno_createsub(nd, &named, &vp, &nva,
1082 1.2.10.2 tls &exclusive_flag, cverf, rdev, p, exp);
1083 1.2.10.2 tls
1084 1.2.10.2 tls if (!nd->nd_repstat) {
1085 1.2.10.2 tls nd->nd_repstat = nfsvno_getfh(vp, &fh, p);
1086 1.2.10.2 tls if (!nd->nd_repstat)
1087 1.2.10.2 tls nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred,
1088 1.2.10.2 tls p, 1);
1089 1.2.10.2 tls vput(vp);
1090 1.2.10.2 tls if (!nd->nd_repstat) {
1091 1.2.10.2 tls tverf[0] = nva.na_atime.tv_sec;
1092 1.2.10.2 tls tverf[1] = nva.na_atime.tv_nsec;
1093 1.2.10.2 tls }
1094 1.2.10.2 tls }
1095 1.2.10.2 tls if (nd->nd_flag & ND_NFSV2) {
1096 1.2.10.2 tls if (!nd->nd_repstat) {
1097 1.2.10.2 tls (void) nfsm_fhtom(nd, (u_int8_t *)&fh, 0, 0);
1098 1.2.10.2 tls nfsrv_fillattr(nd, &nva);
1099 1.2.10.2 tls }
1100 1.2.10.2 tls } else {
1101 1.2.10.2 tls if (exclusive_flag && !nd->nd_repstat && (cverf[0] != tverf[0]
1102 1.2.10.2 tls || cverf[1] != tverf[1]))
1103 1.2.10.2 tls nd->nd_repstat = EEXIST;
1104 1.2.10.2 tls diraft_ret = nfsvno_getattr(dirp, &diraft, nd->nd_cred, p, 0);
1105 1.2.10.2 tls vrele(dirp);
1106 1.2.10.2 tls if (!nd->nd_repstat) {
1107 1.2.10.2 tls (void) nfsm_fhtom(nd, (u_int8_t *)&fh, 0, 1);
1108 1.2.10.2 tls nfsrv_postopattr(nd, 0, &nva);
1109 1.2.10.2 tls }
1110 1.2.10.2 tls nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1111 1.2.10.2 tls }
1112 1.2.10.2 tls
1113 1.2.10.2 tls out:
1114 1.2.10.2 tls NFSEXITCODE2(0, nd);
1115 1.2.10.2 tls return (0);
1116 1.2.10.2 tls nfsmout:
1117 1.2.10.2 tls vput(dp);
1118 1.2.10.2 tls nfsvno_relpathbuf(&named);
1119 1.2.10.2 tls NFSEXITCODE2(error, nd);
1120 1.2.10.2 tls return (error);
1121 1.2.10.2 tls }
1122 1.2.10.2 tls
1123 1.2.10.2 tls /*
1124 1.2.10.2 tls * nfs v3 mknod service (and v4 create)
1125 1.2.10.2 tls */
1126 1.2.10.2 tls APPLESTATIC int
1127 1.2.10.2 tls nfsrvd_mknod(struct nfsrv_descript *nd, __unused int isdgram,
1128 1.2.10.2 tls vnode_t dp, vnode_t *vpp, fhandle_t *fhp, NFSPROC_T *p,
1129 1.2.10.2 tls struct nfsexstuff *exp)
1130 1.2.10.2 tls {
1131 1.2.10.2 tls struct nfsvattr nva, dirfor, diraft;
1132 1.2.10.2 tls u_int32_t *tl;
1133 1.2.10.2 tls struct nameidata named;
1134 1.2.10.2 tls int error = 0, dirfor_ret = 1, diraft_ret = 1, pathlen;
1135 1.2.10.2 tls u_int32_t major, minor;
1136 1.2.10.2 tls enum vtype vtyp = VNON;
1137 1.2.10.2 tls nfstype nfs4type = NFNON;
1138 1.2.10.2 tls vnode_t vp, dirp = NULL;
1139 1.2.10.2 tls nfsattrbit_t attrbits;
1140 1.2.10.2 tls char *bufp = NULL, *pathcp = NULL;
1141 1.2.10.2 tls u_long *hashp, cnflags;
1142 1.2.10.2 tls NFSACL_T *aclp = NULL;
1143 1.2.10.2 tls
1144 1.2.10.2 tls NFSVNO_ATTRINIT(&nva);
1145 1.2.10.2 tls cnflags = (LOCKPARENT | SAVESTART);
1146 1.2.10.2 tls if (nd->nd_repstat) {
1147 1.2.10.2 tls nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1148 1.2.10.2 tls goto out;
1149 1.2.10.2 tls }
1150 1.2.10.2 tls #ifdef NFS4_ACL_EXTATTR_NAME
1151 1.2.10.2 tls aclp = acl_alloc(M_WAITOK);
1152 1.2.10.2 tls aclp->acl_cnt = 0;
1153 1.2.10.2 tls #endif
1154 1.2.10.2 tls
1155 1.2.10.2 tls /*
1156 1.2.10.2 tls * For V4, the creation stuff is here, Yuck!
1157 1.2.10.2 tls */
1158 1.2.10.2 tls if (nd->nd_flag & ND_NFSV4) {
1159 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1160 1.2.10.2 tls vtyp = nfsv34tov_type(*tl);
1161 1.2.10.2 tls nfs4type = fxdr_unsigned(nfstype, *tl);
1162 1.2.10.2 tls switch (nfs4type) {
1163 1.2.10.2 tls case NFLNK:
1164 1.2.10.2 tls error = nfsvno_getsymlink(nd, &nva, p, &pathcp,
1165 1.2.10.2 tls &pathlen);
1166 1.2.10.2 tls if (error)
1167 1.2.10.2 tls goto nfsmout;
1168 1.2.10.2 tls break;
1169 1.2.10.2 tls case NFCHR:
1170 1.2.10.2 tls case NFBLK:
1171 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1172 1.2.10.2 tls major = fxdr_unsigned(u_int32_t, *tl++);
1173 1.2.10.2 tls minor = fxdr_unsigned(u_int32_t, *tl);
1174 1.2.10.2 tls nva.na_rdev = NFSMAKEDEV(major, minor);
1175 1.2.10.2 tls break;
1176 1.2.10.2 tls case NFSOCK:
1177 1.2.10.2 tls case NFFIFO:
1178 1.2.10.2 tls break;
1179 1.2.10.2 tls case NFDIR:
1180 1.2.10.2 tls cnflags = (LOCKPARENT | SAVENAME);
1181 1.2.10.2 tls break;
1182 1.2.10.2 tls default:
1183 1.2.10.2 tls nd->nd_repstat = NFSERR_BADTYPE;
1184 1.2.10.2 tls vrele(dp);
1185 1.2.10.2 tls #ifdef NFS4_ACL_EXTATTR_NAME
1186 1.2.10.2 tls acl_free(aclp);
1187 1.2.10.2 tls #endif
1188 1.2.10.2 tls goto out;
1189 1.2.10.2 tls }
1190 1.2.10.2 tls }
1191 1.2.10.2 tls NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, cnflags);
1192 1.2.10.2 tls nfsvno_setpathbuf(&named, &bufp, &hashp);
1193 1.2.10.2 tls error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
1194 1.2.10.2 tls if (error)
1195 1.2.10.2 tls goto nfsmout;
1196 1.2.10.2 tls if (!nd->nd_repstat) {
1197 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3) {
1198 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1199 1.2.10.2 tls vtyp = nfsv34tov_type(*tl);
1200 1.2.10.2 tls }
1201 1.2.10.2 tls error = nfsrv_sattr(nd, &nva, &attrbits, aclp, p);
1202 1.2.10.2 tls if (error)
1203 1.2.10.2 tls goto nfsmout;
1204 1.2.10.2 tls nva.na_type = vtyp;
1205 1.2.10.2 tls if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV3) &&
1206 1.2.10.2 tls (vtyp == VCHR || vtyp == VBLK)) {
1207 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1208 1.2.10.2 tls major = fxdr_unsigned(u_int32_t, *tl++);
1209 1.2.10.2 tls minor = fxdr_unsigned(u_int32_t, *tl);
1210 1.2.10.2 tls nva.na_rdev = NFSMAKEDEV(major, minor);
1211 1.2.10.2 tls }
1212 1.2.10.2 tls }
1213 1.2.10.2 tls
1214 1.2.10.2 tls dirfor_ret = nfsvno_getattr(dp, &dirfor, nd->nd_cred, p, 0);
1215 1.2.10.2 tls if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV4)) {
1216 1.2.10.2 tls if (!dirfor_ret && NFSVNO_ISSETGID(&nva) &&
1217 1.2.10.2 tls dirfor.na_gid == nva.na_gid)
1218 1.2.10.2 tls NFSVNO_UNSET(&nva, gid);
1219 1.2.10.2 tls nd->nd_repstat = nfsrv_checkuidgid(nd, &nva);
1220 1.2.10.2 tls }
1221 1.2.10.2 tls if (nd->nd_repstat) {
1222 1.2.10.2 tls vrele(dp);
1223 1.2.10.2 tls #ifdef NFS4_ACL_EXTATTR_NAME
1224 1.2.10.2 tls acl_free(aclp);
1225 1.2.10.2 tls #endif
1226 1.2.10.2 tls nfsvno_relpathbuf(&named);
1227 1.2.10.2 tls if (pathcp)
1228 1.2.10.2 tls FREE(pathcp, M_TEMP);
1229 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
1230 1.2.10.2 tls nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
1231 1.2.10.2 tls &diraft);
1232 1.2.10.2 tls goto out;
1233 1.2.10.2 tls }
1234 1.2.10.2 tls
1235 1.2.10.2 tls /*
1236 1.2.10.2 tls * Yuck! For V4, mkdir and link are here and some V4 clients don't fill
1237 1.2.10.2 tls * in va_mode, so we'll have to set a default here.
1238 1.2.10.2 tls */
1239 1.2.10.2 tls if (NFSVNO_NOTSETMODE(&nva)) {
1240 1.2.10.2 tls if (vtyp == VLNK)
1241 1.2.10.2 tls nva.na_mode = 0755;
1242 1.2.10.2 tls else
1243 1.2.10.2 tls nva.na_mode = 0400;
1244 1.2.10.2 tls }
1245 1.2.10.2 tls
1246 1.2.10.2 tls if (vtyp == VDIR)
1247 1.2.10.2 tls named.ni_cnd.cn_flags |= WILLBEDIR;
1248 1.2.10.2 tls nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp);
1249 1.2.10.2 tls if (nd->nd_repstat) {
1250 1.2.10.2 tls if (dirp) {
1251 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
1252 1.2.10.2 tls dirfor_ret = nfsvno_getattr(dirp, &dirfor,
1253 1.2.10.2 tls nd->nd_cred, p, 0);
1254 1.2.10.2 tls vrele(dirp);
1255 1.2.10.2 tls }
1256 1.2.10.2 tls #ifdef NFS4_ACL_EXTATTR_NAME
1257 1.2.10.2 tls acl_free(aclp);
1258 1.2.10.2 tls #endif
1259 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
1260 1.2.10.2 tls nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
1261 1.2.10.2 tls &diraft);
1262 1.2.10.2 tls goto out;
1263 1.2.10.2 tls }
1264 1.2.10.2 tls if (dirp)
1265 1.2.10.2 tls dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd->nd_cred, p, 0);
1266 1.2.10.2 tls
1267 1.2.10.2 tls if ((nd->nd_flag & ND_NFSV4) && (vtyp == VDIR || vtyp == VLNK)) {
1268 1.2.10.2 tls if (vtyp == VDIR) {
1269 1.2.10.2 tls nfsrvd_mkdirsub(nd, &named, &nva, fhp, vpp, dirp,
1270 1.2.10.2 tls &dirfor, &diraft, &diraft_ret, &attrbits, aclp, p,
1271 1.2.10.2 tls exp);
1272 1.2.10.2 tls #ifdef NFS4_ACL_EXTATTR_NAME
1273 1.2.10.2 tls acl_free(aclp);
1274 1.2.10.2 tls #endif
1275 1.2.10.2 tls goto out;
1276 1.2.10.2 tls } else if (vtyp == VLNK) {
1277 1.2.10.2 tls nfsrvd_symlinksub(nd, &named, &nva, fhp, vpp, dirp,
1278 1.2.10.2 tls &dirfor, &diraft, &diraft_ret, &attrbits,
1279 1.2.10.2 tls aclp, p, exp, pathcp, pathlen);
1280 1.2.10.2 tls #ifdef NFS4_ACL_EXTATTR_NAME
1281 1.2.10.2 tls acl_free(aclp);
1282 1.2.10.2 tls #endif
1283 1.2.10.2 tls FREE(pathcp, M_TEMP);
1284 1.2.10.2 tls goto out;
1285 1.2.10.2 tls }
1286 1.2.10.2 tls }
1287 1.2.10.2 tls
1288 1.2.10.2 tls nd->nd_repstat = nfsvno_mknod(&named, &nva, nd->nd_cred, p);
1289 1.2.10.2 tls if (!nd->nd_repstat) {
1290 1.2.10.2 tls vp = named.ni_vp;
1291 1.2.10.2 tls nfsrv_fixattr(nd, vp, &nva, aclp, p, &attrbits, exp);
1292 1.2.10.2 tls nd->nd_repstat = nfsvno_getfh(vp, fhp, p);
1293 1.2.10.2 tls if ((nd->nd_flag & ND_NFSV3) && !nd->nd_repstat)
1294 1.2.10.2 tls nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred,
1295 1.2.10.2 tls p, 1);
1296 1.2.10.2 tls if (vpp != NULL && nd->nd_repstat == 0) {
1297 1.2.10.2 tls NFSVOPUNLOCK(vp, 0);
1298 1.2.10.2 tls *vpp = vp;
1299 1.2.10.2 tls } else
1300 1.2.10.2 tls vput(vp);
1301 1.2.10.2 tls }
1302 1.2.10.2 tls
1303 1.2.10.2 tls diraft_ret = nfsvno_getattr(dirp, &diraft, nd->nd_cred, p, 0);
1304 1.2.10.2 tls vrele(dirp);
1305 1.2.10.2 tls if (!nd->nd_repstat) {
1306 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3) {
1307 1.2.10.2 tls (void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 1);
1308 1.2.10.2 tls nfsrv_postopattr(nd, 0, &nva);
1309 1.2.10.2 tls } else {
1310 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1311 1.2.10.2 tls *tl++ = newnfs_false;
1312 1.2.10.2 tls txdr_hyper(dirfor.na_filerev, tl);
1313 1.2.10.2 tls tl += 2;
1314 1.2.10.2 tls txdr_hyper(diraft.na_filerev, tl);
1315 1.2.10.2 tls (void) nfsrv_putattrbit(nd, &attrbits);
1316 1.2.10.2 tls }
1317 1.2.10.2 tls }
1318 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
1319 1.2.10.2 tls nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1320 1.2.10.2 tls #ifdef NFS4_ACL_EXTATTR_NAME
1321 1.2.10.2 tls acl_free(aclp);
1322 1.2.10.2 tls #endif
1323 1.2.10.2 tls
1324 1.2.10.2 tls out:
1325 1.2.10.2 tls NFSEXITCODE2(0, nd);
1326 1.2.10.2 tls return (0);
1327 1.2.10.2 tls nfsmout:
1328 1.2.10.2 tls vrele(dp);
1329 1.2.10.2 tls #ifdef NFS4_ACL_EXTATTR_NAME
1330 1.2.10.2 tls acl_free(aclp);
1331 1.2.10.2 tls #endif
1332 1.2.10.2 tls if (bufp)
1333 1.2.10.2 tls nfsvno_relpathbuf(&named);
1334 1.2.10.2 tls if (pathcp)
1335 1.2.10.2 tls FREE(pathcp, M_TEMP);
1336 1.2.10.2 tls
1337 1.2.10.2 tls NFSEXITCODE2(error, nd);
1338 1.2.10.2 tls return (error);
1339 1.2.10.2 tls }
1340 1.2.10.2 tls
1341 1.2.10.2 tls /*
1342 1.2.10.2 tls * nfs remove service
1343 1.2.10.2 tls */
1344 1.2.10.2 tls APPLESTATIC int
1345 1.2.10.2 tls nfsrvd_remove(struct nfsrv_descript *nd, __unused int isdgram,
1346 1.2.10.2 tls vnode_t dp, NFSPROC_T *p, struct nfsexstuff *exp)
1347 1.2.10.2 tls {
1348 1.2.10.2 tls struct nameidata named;
1349 1.2.10.2 tls u_int32_t *tl;
1350 1.2.10.2 tls int error = 0, dirfor_ret = 1, diraft_ret = 1;
1351 1.2.10.2 tls vnode_t dirp = NULL;
1352 1.2.10.2 tls struct nfsvattr dirfor, diraft;
1353 1.2.10.2 tls char *bufp;
1354 1.2.10.2 tls u_long *hashp;
1355 1.2.10.2 tls
1356 1.2.10.2 tls if (nd->nd_repstat) {
1357 1.2.10.2 tls nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1358 1.2.10.2 tls goto out;
1359 1.2.10.2 tls }
1360 1.2.10.2 tls NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, DELETE,
1361 1.2.10.2 tls LOCKPARENT | LOCKLEAF);
1362 1.2.10.2 tls nfsvno_setpathbuf(&named, &bufp, &hashp);
1363 1.2.10.2 tls error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
1364 1.2.10.2 tls if (error) {
1365 1.2.10.2 tls vput(dp);
1366 1.2.10.2 tls nfsvno_relpathbuf(&named);
1367 1.2.10.2 tls goto out;
1368 1.2.10.2 tls }
1369 1.2.10.2 tls if (!nd->nd_repstat) {
1370 1.2.10.2 tls nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, p, &dirp);
1371 1.2.10.2 tls } else {
1372 1.2.10.2 tls vput(dp);
1373 1.2.10.2 tls nfsvno_relpathbuf(&named);
1374 1.2.10.2 tls }
1375 1.2.10.2 tls if (dirp) {
1376 1.2.10.2 tls if (!(nd->nd_flag & ND_NFSV2)) {
1377 1.2.10.2 tls dirfor_ret = nfsvno_getattr(dirp, &dirfor,
1378 1.2.10.2 tls nd->nd_cred, p, 0);
1379 1.2.10.2 tls } else {
1380 1.2.10.2 tls vrele(dirp);
1381 1.2.10.2 tls dirp = NULL;
1382 1.2.10.2 tls }
1383 1.2.10.2 tls }
1384 1.2.10.2 tls if (!nd->nd_repstat) {
1385 1.2.10.2 tls if (nd->nd_flag & ND_NFSV4) {
1386 1.2.10.2 tls if (vnode_vtype(named.ni_vp) == VDIR)
1387 1.2.10.2 tls nd->nd_repstat = nfsvno_rmdirsub(&named, 1,
1388 1.2.10.2 tls nd->nd_cred, p, exp);
1389 1.2.10.2 tls else
1390 1.2.10.2 tls nd->nd_repstat = nfsvno_removesub(&named, 1,
1391 1.2.10.2 tls nd->nd_cred, p, exp);
1392 1.2.10.2 tls } else if (nd->nd_procnum == NFSPROC_RMDIR) {
1393 1.2.10.2 tls nd->nd_repstat = nfsvno_rmdirsub(&named, 0,
1394 1.2.10.2 tls nd->nd_cred, p, exp);
1395 1.2.10.2 tls } else {
1396 1.2.10.2 tls nd->nd_repstat = nfsvno_removesub(&named, 0,
1397 1.2.10.2 tls nd->nd_cred, p, exp);
1398 1.2.10.2 tls }
1399 1.2.10.2 tls }
1400 1.2.10.2 tls if (!(nd->nd_flag & ND_NFSV2)) {
1401 1.2.10.2 tls if (dirp) {
1402 1.2.10.2 tls diraft_ret = nfsvno_getattr(dirp, &diraft, nd->nd_cred,
1403 1.2.10.2 tls p, 0);
1404 1.2.10.2 tls vrele(dirp);
1405 1.2.10.2 tls }
1406 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3) {
1407 1.2.10.2 tls nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
1408 1.2.10.2 tls &diraft);
1409 1.2.10.2 tls } else if (!nd->nd_repstat) {
1410 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1411 1.2.10.2 tls *tl++ = newnfs_false;
1412 1.2.10.2 tls txdr_hyper(dirfor.na_filerev, tl);
1413 1.2.10.2 tls tl += 2;
1414 1.2.10.2 tls txdr_hyper(diraft.na_filerev, tl);
1415 1.2.10.2 tls }
1416 1.2.10.2 tls }
1417 1.2.10.2 tls
1418 1.2.10.2 tls out:
1419 1.2.10.2 tls NFSEXITCODE2(error, nd);
1420 1.2.10.2 tls return (error);
1421 1.2.10.2 tls }
1422 1.2.10.2 tls
1423 1.2.10.2 tls /*
1424 1.2.10.2 tls * nfs rename service
1425 1.2.10.2 tls */
1426 1.2.10.2 tls APPLESTATIC int
1427 1.2.10.2 tls nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
1428 1.2.10.2 tls vnode_t dp, vnode_t todp, NFSPROC_T *p, struct nfsexstuff *exp,
1429 1.2.10.2 tls struct nfsexstuff *toexp)
1430 1.2.10.2 tls {
1431 1.2.10.2 tls u_int32_t *tl;
1432 1.2.10.2 tls int error = 0, fdirfor_ret = 1, fdiraft_ret = 1;
1433 1.2.10.2 tls int tdirfor_ret = 1, tdiraft_ret = 1;
1434 1.2.10.2 tls struct nameidata fromnd, tond;
1435 1.2.10.2 tls vnode_t fdirp = NULL, tdirp = NULL, tdp = NULL;
1436 1.2.10.2 tls struct nfsvattr fdirfor, fdiraft, tdirfor, tdiraft;
1437 1.2.10.2 tls struct nfsexstuff tnes;
1438 1.2.10.2 tls struct nfsrvfh tfh;
1439 1.2.10.2 tls char *bufp, *tbufp = NULL;
1440 1.2.10.2 tls u_long *hashp;
1441 1.2.10.2 tls fhandle_t fh;
1442 1.2.10.2 tls
1443 1.2.10.2 tls if (nd->nd_repstat) {
1444 1.2.10.2 tls nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
1445 1.2.10.2 tls nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
1446 1.2.10.2 tls goto out;
1447 1.2.10.2 tls }
1448 1.2.10.2 tls if (!(nd->nd_flag & ND_NFSV2))
1449 1.2.10.2 tls fdirfor_ret = nfsvno_getattr(dp, &fdirfor, nd->nd_cred, p, 1);
1450 1.2.10.2 tls tond.ni_cnd.cn_nameiop = 0;
1451 1.2.10.2 tls tond.ni_startdir = NULL;
1452 1.2.10.2 tls NFSNAMEICNDSET(&fromnd.ni_cnd, nd->nd_cred, DELETE, WANTPARENT | SAVESTART);
1453 1.2.10.2 tls nfsvno_setpathbuf(&fromnd, &bufp, &hashp);
1454 1.2.10.2 tls error = nfsrv_parsename(nd, bufp, hashp, &fromnd.ni_pathlen);
1455 1.2.10.2 tls if (error) {
1456 1.2.10.2 tls vput(dp);
1457 1.2.10.2 tls if (todp)
1458 1.2.10.2 tls vrele(todp);
1459 1.2.10.2 tls nfsvno_relpathbuf(&fromnd);
1460 1.2.10.2 tls goto out;
1461 1.2.10.2 tls }
1462 1.2.10.2 tls if (nd->nd_flag & ND_NFSV4) {
1463 1.2.10.2 tls tdp = todp;
1464 1.2.10.2 tls tnes = *toexp;
1465 1.2.10.2 tls tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred, p, 0);
1466 1.2.10.2 tls } else {
1467 1.2.10.2 tls tfh.nfsrvfh_len = 0;
1468 1.2.10.2 tls error = nfsrv_mtofh(nd, &tfh);
1469 1.2.10.2 tls if (error == 0)
1470 1.2.10.2 tls error = nfsvno_getfh(dp, &fh, p);
1471 1.2.10.2 tls if (error) {
1472 1.2.10.2 tls vput(dp);
1473 1.2.10.2 tls /* todp is always NULL except NFSv4 */
1474 1.2.10.2 tls nfsvno_relpathbuf(&fromnd);
1475 1.2.10.2 tls goto out;
1476 1.2.10.2 tls }
1477 1.2.10.2 tls
1478 1.2.10.2 tls /* If this is the same file handle, just VREF() the vnode. */
1479 1.2.10.2 tls if (tfh.nfsrvfh_len == NFSX_MYFH &&
1480 1.2.10.2 tls !NFSBCMP(tfh.nfsrvfh_data, &fh, NFSX_MYFH)) {
1481 1.2.10.2 tls VREF(dp);
1482 1.2.10.2 tls tdp = dp;
1483 1.2.10.2 tls tnes = *exp;
1484 1.2.10.2 tls tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred,
1485 1.2.10.2 tls p, 1);
1486 1.2.10.2 tls } else {
1487 1.2.10.2 tls nd->nd_cred->cr_uid = nd->nd_saveduid;
1488 1.2.10.2 tls nfsd_fhtovp(nd, &tfh, LK_EXCLUSIVE, &tdp, &tnes, NULL,
1489 1.2.10.2 tls 0, p);
1490 1.2.10.2 tls if (tdp) {
1491 1.2.10.2 tls tdirfor_ret = nfsvno_getattr(tdp, &tdirfor,
1492 1.2.10.2 tls nd->nd_cred, p, 1);
1493 1.2.10.2 tls NFSVOPUNLOCK(tdp, 0);
1494 1.2.10.2 tls }
1495 1.2.10.2 tls }
1496 1.2.10.2 tls }
1497 1.2.10.2 tls NFSNAMEICNDSET(&tond.ni_cnd, nd->nd_cred, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART);
1498 1.2.10.2 tls nfsvno_setpathbuf(&tond, &tbufp, &hashp);
1499 1.2.10.2 tls if (!nd->nd_repstat) {
1500 1.2.10.2 tls error = nfsrv_parsename(nd, tbufp, hashp, &tond.ni_pathlen);
1501 1.2.10.2 tls if (error) {
1502 1.2.10.2 tls if (tdp)
1503 1.2.10.2 tls vrele(tdp);
1504 1.2.10.2 tls vput(dp);
1505 1.2.10.2 tls nfsvno_relpathbuf(&fromnd);
1506 1.2.10.2 tls nfsvno_relpathbuf(&tond);
1507 1.2.10.2 tls goto out;
1508 1.2.10.2 tls }
1509 1.2.10.2 tls }
1510 1.2.10.2 tls if (nd->nd_repstat) {
1511 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3) {
1512 1.2.10.2 tls nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret,
1513 1.2.10.2 tls &fdiraft);
1514 1.2.10.2 tls nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret,
1515 1.2.10.2 tls &tdiraft);
1516 1.2.10.2 tls }
1517 1.2.10.2 tls if (tdp)
1518 1.2.10.2 tls vrele(tdp);
1519 1.2.10.2 tls vput(dp);
1520 1.2.10.2 tls nfsvno_relpathbuf(&fromnd);
1521 1.2.10.2 tls nfsvno_relpathbuf(&tond);
1522 1.2.10.2 tls goto out;
1523 1.2.10.2 tls }
1524 1.2.10.2 tls
1525 1.2.10.2 tls /*
1526 1.2.10.2 tls * Done parsing, now down to business.
1527 1.2.10.2 tls */
1528 1.2.10.2 tls nd->nd_repstat = nfsvno_namei(nd, &fromnd, dp, 1, exp, p, &fdirp);
1529 1.2.10.2 tls if (nd->nd_repstat) {
1530 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3) {
1531 1.2.10.2 tls nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret,
1532 1.2.10.2 tls &fdiraft);
1533 1.2.10.2 tls nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret,
1534 1.2.10.2 tls &tdiraft);
1535 1.2.10.2 tls }
1536 1.2.10.2 tls if (fdirp)
1537 1.2.10.2 tls vrele(fdirp);
1538 1.2.10.2 tls if (tdp)
1539 1.2.10.2 tls vrele(tdp);
1540 1.2.10.2 tls nfsvno_relpathbuf(&tond);
1541 1.2.10.2 tls goto out;
1542 1.2.10.2 tls }
1543 1.2.10.2 tls if (vnode_vtype(fromnd.ni_vp) == VDIR)
1544 1.2.10.2 tls tond.ni_cnd.cn_flags |= WILLBEDIR;
1545 1.2.10.2 tls nd->nd_repstat = nfsvno_namei(nd, &tond, tdp, 0, &tnes, p, &tdirp);
1546 1.2.10.2 tls nd->nd_repstat = nfsvno_rename(&fromnd, &tond, nd->nd_repstat,
1547 1.2.10.2 tls nd->nd_flag, nd->nd_cred, p);
1548 1.2.10.2 tls if (fdirp)
1549 1.2.10.2 tls fdiraft_ret = nfsvno_getattr(fdirp, &fdiraft, nd->nd_cred, p,
1550 1.2.10.2 tls 0);
1551 1.2.10.2 tls if (tdirp)
1552 1.2.10.2 tls tdiraft_ret = nfsvno_getattr(tdirp, &tdiraft, nd->nd_cred, p,
1553 1.2.10.2 tls 0);
1554 1.2.10.2 tls if (fdirp)
1555 1.2.10.2 tls vrele(fdirp);
1556 1.2.10.2 tls if (tdirp)
1557 1.2.10.2 tls vrele(tdirp);
1558 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3) {
1559 1.2.10.2 tls nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
1560 1.2.10.2 tls nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
1561 1.2.10.2 tls } else if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) {
1562 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, 10 * NFSX_UNSIGNED);
1563 1.2.10.2 tls *tl++ = newnfs_false;
1564 1.2.10.2 tls txdr_hyper(fdirfor.na_filerev, tl);
1565 1.2.10.2 tls tl += 2;
1566 1.2.10.2 tls txdr_hyper(fdiraft.na_filerev, tl);
1567 1.2.10.2 tls tl += 2;
1568 1.2.10.2 tls *tl++ = newnfs_false;
1569 1.2.10.2 tls txdr_hyper(tdirfor.na_filerev, tl);
1570 1.2.10.2 tls tl += 2;
1571 1.2.10.2 tls txdr_hyper(tdiraft.na_filerev, tl);
1572 1.2.10.2 tls }
1573 1.2.10.2 tls
1574 1.2.10.2 tls out:
1575 1.2.10.2 tls NFSEXITCODE2(error, nd);
1576 1.2.10.2 tls return (error);
1577 1.2.10.2 tls }
1578 1.2.10.2 tls
1579 1.2.10.2 tls /*
1580 1.2.10.2 tls * nfs link service
1581 1.2.10.2 tls */
1582 1.2.10.2 tls APPLESTATIC int
1583 1.2.10.2 tls nfsrvd_link(struct nfsrv_descript *nd, int isdgram,
1584 1.2.10.2 tls vnode_t vp, vnode_t tovp, NFSPROC_T *p, struct nfsexstuff *exp,
1585 1.2.10.2 tls struct nfsexstuff *toexp)
1586 1.2.10.2 tls {
1587 1.2.10.2 tls struct nameidata named;
1588 1.2.10.2 tls u_int32_t *tl;
1589 1.2.10.2 tls int error = 0, dirfor_ret = 1, diraft_ret = 1, getret = 1;
1590 1.2.10.2 tls vnode_t dirp = NULL, dp = NULL;
1591 1.2.10.2 tls struct nfsvattr dirfor, diraft, at;
1592 1.2.10.2 tls struct nfsexstuff tnes;
1593 1.2.10.2 tls struct nfsrvfh dfh;
1594 1.2.10.2 tls char *bufp;
1595 1.2.10.2 tls u_long *hashp;
1596 1.2.10.2 tls
1597 1.2.10.2 tls if (nd->nd_repstat) {
1598 1.2.10.2 tls nfsrv_postopattr(nd, getret, &at);
1599 1.2.10.2 tls nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1600 1.2.10.2 tls goto out;
1601 1.2.10.2 tls }
1602 1.2.10.2 tls NFSVOPUNLOCK(vp, 0);
1603 1.2.10.2 tls if (vnode_vtype(vp) == VDIR) {
1604 1.2.10.2 tls if (nd->nd_flag & ND_NFSV4)
1605 1.2.10.2 tls nd->nd_repstat = NFSERR_ISDIR;
1606 1.2.10.2 tls else
1607 1.2.10.2 tls nd->nd_repstat = NFSERR_INVAL;
1608 1.2.10.2 tls if (tovp)
1609 1.2.10.2 tls vrele(tovp);
1610 1.2.10.2 tls } else if (vnode_vtype(vp) == VLNK) {
1611 1.2.10.2 tls if (nd->nd_flag & ND_NFSV2)
1612 1.2.10.2 tls nd->nd_repstat = NFSERR_INVAL;
1613 1.2.10.2 tls else
1614 1.2.10.2 tls nd->nd_repstat = NFSERR_NOTSUPP;
1615 1.2.10.2 tls if (tovp)
1616 1.2.10.2 tls vrele(tovp);
1617 1.2.10.2 tls }
1618 1.2.10.2 tls if (!nd->nd_repstat) {
1619 1.2.10.2 tls if (nd->nd_flag & ND_NFSV4) {
1620 1.2.10.2 tls dp = tovp;
1621 1.2.10.2 tls tnes = *toexp;
1622 1.2.10.2 tls } else {
1623 1.2.10.2 tls error = nfsrv_mtofh(nd, &dfh);
1624 1.2.10.2 tls if (error) {
1625 1.2.10.2 tls vrele(vp);
1626 1.2.10.2 tls /* tovp is always NULL unless NFSv4 */
1627 1.2.10.2 tls goto out;
1628 1.2.10.2 tls }
1629 1.2.10.2 tls nfsd_fhtovp(nd, &dfh, LK_EXCLUSIVE, &dp, &tnes, NULL, 0,
1630 1.2.10.2 tls p);
1631 1.2.10.2 tls if (dp)
1632 1.2.10.2 tls NFSVOPUNLOCK(dp, 0);
1633 1.2.10.2 tls }
1634 1.2.10.2 tls }
1635 1.2.10.2 tls NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
1636 1.2.10.2 tls LOCKPARENT | SAVENAME);
1637 1.2.10.2 tls if (!nd->nd_repstat) {
1638 1.2.10.2 tls nfsvno_setpathbuf(&named, &bufp, &hashp);
1639 1.2.10.2 tls error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
1640 1.2.10.2 tls if (error) {
1641 1.2.10.2 tls vrele(vp);
1642 1.2.10.2 tls if (dp)
1643 1.2.10.2 tls vrele(dp);
1644 1.2.10.2 tls nfsvno_relpathbuf(&named);
1645 1.2.10.2 tls goto out;
1646 1.2.10.2 tls }
1647 1.2.10.2 tls if (!nd->nd_repstat) {
1648 1.2.10.2 tls nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, &tnes,
1649 1.2.10.2 tls p, &dirp);
1650 1.2.10.2 tls } else {
1651 1.2.10.2 tls if (dp)
1652 1.2.10.2 tls vrele(dp);
1653 1.2.10.2 tls nfsvno_relpathbuf(&named);
1654 1.2.10.2 tls }
1655 1.2.10.2 tls }
1656 1.2.10.2 tls if (dirp) {
1657 1.2.10.2 tls if (nd->nd_flag & ND_NFSV2) {
1658 1.2.10.2 tls vrele(dirp);
1659 1.2.10.2 tls dirp = NULL;
1660 1.2.10.2 tls } else {
1661 1.2.10.2 tls dirfor_ret = nfsvno_getattr(dirp, &dirfor,
1662 1.2.10.2 tls nd->nd_cred, p, 0);
1663 1.2.10.2 tls }
1664 1.2.10.2 tls }
1665 1.2.10.2 tls if (!nd->nd_repstat)
1666 1.2.10.2 tls nd->nd_repstat = nfsvno_link(&named, vp, nd->nd_cred, p, exp);
1667 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
1668 1.2.10.2 tls getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 0);
1669 1.2.10.2 tls if (dirp) {
1670 1.2.10.2 tls diraft_ret = nfsvno_getattr(dirp, &diraft, nd->nd_cred, p, 0);
1671 1.2.10.2 tls vrele(dirp);
1672 1.2.10.2 tls }
1673 1.2.10.2 tls vrele(vp);
1674 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3) {
1675 1.2.10.2 tls nfsrv_postopattr(nd, getret, &at);
1676 1.2.10.2 tls nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1677 1.2.10.2 tls } else if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) {
1678 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1679 1.2.10.2 tls *tl++ = newnfs_false;
1680 1.2.10.2 tls txdr_hyper(dirfor.na_filerev, tl);
1681 1.2.10.2 tls tl += 2;
1682 1.2.10.2 tls txdr_hyper(diraft.na_filerev, tl);
1683 1.2.10.2 tls }
1684 1.2.10.2 tls
1685 1.2.10.2 tls out:
1686 1.2.10.2 tls NFSEXITCODE2(error, nd);
1687 1.2.10.2 tls return (error);
1688 1.2.10.2 tls }
1689 1.2.10.2 tls
1690 1.2.10.2 tls /*
1691 1.2.10.2 tls * nfs symbolic link service
1692 1.2.10.2 tls */
1693 1.2.10.2 tls APPLESTATIC int
1694 1.2.10.2 tls nfsrvd_symlink(struct nfsrv_descript *nd, __unused int isdgram,
1695 1.2.10.2 tls vnode_t dp, vnode_t *vpp, fhandle_t *fhp, NFSPROC_T *p,
1696 1.2.10.2 tls struct nfsexstuff *exp)
1697 1.2.10.2 tls {
1698 1.2.10.2 tls struct nfsvattr nva, dirfor, diraft;
1699 1.2.10.2 tls struct nameidata named;
1700 1.2.10.2 tls int error = 0, dirfor_ret = 1, diraft_ret = 1, pathlen;
1701 1.2.10.2 tls vnode_t dirp = NULL;
1702 1.2.10.2 tls char *bufp, *pathcp = NULL;
1703 1.2.10.2 tls u_long *hashp;
1704 1.2.10.2 tls
1705 1.2.10.2 tls if (nd->nd_repstat) {
1706 1.2.10.2 tls nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1707 1.2.10.2 tls goto out;
1708 1.2.10.2 tls }
1709 1.2.10.2 tls if (vpp)
1710 1.2.10.2 tls *vpp = NULL;
1711 1.2.10.2 tls NFSVNO_ATTRINIT(&nva);
1712 1.2.10.2 tls NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
1713 1.2.10.2 tls LOCKPARENT | SAVESTART);
1714 1.2.10.2 tls nfsvno_setpathbuf(&named, &bufp, &hashp);
1715 1.2.10.2 tls error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
1716 1.2.10.2 tls if (!error && !nd->nd_repstat)
1717 1.2.10.2 tls error = nfsvno_getsymlink(nd, &nva, p, &pathcp, &pathlen);
1718 1.2.10.2 tls if (error) {
1719 1.2.10.2 tls vrele(dp);
1720 1.2.10.2 tls nfsvno_relpathbuf(&named);
1721 1.2.10.2 tls goto out;
1722 1.2.10.2 tls }
1723 1.2.10.2 tls if (!nd->nd_repstat) {
1724 1.2.10.2 tls nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp);
1725 1.2.10.2 tls } else {
1726 1.2.10.2 tls vrele(dp);
1727 1.2.10.2 tls nfsvno_relpathbuf(&named);
1728 1.2.10.2 tls }
1729 1.2.10.2 tls if (dirp != NULL && !(nd->nd_flag & ND_NFSV3)) {
1730 1.2.10.2 tls vrele(dirp);
1731 1.2.10.2 tls dirp = NULL;
1732 1.2.10.2 tls }
1733 1.2.10.2 tls
1734 1.2.10.2 tls /*
1735 1.2.10.2 tls * And call nfsrvd_symlinksub() to do the common code. It will
1736 1.2.10.2 tls * return EBADRPC upon a parsing error, 0 otherwise.
1737 1.2.10.2 tls */
1738 1.2.10.2 tls if (!nd->nd_repstat) {
1739 1.2.10.2 tls if (dirp != NULL)
1740 1.2.10.2 tls dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd->nd_cred,
1741 1.2.10.2 tls p, 0);
1742 1.2.10.2 tls nfsrvd_symlinksub(nd, &named, &nva, fhp, vpp, dirp,
1743 1.2.10.2 tls &dirfor, &diraft, &diraft_ret, NULL, NULL, p, exp,
1744 1.2.10.2 tls pathcp, pathlen);
1745 1.2.10.2 tls } else if (dirp != NULL) {
1746 1.2.10.2 tls dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd->nd_cred, p, 0);
1747 1.2.10.2 tls vrele(dirp);
1748 1.2.10.2 tls }
1749 1.2.10.2 tls if (pathcp)
1750 1.2.10.2 tls FREE(pathcp, M_TEMP);
1751 1.2.10.2 tls
1752 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3) {
1753 1.2.10.2 tls if (!nd->nd_repstat) {
1754 1.2.10.2 tls (void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 1);
1755 1.2.10.2 tls nfsrv_postopattr(nd, 0, &nva);
1756 1.2.10.2 tls }
1757 1.2.10.2 tls nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1758 1.2.10.2 tls }
1759 1.2.10.2 tls
1760 1.2.10.2 tls out:
1761 1.2.10.2 tls NFSEXITCODE2(error, nd);
1762 1.2.10.2 tls return (error);
1763 1.2.10.2 tls }
1764 1.2.10.2 tls
1765 1.2.10.2 tls /*
1766 1.2.10.2 tls * Common code for creating a symbolic link.
1767 1.2.10.2 tls */
1768 1.2.10.2 tls static void
1769 1.2.10.2 tls nfsrvd_symlinksub(struct nfsrv_descript *nd, struct nameidata *ndp,
1770 1.2.10.2 tls struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp,
1771 1.2.10.2 tls vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp,
1772 1.2.10.2 tls int *diraft_retp, nfsattrbit_t *attrbitp,
1773 1.2.10.2 tls NFSACL_T *aclp, NFSPROC_T *p, struct nfsexstuff *exp, char *pathcp,
1774 1.2.10.2 tls int pathlen)
1775 1.2.10.2 tls {
1776 1.2.10.2 tls u_int32_t *tl;
1777 1.2.10.2 tls
1778 1.2.10.2 tls nd->nd_repstat = nfsvno_symlink(ndp, nvap, pathcp, pathlen,
1779 1.2.10.2 tls !(nd->nd_flag & ND_NFSV2), nd->nd_saveduid, nd->nd_cred, p, exp);
1780 1.2.10.2 tls if (!nd->nd_repstat && !(nd->nd_flag & ND_NFSV2)) {
1781 1.2.10.2 tls nfsrv_fixattr(nd, ndp->ni_vp, nvap, aclp, p, attrbitp, exp);
1782 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3) {
1783 1.2.10.2 tls nd->nd_repstat = nfsvno_getfh(ndp->ni_vp, fhp, p);
1784 1.2.10.2 tls if (!nd->nd_repstat)
1785 1.2.10.2 tls nd->nd_repstat = nfsvno_getattr(ndp->ni_vp,
1786 1.2.10.2 tls nvap, nd->nd_cred, p, 1);
1787 1.2.10.2 tls }
1788 1.2.10.2 tls if (vpp != NULL && nd->nd_repstat == 0) {
1789 1.2.10.2 tls NFSVOPUNLOCK(ndp->ni_vp, 0);
1790 1.2.10.2 tls *vpp = ndp->ni_vp;
1791 1.2.10.2 tls } else
1792 1.2.10.2 tls vput(ndp->ni_vp);
1793 1.2.10.2 tls }
1794 1.2.10.2 tls if (dirp) {
1795 1.2.10.2 tls *diraft_retp = nfsvno_getattr(dirp, diraftp, nd->nd_cred, p, 0);
1796 1.2.10.2 tls vrele(dirp);
1797 1.2.10.2 tls }
1798 1.2.10.2 tls if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) {
1799 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1800 1.2.10.2 tls *tl++ = newnfs_false;
1801 1.2.10.2 tls txdr_hyper(dirforp->na_filerev, tl);
1802 1.2.10.2 tls tl += 2;
1803 1.2.10.2 tls txdr_hyper(diraftp->na_filerev, tl);
1804 1.2.10.2 tls (void) nfsrv_putattrbit(nd, attrbitp);
1805 1.2.10.2 tls }
1806 1.2.10.2 tls
1807 1.2.10.2 tls NFSEXITCODE2(0, nd);
1808 1.2.10.2 tls }
1809 1.2.10.2 tls
1810 1.2.10.2 tls /*
1811 1.2.10.2 tls * nfs mkdir service
1812 1.2.10.2 tls */
1813 1.2.10.2 tls APPLESTATIC int
1814 1.2.10.2 tls nfsrvd_mkdir(struct nfsrv_descript *nd, __unused int isdgram,
1815 1.2.10.2 tls vnode_t dp, vnode_t *vpp, fhandle_t *fhp, NFSPROC_T *p,
1816 1.2.10.2 tls struct nfsexstuff *exp)
1817 1.2.10.2 tls {
1818 1.2.10.2 tls struct nfsvattr nva, dirfor, diraft;
1819 1.2.10.2 tls struct nameidata named;
1820 1.2.10.2 tls u_int32_t *tl;
1821 1.2.10.2 tls int error = 0, dirfor_ret = 1, diraft_ret = 1;
1822 1.2.10.2 tls vnode_t dirp = NULL;
1823 1.2.10.2 tls char *bufp;
1824 1.2.10.2 tls u_long *hashp;
1825 1.2.10.2 tls
1826 1.2.10.2 tls if (nd->nd_repstat) {
1827 1.2.10.2 tls nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1828 1.2.10.2 tls goto out;
1829 1.2.10.2 tls }
1830 1.2.10.2 tls NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
1831 1.2.10.2 tls LOCKPARENT | SAVENAME);
1832 1.2.10.2 tls nfsvno_setpathbuf(&named, &bufp, &hashp);
1833 1.2.10.2 tls error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
1834 1.2.10.2 tls if (error)
1835 1.2.10.2 tls goto nfsmout;
1836 1.2.10.2 tls if (!nd->nd_repstat) {
1837 1.2.10.2 tls NFSVNO_ATTRINIT(&nva);
1838 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3) {
1839 1.2.10.2 tls error = nfsrv_sattr(nd, &nva, NULL, NULL, p);
1840 1.2.10.2 tls if (error)
1841 1.2.10.2 tls goto nfsmout;
1842 1.2.10.2 tls } else {
1843 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1844 1.2.10.2 tls nva.na_mode = nfstov_mode(*tl++);
1845 1.2.10.2 tls }
1846 1.2.10.2 tls }
1847 1.2.10.2 tls if (!nd->nd_repstat) {
1848 1.2.10.2 tls nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp);
1849 1.2.10.2 tls } else {
1850 1.2.10.2 tls vrele(dp);
1851 1.2.10.2 tls nfsvno_relpathbuf(&named);
1852 1.2.10.2 tls }
1853 1.2.10.2 tls if (dirp != NULL && !(nd->nd_flag & ND_NFSV3)) {
1854 1.2.10.2 tls vrele(dirp);
1855 1.2.10.2 tls dirp = NULL;
1856 1.2.10.2 tls }
1857 1.2.10.2 tls if (nd->nd_repstat) {
1858 1.2.10.2 tls if (dirp != NULL) {
1859 1.2.10.2 tls dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd->nd_cred,
1860 1.2.10.2 tls p, 0);
1861 1.2.10.2 tls vrele(dirp);
1862 1.2.10.2 tls }
1863 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
1864 1.2.10.2 tls nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
1865 1.2.10.2 tls &diraft);
1866 1.2.10.2 tls goto out;
1867 1.2.10.2 tls }
1868 1.2.10.2 tls if (dirp != NULL)
1869 1.2.10.2 tls dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd->nd_cred, p, 0);
1870 1.2.10.2 tls
1871 1.2.10.2 tls /*
1872 1.2.10.2 tls * Call nfsrvd_mkdirsub() for the code common to V4 as well.
1873 1.2.10.2 tls */
1874 1.2.10.2 tls nfsrvd_mkdirsub(nd, &named, &nva, fhp, vpp, dirp, &dirfor, &diraft,
1875 1.2.10.2 tls &diraft_ret, NULL, NULL, p, exp);
1876 1.2.10.2 tls
1877 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3) {
1878 1.2.10.2 tls if (!nd->nd_repstat) {
1879 1.2.10.2 tls (void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 1);
1880 1.2.10.2 tls nfsrv_postopattr(nd, 0, &nva);
1881 1.2.10.2 tls }
1882 1.2.10.2 tls nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1883 1.2.10.2 tls } else if (!nd->nd_repstat) {
1884 1.2.10.2 tls (void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 0);
1885 1.2.10.2 tls nfsrv_fillattr(nd, &nva);
1886 1.2.10.2 tls }
1887 1.2.10.2 tls
1888 1.2.10.2 tls out:
1889 1.2.10.2 tls NFSEXITCODE2(0, nd);
1890 1.2.10.2 tls return (0);
1891 1.2.10.2 tls nfsmout:
1892 1.2.10.2 tls vrele(dp);
1893 1.2.10.2 tls nfsvno_relpathbuf(&named);
1894 1.2.10.2 tls NFSEXITCODE2(error, nd);
1895 1.2.10.2 tls return (error);
1896 1.2.10.2 tls }
1897 1.2.10.2 tls
1898 1.2.10.2 tls /*
1899 1.2.10.2 tls * Code common to mkdir for V2,3 and 4.
1900 1.2.10.2 tls */
1901 1.2.10.2 tls static void
1902 1.2.10.2 tls nfsrvd_mkdirsub(struct nfsrv_descript *nd, struct nameidata *ndp,
1903 1.2.10.2 tls struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp,
1904 1.2.10.2 tls vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp,
1905 1.2.10.2 tls int *diraft_retp, nfsattrbit_t *attrbitp, NFSACL_T *aclp,
1906 1.2.10.2 tls NFSPROC_T *p, struct nfsexstuff *exp)
1907 1.2.10.2 tls {
1908 1.2.10.2 tls vnode_t vp;
1909 1.2.10.2 tls u_int32_t *tl;
1910 1.2.10.2 tls
1911 1.2.10.2 tls NFSVNO_SETATTRVAL(nvap, type, VDIR);
1912 1.2.10.2 tls nd->nd_repstat = nfsvno_mkdir(ndp, nvap, nd->nd_saveduid,
1913 1.2.10.2 tls nd->nd_cred, p, exp);
1914 1.2.10.2 tls if (!nd->nd_repstat) {
1915 1.2.10.2 tls vp = ndp->ni_vp;
1916 1.2.10.2 tls nfsrv_fixattr(nd, vp, nvap, aclp, p, attrbitp, exp);
1917 1.2.10.2 tls nd->nd_repstat = nfsvno_getfh(vp, fhp, p);
1918 1.2.10.2 tls if (!(nd->nd_flag & ND_NFSV4) && !nd->nd_repstat)
1919 1.2.10.2 tls nd->nd_repstat = nfsvno_getattr(vp, nvap, nd->nd_cred,
1920 1.2.10.2 tls p, 1);
1921 1.2.10.2 tls if (vpp && !nd->nd_repstat) {
1922 1.2.10.2 tls NFSVOPUNLOCK(vp, 0);
1923 1.2.10.2 tls *vpp = vp;
1924 1.2.10.2 tls } else {
1925 1.2.10.2 tls vput(vp);
1926 1.2.10.2 tls }
1927 1.2.10.2 tls }
1928 1.2.10.2 tls if (dirp) {
1929 1.2.10.2 tls *diraft_retp = nfsvno_getattr(dirp, diraftp, nd->nd_cred, p, 0);
1930 1.2.10.2 tls vrele(dirp);
1931 1.2.10.2 tls }
1932 1.2.10.2 tls if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) {
1933 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1934 1.2.10.2 tls *tl++ = newnfs_false;
1935 1.2.10.2 tls txdr_hyper(dirforp->na_filerev, tl);
1936 1.2.10.2 tls tl += 2;
1937 1.2.10.2 tls txdr_hyper(diraftp->na_filerev, tl);
1938 1.2.10.2 tls (void) nfsrv_putattrbit(nd, attrbitp);
1939 1.2.10.2 tls }
1940 1.2.10.2 tls
1941 1.2.10.2 tls NFSEXITCODE2(0, nd);
1942 1.2.10.2 tls }
1943 1.2.10.2 tls
1944 1.2.10.2 tls /*
1945 1.2.10.2 tls * nfs commit service
1946 1.2.10.2 tls */
1947 1.2.10.2 tls APPLESTATIC int
1948 1.2.10.2 tls nfsrvd_commit(struct nfsrv_descript *nd, __unused int isdgram,
1949 1.2.10.2 tls vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp)
1950 1.2.10.2 tls {
1951 1.2.10.2 tls struct nfsvattr bfor, aft;
1952 1.2.10.2 tls u_int32_t *tl;
1953 1.2.10.2 tls int error = 0, for_ret = 1, aft_ret = 1, cnt;
1954 1.2.10.2 tls u_int64_t off;
1955 1.2.10.2 tls
1956 1.2.10.2 tls if (nd->nd_repstat) {
1957 1.2.10.2 tls nfsrv_wcc(nd, for_ret, &bfor, aft_ret, &aft);
1958 1.2.10.2 tls goto out;
1959 1.2.10.2 tls }
1960 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
1961 1.2.10.2 tls /*
1962 1.2.10.2 tls * XXX At this time VOP_FSYNC() does not accept offset and byte
1963 1.2.10.2 tls * count parameters, so these arguments are useless (someday maybe).
1964 1.2.10.2 tls */
1965 1.2.10.2 tls off = fxdr_hyper(tl);
1966 1.2.10.2 tls tl += 2;
1967 1.2.10.2 tls cnt = fxdr_unsigned(int, *tl);
1968 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
1969 1.2.10.2 tls for_ret = nfsvno_getattr(vp, &bfor, nd->nd_cred, p, 1);
1970 1.2.10.2 tls nd->nd_repstat = nfsvno_fsync(vp, off, cnt, nd->nd_cred, p);
1971 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3) {
1972 1.2.10.2 tls aft_ret = nfsvno_getattr(vp, &aft, nd->nd_cred, p, 1);
1973 1.2.10.2 tls nfsrv_wcc(nd, for_ret, &bfor, aft_ret, &aft);
1974 1.2.10.2 tls }
1975 1.2.10.2 tls vput(vp);
1976 1.2.10.2 tls if (!nd->nd_repstat) {
1977 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, NFSX_VERF);
1978 1.2.10.2 tls *tl++ = txdr_unsigned(nfsboottime.tv_sec);
1979 1.2.10.2 tls *tl = txdr_unsigned(nfsboottime.tv_usec);
1980 1.2.10.2 tls }
1981 1.2.10.2 tls
1982 1.2.10.2 tls out:
1983 1.2.10.2 tls NFSEXITCODE2(0, nd);
1984 1.2.10.2 tls return (0);
1985 1.2.10.2 tls nfsmout:
1986 1.2.10.2 tls vput(vp);
1987 1.2.10.2 tls NFSEXITCODE2(error, nd);
1988 1.2.10.2 tls return (error);
1989 1.2.10.2 tls }
1990 1.2.10.2 tls
1991 1.2.10.2 tls /*
1992 1.2.10.2 tls * nfs statfs service
1993 1.2.10.2 tls */
1994 1.2.10.2 tls APPLESTATIC int
1995 1.2.10.2 tls nfsrvd_statfs(struct nfsrv_descript *nd, __unused int isdgram,
1996 1.2.10.2 tls vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp)
1997 1.2.10.2 tls {
1998 1.2.10.2 tls struct statfs *sf;
1999 1.2.10.2 tls u_int32_t *tl;
2000 1.2.10.2 tls int getret = 1;
2001 1.2.10.2 tls struct nfsvattr at;
2002 1.2.10.2 tls struct statfs sfs;
2003 1.2.10.2 tls u_quad_t tval;
2004 1.2.10.2 tls
2005 1.2.10.2 tls if (nd->nd_repstat) {
2006 1.2.10.2 tls nfsrv_postopattr(nd, getret, &at);
2007 1.2.10.2 tls goto out;
2008 1.2.10.2 tls }
2009 1.2.10.2 tls sf = &sfs;
2010 1.2.10.2 tls nd->nd_repstat = nfsvno_statfs(vp, sf);
2011 1.2.10.2 tls getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1);
2012 1.2.10.2 tls vput(vp);
2013 1.2.10.2 tls if (nd->nd_flag & ND_NFSV3)
2014 1.2.10.2 tls nfsrv_postopattr(nd, getret, &at);
2015 1.2.10.2 tls if (nd->nd_repstat)
2016 1.2.10.2 tls goto out;
2017 1.2.10.2 tls if (nd->nd_flag & ND_NFSV2) {
2018 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, NFSX_V2STATFS);
2019 1.2.10.2 tls *tl++ = txdr_unsigned(NFS_V2MAXDATA);
2020 1.2.10.2 tls *tl++ = txdr_unsigned(sf->f_bsize);
2021 1.2.10.2 tls *tl++ = txdr_unsigned(sf->f_blocks);
2022 1.2.10.2 tls *tl++ = txdr_unsigned(sf->f_bfree);
2023 1.2.10.2 tls *tl = txdr_unsigned(sf->f_bavail);
2024 1.2.10.2 tls } else {
2025 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, NFSX_V3STATFS);
2026 1.2.10.2 tls tval = (u_quad_t)sf->f_blocks;
2027 1.2.10.2 tls tval *= (u_quad_t)sf->f_bsize;
2028 1.2.10.2 tls txdr_hyper(tval, tl); tl += 2;
2029 1.2.10.2 tls tval = (u_quad_t)sf->f_bfree;
2030 1.2.10.2 tls tval *= (u_quad_t)sf->f_bsize;
2031 1.2.10.2 tls txdr_hyper(tval, tl); tl += 2;
2032 1.2.10.2 tls tval = (u_quad_t)sf->f_bavail;
2033 1.2.10.2 tls tval *= (u_quad_t)sf->f_bsize;
2034 1.2.10.2 tls txdr_hyper(tval, tl); tl += 2;
2035 1.2.10.2 tls tval = (u_quad_t)sf->f_files;
2036 1.2.10.2 tls txdr_hyper(tval, tl); tl += 2;
2037 1.2.10.2 tls tval = (u_quad_t)sf->f_ffree;
2038 1.2.10.2 tls txdr_hyper(tval, tl); tl += 2;
2039 1.2.10.2 tls tval = (u_quad_t)sf->f_ffree;
2040 1.2.10.2 tls txdr_hyper(tval, tl); tl += 2;
2041 1.2.10.2 tls *tl = 0;
2042 1.2.10.2 tls }
2043 1.2.10.2 tls
2044 1.2.10.2 tls out:
2045 1.2.10.2 tls NFSEXITCODE2(0, nd);
2046 1.2.10.2 tls return (0);
2047 1.2.10.2 tls }
2048 1.2.10.2 tls
2049 1.2.10.2 tls /*
2050 1.2.10.2 tls * nfs fsinfo service
2051 1.2.10.2 tls */
2052 1.2.10.2 tls APPLESTATIC int
2053 1.2.10.2 tls nfsrvd_fsinfo(struct nfsrv_descript *nd, int isdgram,
2054 1.2.10.2 tls vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp)
2055 1.2.10.2 tls {
2056 1.2.10.2 tls u_int32_t *tl;
2057 1.2.10.2 tls struct nfsfsinfo fs;
2058 1.2.10.2 tls int getret = 1;
2059 1.2.10.2 tls struct nfsvattr at;
2060 1.2.10.2 tls
2061 1.2.10.2 tls if (nd->nd_repstat) {
2062 1.2.10.2 tls nfsrv_postopattr(nd, getret, &at);
2063 1.2.10.2 tls goto out;
2064 1.2.10.2 tls }
2065 1.2.10.2 tls getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1);
2066 1.2.10.2 tls nfsvno_getfs(&fs, isdgram);
2067 1.2.10.2 tls vput(vp);
2068 1.2.10.2 tls nfsrv_postopattr(nd, getret, &at);
2069 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, NFSX_V3FSINFO);
2070 1.2.10.2 tls *tl++ = txdr_unsigned(fs.fs_rtmax);
2071 1.2.10.2 tls *tl++ = txdr_unsigned(fs.fs_rtpref);
2072 1.2.10.2 tls *tl++ = txdr_unsigned(fs.fs_rtmult);
2073 1.2.10.2 tls *tl++ = txdr_unsigned(fs.fs_wtmax);
2074 1.2.10.2 tls *tl++ = txdr_unsigned(fs.fs_wtpref);
2075 1.2.10.2 tls *tl++ = txdr_unsigned(fs.fs_wtmult);
2076 1.2.10.2 tls *tl++ = txdr_unsigned(fs.fs_dtpref);
2077 1.2.10.2 tls txdr_hyper(fs.fs_maxfilesize, tl);
2078 1.2.10.2 tls tl += 2;
2079 1.2.10.2 tls txdr_nfsv3time(&fs.fs_timedelta, tl);
2080 1.2.10.2 tls tl += 2;
2081 1.2.10.2 tls *tl = txdr_unsigned(fs.fs_properties);
2082 1.2.10.2 tls
2083 1.2.10.2 tls out:
2084 1.2.10.2 tls NFSEXITCODE2(0, nd);
2085 1.2.10.2 tls return (0);
2086 1.2.10.2 tls }
2087 1.2.10.2 tls
2088 1.2.10.2 tls /*
2089 1.2.10.2 tls * nfs pathconf service
2090 1.2.10.2 tls */
2091 1.2.10.2 tls APPLESTATIC int
2092 1.2.10.2 tls nfsrvd_pathconf(struct nfsrv_descript *nd, __unused int isdgram,
2093 1.2.10.2 tls vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp)
2094 1.2.10.2 tls {
2095 1.2.10.2 tls struct nfsv3_pathconf *pc;
2096 1.2.10.2 tls int getret = 1;
2097 1.2.10.2 tls register_t linkmax, namemax, chownres, notrunc;
2098 1.2.10.2 tls struct nfsvattr at;
2099 1.2.10.2 tls
2100 1.2.10.2 tls if (nd->nd_repstat) {
2101 1.2.10.2 tls nfsrv_postopattr(nd, getret, &at);
2102 1.2.10.2 tls goto out;
2103 1.2.10.2 tls }
2104 1.2.10.2 tls nd->nd_repstat = nfsvno_pathconf(vp, _PC_LINK_MAX, &linkmax,
2105 1.2.10.2 tls nd->nd_cred, p);
2106 1.2.10.2 tls if (!nd->nd_repstat)
2107 1.2.10.2 tls nd->nd_repstat = nfsvno_pathconf(vp, _PC_NAME_MAX, &namemax,
2108 1.2.10.2 tls nd->nd_cred, p);
2109 1.2.10.2 tls if (!nd->nd_repstat)
2110 1.2.10.2 tls nd->nd_repstat=nfsvno_pathconf(vp, _PC_CHOWN_RESTRICTED,
2111 1.2.10.2 tls &chownres, nd->nd_cred, p);
2112 1.2.10.2 tls if (!nd->nd_repstat)
2113 1.2.10.2 tls nd->nd_repstat = nfsvno_pathconf(vp, _PC_NO_TRUNC, ¬runc,
2114 1.2.10.2 tls nd->nd_cred, p);
2115 1.2.10.2 tls getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1);
2116 1.2.10.2 tls vput(vp);
2117 1.2.10.2 tls nfsrv_postopattr(nd, getret, &at);
2118 1.2.10.2 tls if (!nd->nd_repstat) {
2119 1.2.10.2 tls NFSM_BUILD(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF);
2120 1.2.10.2 tls pc->pc_linkmax = txdr_unsigned(linkmax);
2121 1.2.10.2 tls pc->pc_namemax = txdr_unsigned(namemax);
2122 1.2.10.2 tls pc->pc_notrunc = txdr_unsigned(notrunc);
2123 1.2.10.2 tls pc->pc_chownrestricted = txdr_unsigned(chownres);
2124 1.2.10.2 tls
2125 1.2.10.2 tls /*
2126 1.2.10.2 tls * These should probably be supported by VOP_PATHCONF(), but
2127 1.2.10.2 tls * until msdosfs is exportable (why would you want to?), the
2128 1.2.10.2 tls * Unix defaults should be ok.
2129 1.2.10.2 tls */
2130 1.2.10.2 tls pc->pc_caseinsensitive = newnfs_false;
2131 1.2.10.2 tls pc->pc_casepreserving = newnfs_true;
2132 1.2.10.2 tls }
2133 1.2.10.2 tls
2134 1.2.10.2 tls out:
2135 1.2.10.2 tls NFSEXITCODE2(0, nd);
2136 1.2.10.2 tls return (0);
2137 1.2.10.2 tls }
2138 1.2.10.2 tls
2139 1.2.10.2 tls /*
2140 1.2.10.2 tls * nfsv4 lock service
2141 1.2.10.2 tls */
2142 1.2.10.2 tls APPLESTATIC int
2143 1.2.10.2 tls nfsrvd_lock(struct nfsrv_descript *nd, __unused int isdgram,
2144 1.2.10.2 tls vnode_t vp, NFSPROC_T *p, struct nfsexstuff *exp)
2145 1.2.10.2 tls {
2146 1.2.10.2 tls u_int32_t *tl;
2147 1.2.10.2 tls int i;
2148 1.2.10.2 tls struct nfsstate *stp = NULL;
2149 1.2.10.2 tls struct nfslock *lop;
2150 1.2.10.2 tls struct nfslockconflict cf;
2151 1.2.10.2 tls int error = 0;
2152 1.2.10.2 tls u_short flags = NFSLCK_LOCK, lflags;
2153 1.2.10.2 tls u_int64_t offset, len;
2154 1.2.10.2 tls nfsv4stateid_t stateid;
2155 1.2.10.2 tls nfsquad_t clientid;
2156 1.2.10.2 tls
2157 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
2158 1.2.10.2 tls i = fxdr_unsigned(int, *tl++);
2159 1.2.10.2 tls switch (i) {
2160 1.2.10.2 tls case NFSV4LOCKT_READW:
2161 1.2.10.2 tls flags |= NFSLCK_BLOCKING;
2162 1.2.10.2 tls case NFSV4LOCKT_READ:
2163 1.2.10.2 tls lflags = NFSLCK_READ;
2164 1.2.10.2 tls break;
2165 1.2.10.2 tls case NFSV4LOCKT_WRITEW:
2166 1.2.10.2 tls flags |= NFSLCK_BLOCKING;
2167 1.2.10.2 tls case NFSV4LOCKT_WRITE:
2168 1.2.10.2 tls lflags = NFSLCK_WRITE;
2169 1.2.10.2 tls break;
2170 1.2.10.2 tls default:
2171 1.2.10.2 tls nd->nd_repstat = NFSERR_BADXDR;
2172 1.2.10.2 tls goto nfsmout;
2173 1.2.10.2 tls };
2174 1.2.10.2 tls if (*tl++ == newnfs_true)
2175 1.2.10.2 tls flags |= NFSLCK_RECLAIM;
2176 1.2.10.2 tls offset = fxdr_hyper(tl);
2177 1.2.10.2 tls tl += 2;
2178 1.2.10.2 tls len = fxdr_hyper(tl);
2179 1.2.10.2 tls tl += 2;
2180 1.2.10.2 tls if (*tl == newnfs_true)
2181 1.2.10.2 tls flags |= NFSLCK_OPENTOLOCK;
2182 1.2.10.2 tls if (flags & NFSLCK_OPENTOLOCK) {
2183 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED + NFSX_STATEID);
2184 1.2.10.2 tls i = fxdr_unsigned(int, *(tl+4+(NFSX_STATEID / NFSX_UNSIGNED)));
2185 1.2.10.2 tls if (i <= 0 || i > NFSV4_OPAQUELIMIT) {
2186 1.2.10.2 tls nd->nd_repstat = NFSERR_BADXDR;
2187 1.2.10.2 tls goto nfsmout;
2188 1.2.10.2 tls }
2189 1.2.10.2 tls MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate) + i,
2190 1.2.10.2 tls M_NFSDSTATE, M_WAITOK);
2191 1.2.10.2 tls stp->ls_ownerlen = i;
2192 1.2.10.2 tls stp->ls_op = nd->nd_rp;
2193 1.2.10.2 tls stp->ls_seq = fxdr_unsigned(int, *tl++);
2194 1.2.10.2 tls stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
2195 1.2.10.2 tls NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
2196 1.2.10.2 tls NFSX_STATEIDOTHER);
2197 1.2.10.2 tls tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
2198 1.2.10.2 tls stp->ls_opentolockseq = fxdr_unsigned(int, *tl++);
2199 1.2.10.2 tls clientid.lval[0] = *tl++;
2200 1.2.10.2 tls clientid.lval[1] = *tl++;
2201 1.2.10.2 tls if (nd->nd_flag & ND_IMPLIEDCLID) {
2202 1.2.10.2 tls if (nd->nd_clientid.qval != clientid.qval)
2203 1.2.10.2 tls printf("EEK! multiple clids\n");
2204 1.2.10.2 tls } else {
2205 1.2.10.2 tls nd->nd_flag |= ND_IMPLIEDCLID;
2206 1.2.10.2 tls nd->nd_clientid.qval = clientid.qval;
2207 1.2.10.2 tls }
2208 1.2.10.2 tls error = nfsrv_mtostr(nd, stp->ls_owner, stp->ls_ownerlen);
2209 1.2.10.2 tls if (error)
2210 1.2.10.2 tls goto nfsmout;
2211 1.2.10.2 tls } else {
2212 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + NFSX_UNSIGNED);
2213 1.2.10.2 tls MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate),
2214 1.2.10.2 tls M_NFSDSTATE, M_WAITOK);
2215 1.2.10.2 tls stp->ls_ownerlen = 0;
2216 1.2.10.2 tls stp->ls_op = nd->nd_rp;
2217 1.2.10.2 tls stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
2218 1.2.10.2 tls NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
2219 1.2.10.2 tls NFSX_STATEIDOTHER);
2220 1.2.10.2 tls tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
2221 1.2.10.2 tls stp->ls_seq = fxdr_unsigned(int, *tl);
2222 1.2.10.2 tls clientid.lval[0] = stp->ls_stateid.other[0];
2223 1.2.10.2 tls clientid.lval[1] = stp->ls_stateid.other[1];
2224 1.2.10.2 tls if (nd->nd_flag & ND_IMPLIEDCLID) {
2225 1.2.10.2 tls if (nd->nd_clientid.qval != clientid.qval)
2226 1.2.10.2 tls printf("EEK! multiple clids\n");
2227 1.2.10.2 tls } else {
2228 1.2.10.2 tls nd->nd_flag |= ND_IMPLIEDCLID;
2229 1.2.10.2 tls nd->nd_clientid.qval = clientid.qval;
2230 1.2.10.2 tls }
2231 1.2.10.2 tls }
2232 1.2.10.2 tls MALLOC(lop, struct nfslock *, sizeof (struct nfslock),
2233 1.2.10.2 tls M_NFSDLOCK, M_WAITOK);
2234 1.2.10.2 tls lop->lo_first = offset;
2235 1.2.10.2 tls if (len == NFS64BITSSET) {
2236 1.2.10.2 tls lop->lo_end = NFS64BITSSET;
2237 1.2.10.2 tls } else {
2238 1.2.10.2 tls lop->lo_end = offset + len;
2239 1.2.10.2 tls if (lop->lo_end <= lop->lo_first)
2240 1.2.10.2 tls nd->nd_repstat = NFSERR_INVAL;
2241 1.2.10.2 tls }
2242 1.2.10.2 tls lop->lo_flags = lflags;
2243 1.2.10.2 tls stp->ls_flags = flags;
2244 1.2.10.2 tls stp->ls_uid = nd->nd_cred->cr_uid;
2245 1.2.10.2 tls
2246 1.2.10.2 tls /*
2247 1.2.10.2 tls * Do basic access checking.
2248 1.2.10.2 tls */
2249 1.2.10.2 tls if (!nd->nd_repstat && vnode_vtype(vp) != VREG) {
2250 1.2.10.2 tls if (vnode_vtype(vp) == VDIR)
2251 1.2.10.2 tls nd->nd_repstat = NFSERR_ISDIR;
2252 1.2.10.2 tls else
2253 1.2.10.2 tls nd->nd_repstat = NFSERR_INVAL;
2254 1.2.10.2 tls }
2255 1.2.10.2 tls if (!nd->nd_repstat) {
2256 1.2.10.2 tls if (lflags & NFSLCK_WRITE) {
2257 1.2.10.2 tls nd->nd_repstat = nfsvno_accchk(vp, VWRITE,
2258 1.2.10.2 tls nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER,
2259 1.2.10.2 tls NFSACCCHK_VPISLOCKED, NULL);
2260 1.2.10.2 tls } else {
2261 1.2.10.2 tls nd->nd_repstat = nfsvno_accchk(vp, VREAD,
2262 1.2.10.2 tls nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER,
2263 1.2.10.2 tls NFSACCCHK_VPISLOCKED, NULL);
2264 1.2.10.2 tls if (nd->nd_repstat)
2265 1.2.10.2 tls nd->nd_repstat = nfsvno_accchk(vp, VEXEC,
2266 1.2.10.2 tls nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER,
2267 1.2.10.2 tls NFSACCCHK_VPISLOCKED, NULL);
2268 1.2.10.2 tls }
2269 1.2.10.2 tls }
2270 1.2.10.2 tls
2271 1.2.10.2 tls /*
2272 1.2.10.2 tls * We call nfsrv_lockctrl() even if nd_repstat set, so that the
2273 1.2.10.2 tls * seqid# gets updated. nfsrv_lockctrl() will return the value
2274 1.2.10.2 tls * of nd_repstat, if it gets that far.
2275 1.2.10.2 tls */
2276 1.2.10.2 tls nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, &cf, clientid,
2277 1.2.10.2 tls &stateid, exp, nd, p);
2278 1.2.10.2 tls if (lop)
2279 1.2.10.2 tls FREE((caddr_t)lop, M_NFSDLOCK);
2280 1.2.10.2 tls if (stp)
2281 1.2.10.2 tls FREE((caddr_t)stp, M_NFSDSTATE);
2282 1.2.10.2 tls if (!nd->nd_repstat) {
2283 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
2284 1.2.10.2 tls *tl++ = txdr_unsigned(stateid.seqid);
2285 1.2.10.2 tls NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
2286 1.2.10.2 tls } else if (nd->nd_repstat == NFSERR_DENIED) {
2287 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
2288 1.2.10.2 tls txdr_hyper(cf.cl_first, tl);
2289 1.2.10.2 tls tl += 2;
2290 1.2.10.2 tls if (cf.cl_end == NFS64BITSSET)
2291 1.2.10.2 tls len = NFS64BITSSET;
2292 1.2.10.2 tls else
2293 1.2.10.2 tls len = cf.cl_end - cf.cl_first;
2294 1.2.10.2 tls txdr_hyper(len, tl);
2295 1.2.10.2 tls tl += 2;
2296 1.2.10.2 tls if (cf.cl_flags == NFSLCK_WRITE)
2297 1.2.10.2 tls *tl++ = txdr_unsigned(NFSV4LOCKT_WRITE);
2298 1.2.10.2 tls else
2299 1.2.10.2 tls *tl++ = txdr_unsigned(NFSV4LOCKT_READ);
2300 1.2.10.2 tls *tl++ = stateid.other[0];
2301 1.2.10.2 tls *tl = stateid.other[1];
2302 1.2.10.2 tls (void) nfsm_strtom(nd, cf.cl_owner, cf.cl_ownerlen);
2303 1.2.10.2 tls }
2304 1.2.10.2 tls vput(vp);
2305 1.2.10.2 tls NFSEXITCODE2(0, nd);
2306 1.2.10.2 tls return (0);
2307 1.2.10.2 tls nfsmout:
2308 1.2.10.2 tls vput(vp);
2309 1.2.10.2 tls if (stp)
2310 1.2.10.2 tls free((caddr_t)stp, M_NFSDSTATE);
2311 1.2.10.2 tls NFSEXITCODE2(error, nd);
2312 1.2.10.2 tls return (error);
2313 1.2.10.2 tls }
2314 1.2.10.2 tls
2315 1.2.10.2 tls /*
2316 1.2.10.2 tls * nfsv4 lock test service
2317 1.2.10.2 tls */
2318 1.2.10.2 tls APPLESTATIC int
2319 1.2.10.2 tls nfsrvd_lockt(struct nfsrv_descript *nd, __unused int isdgram,
2320 1.2.10.2 tls vnode_t vp, NFSPROC_T *p, struct nfsexstuff *exp)
2321 1.2.10.2 tls {
2322 1.2.10.2 tls u_int32_t *tl;
2323 1.2.10.2 tls int i;
2324 1.2.10.2 tls struct nfsstate *stp = NULL;
2325 1.2.10.2 tls struct nfslock lo, *lop = &lo;
2326 1.2.10.2 tls struct nfslockconflict cf;
2327 1.2.10.2 tls int error = 0;
2328 1.2.10.2 tls nfsv4stateid_t stateid;
2329 1.2.10.2 tls nfsquad_t clientid;
2330 1.2.10.2 tls u_int64_t len;
2331 1.2.10.2 tls
2332 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
2333 1.2.10.2 tls i = fxdr_unsigned(int, *(tl + 7));
2334 1.2.10.2 tls if (i <= 0 || i > NFSV4_OPAQUELIMIT) {
2335 1.2.10.2 tls nd->nd_repstat = NFSERR_BADXDR;
2336 1.2.10.2 tls goto nfsmout;
2337 1.2.10.2 tls }
2338 1.2.10.2 tls MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate) + i,
2339 1.2.10.2 tls M_NFSDSTATE, M_WAITOK);
2340 1.2.10.2 tls stp->ls_ownerlen = i;
2341 1.2.10.2 tls stp->ls_op = NULL;
2342 1.2.10.2 tls stp->ls_flags = NFSLCK_TEST;
2343 1.2.10.2 tls stp->ls_uid = nd->nd_cred->cr_uid;
2344 1.2.10.2 tls i = fxdr_unsigned(int, *tl++);
2345 1.2.10.2 tls switch (i) {
2346 1.2.10.2 tls case NFSV4LOCKT_READW:
2347 1.2.10.2 tls stp->ls_flags |= NFSLCK_BLOCKING;
2348 1.2.10.2 tls case NFSV4LOCKT_READ:
2349 1.2.10.2 tls lo.lo_flags = NFSLCK_READ;
2350 1.2.10.2 tls break;
2351 1.2.10.2 tls case NFSV4LOCKT_WRITEW:
2352 1.2.10.2 tls stp->ls_flags |= NFSLCK_BLOCKING;
2353 1.2.10.2 tls case NFSV4LOCKT_WRITE:
2354 1.2.10.2 tls lo.lo_flags = NFSLCK_WRITE;
2355 1.2.10.2 tls break;
2356 1.2.10.2 tls default:
2357 1.2.10.2 tls nd->nd_repstat = NFSERR_BADXDR;
2358 1.2.10.2 tls goto nfsmout;
2359 1.2.10.2 tls };
2360 1.2.10.2 tls lo.lo_first = fxdr_hyper(tl);
2361 1.2.10.2 tls tl += 2;
2362 1.2.10.2 tls len = fxdr_hyper(tl);
2363 1.2.10.2 tls if (len == NFS64BITSSET) {
2364 1.2.10.2 tls lo.lo_end = NFS64BITSSET;
2365 1.2.10.2 tls } else {
2366 1.2.10.2 tls lo.lo_end = lo.lo_first + len;
2367 1.2.10.2 tls if (lo.lo_end <= lo.lo_first)
2368 1.2.10.2 tls nd->nd_repstat = NFSERR_INVAL;
2369 1.2.10.2 tls }
2370 1.2.10.2 tls tl += 2;
2371 1.2.10.2 tls clientid.lval[0] = *tl++;
2372 1.2.10.2 tls clientid.lval[1] = *tl;
2373 1.2.10.2 tls if (nd->nd_flag & ND_IMPLIEDCLID) {
2374 1.2.10.2 tls if (nd->nd_clientid.qval != clientid.qval)
2375 1.2.10.2 tls printf("EEK! multiple clids\n");
2376 1.2.10.2 tls } else {
2377 1.2.10.2 tls nd->nd_flag |= ND_IMPLIEDCLID;
2378 1.2.10.2 tls nd->nd_clientid.qval = clientid.qval;
2379 1.2.10.2 tls }
2380 1.2.10.2 tls error = nfsrv_mtostr(nd, stp->ls_owner, stp->ls_ownerlen);
2381 1.2.10.2 tls if (error)
2382 1.2.10.2 tls goto nfsmout;
2383 1.2.10.2 tls if (!nd->nd_repstat && vnode_vtype(vp) != VREG) {
2384 1.2.10.2 tls if (vnode_vtype(vp) == VDIR)
2385 1.2.10.2 tls nd->nd_repstat = NFSERR_ISDIR;
2386 1.2.10.2 tls else
2387 1.2.10.2 tls nd->nd_repstat = NFSERR_INVAL;
2388 1.2.10.2 tls }
2389 1.2.10.2 tls if (!nd->nd_repstat)
2390 1.2.10.2 tls nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, &cf, clientid,
2391 1.2.10.2 tls &stateid, exp, nd, p);
2392 1.2.10.2 tls if (stp)
2393 1.2.10.2 tls FREE((caddr_t)stp, M_NFSDSTATE);
2394 1.2.10.2 tls if (nd->nd_repstat) {
2395 1.2.10.2 tls if (nd->nd_repstat == NFSERR_DENIED) {
2396 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
2397 1.2.10.2 tls txdr_hyper(cf.cl_first, tl);
2398 1.2.10.2 tls tl += 2;
2399 1.2.10.2 tls if (cf.cl_end == NFS64BITSSET)
2400 1.2.10.2 tls len = NFS64BITSSET;
2401 1.2.10.2 tls else
2402 1.2.10.2 tls len = cf.cl_end - cf.cl_first;
2403 1.2.10.2 tls txdr_hyper(len, tl);
2404 1.2.10.2 tls tl += 2;
2405 1.2.10.2 tls if (cf.cl_flags == NFSLCK_WRITE)
2406 1.2.10.2 tls *tl++ = txdr_unsigned(NFSV4LOCKT_WRITE);
2407 1.2.10.2 tls else
2408 1.2.10.2 tls *tl++ = txdr_unsigned(NFSV4LOCKT_READ);
2409 1.2.10.2 tls *tl++ = stp->ls_stateid.other[0];
2410 1.2.10.2 tls *tl = stp->ls_stateid.other[1];
2411 1.2.10.2 tls (void) nfsm_strtom(nd, cf.cl_owner, cf.cl_ownerlen);
2412 1.2.10.2 tls }
2413 1.2.10.2 tls }
2414 1.2.10.2 tls vput(vp);
2415 1.2.10.2 tls NFSEXITCODE2(0, nd);
2416 1.2.10.2 tls return (0);
2417 1.2.10.2 tls nfsmout:
2418 1.2.10.2 tls vput(vp);
2419 1.2.10.2 tls if (stp)
2420 1.2.10.2 tls free((caddr_t)stp, M_NFSDSTATE);
2421 1.2.10.2 tls NFSEXITCODE2(error, nd);
2422 1.2.10.2 tls return (error);
2423 1.2.10.2 tls }
2424 1.2.10.2 tls
2425 1.2.10.2 tls /*
2426 1.2.10.2 tls * nfsv4 unlock service
2427 1.2.10.2 tls */
2428 1.2.10.2 tls APPLESTATIC int
2429 1.2.10.2 tls nfsrvd_locku(struct nfsrv_descript *nd, __unused int isdgram,
2430 1.2.10.2 tls vnode_t vp, NFSPROC_T *p, struct nfsexstuff *exp)
2431 1.2.10.2 tls {
2432 1.2.10.2 tls u_int32_t *tl;
2433 1.2.10.2 tls int i;
2434 1.2.10.2 tls struct nfsstate *stp;
2435 1.2.10.2 tls struct nfslock *lop;
2436 1.2.10.2 tls int error = 0;
2437 1.2.10.2 tls nfsv4stateid_t stateid;
2438 1.2.10.2 tls nfsquad_t clientid;
2439 1.2.10.2 tls u_int64_t len;
2440 1.2.10.2 tls
2441 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, 6 * NFSX_UNSIGNED + NFSX_STATEID);
2442 1.2.10.2 tls MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate),
2443 1.2.10.2 tls M_NFSDSTATE, M_WAITOK);
2444 1.2.10.2 tls MALLOC(lop, struct nfslock *, sizeof (struct nfslock),
2445 1.2.10.2 tls M_NFSDLOCK, M_WAITOK);
2446 1.2.10.2 tls stp->ls_flags = NFSLCK_UNLOCK;
2447 1.2.10.2 tls lop->lo_flags = NFSLCK_UNLOCK;
2448 1.2.10.2 tls stp->ls_op = nd->nd_rp;
2449 1.2.10.2 tls i = fxdr_unsigned(int, *tl++);
2450 1.2.10.2 tls switch (i) {
2451 1.2.10.2 tls case NFSV4LOCKT_READW:
2452 1.2.10.2 tls stp->ls_flags |= NFSLCK_BLOCKING;
2453 1.2.10.2 tls case NFSV4LOCKT_READ:
2454 1.2.10.2 tls break;
2455 1.2.10.2 tls case NFSV4LOCKT_WRITEW:
2456 1.2.10.2 tls stp->ls_flags |= NFSLCK_BLOCKING;
2457 1.2.10.2 tls case NFSV4LOCKT_WRITE:
2458 1.2.10.2 tls break;
2459 1.2.10.2 tls default:
2460 1.2.10.2 tls nd->nd_repstat = NFSERR_BADXDR;
2461 1.2.10.2 tls free(stp, M_NFSDSTATE);
2462 1.2.10.2 tls free(lop, M_NFSDLOCK);
2463 1.2.10.2 tls goto nfsmout;
2464 1.2.10.2 tls };
2465 1.2.10.2 tls stp->ls_ownerlen = 0;
2466 1.2.10.2 tls stp->ls_uid = nd->nd_cred->cr_uid;
2467 1.2.10.2 tls stp->ls_seq = fxdr_unsigned(int, *tl++);
2468 1.2.10.2 tls stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
2469 1.2.10.2 tls NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
2470 1.2.10.2 tls NFSX_STATEIDOTHER);
2471 1.2.10.2 tls tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
2472 1.2.10.2 tls lop->lo_first = fxdr_hyper(tl);
2473 1.2.10.2 tls tl += 2;
2474 1.2.10.2 tls len = fxdr_hyper(tl);
2475 1.2.10.2 tls if (len == NFS64BITSSET) {
2476 1.2.10.2 tls lop->lo_end = NFS64BITSSET;
2477 1.2.10.2 tls } else {
2478 1.2.10.2 tls lop->lo_end = lop->lo_first + len;
2479 1.2.10.2 tls if (lop->lo_end <= lop->lo_first)
2480 1.2.10.2 tls nd->nd_repstat = NFSERR_INVAL;
2481 1.2.10.2 tls }
2482 1.2.10.2 tls clientid.lval[0] = stp->ls_stateid.other[0];
2483 1.2.10.2 tls clientid.lval[1] = stp->ls_stateid.other[1];
2484 1.2.10.2 tls if (nd->nd_flag & ND_IMPLIEDCLID) {
2485 1.2.10.2 tls if (nd->nd_clientid.qval != clientid.qval)
2486 1.2.10.2 tls printf("EEK! multiple clids\n");
2487 1.2.10.2 tls } else {
2488 1.2.10.2 tls nd->nd_flag |= ND_IMPLIEDCLID;
2489 1.2.10.2 tls nd->nd_clientid.qval = clientid.qval;
2490 1.2.10.2 tls }
2491 1.2.10.2 tls if (!nd->nd_repstat && vnode_vtype(vp) != VREG) {
2492 1.2.10.2 tls if (vnode_vtype(vp) == VDIR)
2493 1.2.10.2 tls nd->nd_repstat = NFSERR_ISDIR;
2494 1.2.10.2 tls else
2495 1.2.10.2 tls nd->nd_repstat = NFSERR_INVAL;
2496 1.2.10.2 tls }
2497 1.2.10.2 tls /*
2498 1.2.10.2 tls * Call nfsrv_lockctrl() even if nd_repstat is set, so that the
2499 1.2.10.2 tls * seqid# gets incremented. nfsrv_lockctrl() will return the
2500 1.2.10.2 tls * value of nd_repstat, if it gets that far.
2501 1.2.10.2 tls */
2502 1.2.10.2 tls nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid,
2503 1.2.10.2 tls &stateid, exp, nd, p);
2504 1.2.10.2 tls if (stp)
2505 1.2.10.2 tls FREE((caddr_t)stp, M_NFSDSTATE);
2506 1.2.10.2 tls if (lop)
2507 1.2.10.2 tls free((caddr_t)lop, M_NFSDLOCK);
2508 1.2.10.2 tls if (!nd->nd_repstat) {
2509 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
2510 1.2.10.2 tls *tl++ = txdr_unsigned(stateid.seqid);
2511 1.2.10.2 tls NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
2512 1.2.10.2 tls }
2513 1.2.10.2 tls nfsmout:
2514 1.2.10.2 tls vput(vp);
2515 1.2.10.2 tls NFSEXITCODE2(error, nd);
2516 1.2.10.2 tls return (error);
2517 1.2.10.2 tls }
2518 1.2.10.2 tls
2519 1.2.10.2 tls /*
2520 1.2.10.2 tls * nfsv4 open service
2521 1.2.10.2 tls */
2522 1.2.10.2 tls APPLESTATIC int
2523 1.2.10.2 tls nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
2524 1.2.10.2 tls vnode_t dp, vnode_t *vpp, __unused fhandle_t *fhp, NFSPROC_T *p,
2525 1.2.10.2 tls struct nfsexstuff *exp)
2526 1.2.10.2 tls {
2527 1.2.10.2 tls u_int32_t *tl;
2528 1.2.10.2 tls int i;
2529 1.2.10.2 tls struct nfsstate *stp = NULL;
2530 1.2.10.2 tls int error = 0, create, claim, exclusive_flag = 0;
2531 1.2.10.2 tls u_int32_t rflags = NFSV4OPEN_LOCKTYPEPOSIX, acemask;
2532 1.2.10.2 tls int how = NFSCREATE_UNCHECKED;
2533 1.2.10.2 tls int32_t cverf[2], tverf[2] = { 0, 0 };
2534 1.2.10.2 tls vnode_t vp = NULL, dirp = NULL;
2535 1.2.10.2 tls struct nfsvattr nva, dirfor, diraft;
2536 1.2.10.2 tls struct nameidata named;
2537 1.2.10.2 tls nfsv4stateid_t stateid, delegstateid;
2538 1.2.10.2 tls nfsattrbit_t attrbits;
2539 1.2.10.2 tls nfsquad_t clientid;
2540 1.2.10.2 tls char *bufp = NULL;
2541 1.2.10.2 tls u_long *hashp;
2542 1.2.10.2 tls NFSACL_T *aclp = NULL;
2543 1.2.10.2 tls
2544 1.2.10.2 tls #ifdef NFS4_ACL_EXTATTR_NAME
2545 1.2.10.2 tls aclp = acl_alloc(M_WAITOK);
2546 1.2.10.2 tls aclp->acl_cnt = 0;
2547 1.2.10.2 tls #endif
2548 1.2.10.2 tls NFSZERO_ATTRBIT(&attrbits);
2549 1.2.10.2 tls named.ni_startdir = NULL;
2550 1.2.10.2 tls named.ni_cnd.cn_nameiop = 0;
2551 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
2552 1.2.10.2 tls i = fxdr_unsigned(int, *(tl + 5));
2553 1.2.10.2 tls if (i <= 0 || i > NFSV4_OPAQUELIMIT) {
2554 1.2.10.2 tls nd->nd_repstat = NFSERR_BADXDR;
2555 1.2.10.2 tls goto nfsmout;
2556 1.2.10.2 tls }
2557 1.2.10.2 tls MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate) + i,
2558 1.2.10.2 tls M_NFSDSTATE, M_WAITOK);
2559 1.2.10.2 tls stp->ls_ownerlen = i;
2560 1.2.10.2 tls stp->ls_op = nd->nd_rp;
2561 1.2.10.2 tls stp->ls_flags = NFSLCK_OPEN;
2562 1.2.10.2 tls stp->ls_uid = nd->nd_cred->cr_uid;
2563 1.2.10.2 tls stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++);
2564 1.2.10.2 tls i = fxdr_unsigned(int, *tl++);
2565 1.2.10.2 tls switch (i) {
2566 1.2.10.2 tls case NFSV4OPEN_ACCESSREAD:
2567 1.2.10.2 tls stp->ls_flags |= NFSLCK_READACCESS;
2568 1.2.10.2 tls break;
2569 1.2.10.2 tls case NFSV4OPEN_ACCESSWRITE:
2570 1.2.10.2 tls stp->ls_flags |= NFSLCK_WRITEACCESS;
2571 1.2.10.2 tls break;
2572 1.2.10.2 tls case NFSV4OPEN_ACCESSBOTH:
2573 1.2.10.2 tls stp->ls_flags |= (NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
2574 1.2.10.2 tls break;
2575 1.2.10.2 tls default:
2576 1.2.10.2 tls nd->nd_repstat = NFSERR_INVAL;
2577 1.2.10.2 tls };
2578 1.2.10.2 tls i = fxdr_unsigned(int, *tl++);
2579 1.2.10.2 tls switch (i) {
2580 1.2.10.2 tls case NFSV4OPEN_DENYNONE:
2581 1.2.10.2 tls break;
2582 1.2.10.2 tls case NFSV4OPEN_DENYREAD:
2583 1.2.10.2 tls stp->ls_flags |= NFSLCK_READDENY;
2584 1.2.10.2 tls break;
2585 1.2.10.2 tls case NFSV4OPEN_DENYWRITE:
2586 1.2.10.2 tls stp->ls_flags |= NFSLCK_WRITEDENY;
2587 1.2.10.2 tls break;
2588 1.2.10.2 tls case NFSV4OPEN_DENYBOTH:
2589 1.2.10.2 tls stp->ls_flags |= (NFSLCK_READDENY | NFSLCK_WRITEDENY);
2590 1.2.10.2 tls break;
2591 1.2.10.2 tls default:
2592 1.2.10.2 tls nd->nd_repstat = NFSERR_INVAL;
2593 1.2.10.2 tls };
2594 1.2.10.2 tls clientid.lval[0] = *tl++;
2595 1.2.10.2 tls clientid.lval[1] = *tl;
2596 1.2.10.2 tls if (nd->nd_flag & ND_IMPLIEDCLID) {
2597 1.2.10.2 tls if (nd->nd_clientid.qval != clientid.qval)
2598 1.2.10.2 tls printf("EEK! multiple clids\n");
2599 1.2.10.2 tls } else {
2600 1.2.10.2 tls nd->nd_flag |= ND_IMPLIEDCLID;
2601 1.2.10.2 tls nd->nd_clientid.qval = clientid.qval;
2602 1.2.10.2 tls }
2603 1.2.10.2 tls error = nfsrv_mtostr(nd, stp->ls_owner, stp->ls_ownerlen);
2604 1.2.10.2 tls if (error)
2605 1.2.10.2 tls goto nfsmout;
2606 1.2.10.2 tls NFSVNO_ATTRINIT(&nva);
2607 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2608 1.2.10.2 tls create = fxdr_unsigned(int, *tl);
2609 1.2.10.2 tls if (!nd->nd_repstat)
2610 1.2.10.2 tls nd->nd_repstat = nfsvno_getattr(dp, &dirfor, nd->nd_cred, p, 0);
2611 1.2.10.2 tls if (create == NFSV4OPEN_CREATE) {
2612 1.2.10.2 tls nva.na_type = VREG;
2613 1.2.10.2 tls nva.na_mode = 0;
2614 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2615 1.2.10.2 tls how = fxdr_unsigned(int, *tl);
2616 1.2.10.2 tls switch (how) {
2617 1.2.10.2 tls case NFSCREATE_UNCHECKED:
2618 1.2.10.2 tls case NFSCREATE_GUARDED:
2619 1.2.10.2 tls error = nfsv4_sattr(nd, &nva, &attrbits, aclp, p);
2620 1.2.10.2 tls if (error)
2621 1.2.10.2 tls goto nfsmout;
2622 1.2.10.2 tls /*
2623 1.2.10.2 tls * If the na_gid being set is the same as that of
2624 1.2.10.2 tls * the directory it is going in, clear it, since
2625 1.2.10.2 tls * that is what will be set by default. This allows
2626 1.2.10.2 tls * a user that isn't in that group to do the create.
2627 1.2.10.2 tls */
2628 1.2.10.2 tls if (!nd->nd_repstat && NFSVNO_ISSETGID(&nva) &&
2629 1.2.10.2 tls nva.na_gid == dirfor.na_gid)
2630 1.2.10.2 tls NFSVNO_UNSET(&nva, gid);
2631 1.2.10.2 tls if (!nd->nd_repstat)
2632 1.2.10.2 tls nd->nd_repstat = nfsrv_checkuidgid(nd, &nva);
2633 1.2.10.2 tls break;
2634 1.2.10.2 tls case NFSCREATE_EXCLUSIVE:
2635 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF);
2636 1.2.10.2 tls cverf[0] = *tl++;
2637 1.2.10.2 tls cverf[1] = *tl;
2638 1.2.10.2 tls break;
2639 1.2.10.2 tls default:
2640 1.2.10.2 tls nd->nd_repstat = NFSERR_BADXDR;
2641 1.2.10.2 tls goto nfsmout;
2642 1.2.10.2 tls };
2643 1.2.10.2 tls } else if (create != NFSV4OPEN_NOCREATE) {
2644 1.2.10.2 tls nd->nd_repstat = NFSERR_BADXDR;
2645 1.2.10.2 tls goto nfsmout;
2646 1.2.10.2 tls }
2647 1.2.10.2 tls
2648 1.2.10.2 tls /*
2649 1.2.10.2 tls * Now, handle the claim, which usually includes looking up a
2650 1.2.10.2 tls * name in the directory referenced by dp. The exception is
2651 1.2.10.2 tls * NFSV4OPEN_CLAIMPREVIOUS.
2652 1.2.10.2 tls */
2653 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2654 1.2.10.2 tls claim = fxdr_unsigned(int, *tl);
2655 1.2.10.2 tls if (claim == NFSV4OPEN_CLAIMDELEGATECUR) {
2656 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
2657 1.2.10.2 tls stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
2658 1.2.10.2 tls NFSBCOPY((caddr_t)tl,(caddr_t)stateid.other,NFSX_STATEIDOTHER);
2659 1.2.10.2 tls stp->ls_flags |= NFSLCK_DELEGCUR;
2660 1.2.10.2 tls } else if (claim == NFSV4OPEN_CLAIMDELEGATEPREV) {
2661 1.2.10.2 tls stp->ls_flags |= NFSLCK_DELEGPREV;
2662 1.2.10.2 tls }
2663 1.2.10.2 tls if (claim == NFSV4OPEN_CLAIMNULL || claim == NFSV4OPEN_CLAIMDELEGATECUR
2664 1.2.10.2 tls || claim == NFSV4OPEN_CLAIMDELEGATEPREV) {
2665 1.2.10.2 tls if (!nd->nd_repstat && create == NFSV4OPEN_CREATE &&
2666 1.2.10.2 tls claim != NFSV4OPEN_CLAIMNULL)
2667 1.2.10.2 tls nd->nd_repstat = NFSERR_INVAL;
2668 1.2.10.2 tls if (nd->nd_repstat) {
2669 1.2.10.2 tls nd->nd_repstat = nfsrv_opencheck(clientid,
2670 1.2.10.2 tls &stateid, stp, NULL, nd, p, nd->nd_repstat);
2671 1.2.10.2 tls goto nfsmout;
2672 1.2.10.2 tls }
2673 1.2.10.2 tls if (create == NFSV4OPEN_CREATE)
2674 1.2.10.2 tls NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
2675 1.2.10.2 tls LOCKPARENT | LOCKLEAF | SAVESTART);
2676 1.2.10.2 tls else
2677 1.2.10.2 tls NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP,
2678 1.2.10.2 tls LOCKLEAF | SAVESTART);
2679 1.2.10.2 tls nfsvno_setpathbuf(&named, &bufp, &hashp);
2680 1.2.10.2 tls error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
2681 1.2.10.2 tls if (error) {
2682 1.2.10.2 tls vrele(dp);
2683 1.2.10.2 tls #ifdef NFS4_ACL_EXTATTR_NAME
2684 1.2.10.2 tls acl_free(aclp);
2685 1.2.10.2 tls #endif
2686 1.2.10.2 tls FREE((caddr_t)stp, M_NFSDSTATE);
2687 1.2.10.2 tls nfsvno_relpathbuf(&named);
2688 1.2.10.2 tls NFSEXITCODE2(error, nd);
2689 1.2.10.2 tls return (error);
2690 1.2.10.2 tls }
2691 1.2.10.2 tls if (!nd->nd_repstat) {
2692 1.2.10.2 tls nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp,
2693 1.2.10.2 tls p, &dirp);
2694 1.2.10.2 tls } else {
2695 1.2.10.2 tls vrele(dp);
2696 1.2.10.2 tls nfsvno_relpathbuf(&named);
2697 1.2.10.2 tls }
2698 1.2.10.2 tls if (create == NFSV4OPEN_CREATE) {
2699 1.2.10.2 tls switch (how) {
2700 1.2.10.2 tls case NFSCREATE_UNCHECKED:
2701 1.2.10.2 tls if (named.ni_vp) {
2702 1.2.10.2 tls /*
2703 1.2.10.2 tls * Clear the setable attribute bits, except
2704 1.2.10.2 tls * for Size, if it is being truncated.
2705 1.2.10.2 tls */
2706 1.2.10.2 tls NFSZERO_ATTRBIT(&attrbits);
2707 1.2.10.2 tls if (NFSVNO_ISSETSIZE(&nva))
2708 1.2.10.2 tls NFSSETBIT_ATTRBIT(&attrbits,
2709 1.2.10.2 tls NFSATTRBIT_SIZE);
2710 1.2.10.2 tls }
2711 1.2.10.2 tls break;
2712 1.2.10.2 tls case NFSCREATE_GUARDED:
2713 1.2.10.2 tls if (named.ni_vp && !nd->nd_repstat)
2714 1.2.10.2 tls nd->nd_repstat = EEXIST;
2715 1.2.10.2 tls break;
2716 1.2.10.2 tls case NFSCREATE_EXCLUSIVE:
2717 1.2.10.2 tls exclusive_flag = 1;
2718 1.2.10.2 tls if (!named.ni_vp)
2719 1.2.10.2 tls nva.na_mode = 0;
2720 1.2.10.2 tls };
2721 1.2.10.2 tls }
2722 1.2.10.2 tls nfsvno_open(nd, &named, clientid, &stateid, stp,
2723 1.2.10.2 tls &exclusive_flag, &nva, cverf, create, aclp, &attrbits,
2724 1.2.10.2 tls nd->nd_cred, p, exp, &vp);
2725 1.2.10.2 tls } else if (claim == NFSV4OPEN_CLAIMPREVIOUS) {
2726 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2727 1.2.10.2 tls i = fxdr_unsigned(int, *tl);
2728 1.2.10.2 tls switch (i) {
2729 1.2.10.2 tls case NFSV4OPEN_DELEGATEREAD:
2730 1.2.10.2 tls stp->ls_flags |= NFSLCK_DELEGREAD;
2731 1.2.10.2 tls break;
2732 1.2.10.2 tls case NFSV4OPEN_DELEGATEWRITE:
2733 1.2.10.2 tls stp->ls_flags |= NFSLCK_DELEGWRITE;
2734 1.2.10.2 tls case NFSV4OPEN_DELEGATENONE:
2735 1.2.10.2 tls break;
2736 1.2.10.2 tls default:
2737 1.2.10.2 tls nd->nd_repstat = NFSERR_BADXDR;
2738 1.2.10.2 tls goto nfsmout;
2739 1.2.10.2 tls };
2740 1.2.10.2 tls stp->ls_flags |= NFSLCK_RECLAIM;
2741 1.2.10.2 tls vp = dp;
2742 1.2.10.2 tls NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
2743 1.2.10.2 tls if ((vp->v_iflag & VI_DOOMED) == 0)
2744 1.2.10.2 tls nd->nd_repstat = nfsrv_opencheck(clientid, &stateid,
2745 1.2.10.2 tls stp, vp, nd, p, nd->nd_repstat);
2746 1.2.10.2 tls else
2747 1.2.10.2 tls nd->nd_repstat = NFSERR_PERM;
2748 1.2.10.2 tls } else {
2749 1.2.10.2 tls nd->nd_repstat = NFSERR_BADXDR;
2750 1.2.10.2 tls goto nfsmout;
2751 1.2.10.2 tls }
2752 1.2.10.2 tls
2753 1.2.10.2 tls /*
2754 1.2.10.2 tls * Do basic access checking.
2755 1.2.10.2 tls */
2756 1.2.10.2 tls if (!nd->nd_repstat && vnode_vtype(vp) != VREG) {
2757 1.2.10.2 tls /*
2758 1.2.10.2 tls * The IETF working group decided that this is the correct
2759 1.2.10.2 tls * error return for all non-regular files.
2760 1.2.10.2 tls */
2761 1.2.10.2 tls nd->nd_repstat = NFSERR_SYMLINK;
2762 1.2.10.2 tls }
2763 1.2.10.2 tls if (!nd->nd_repstat && (stp->ls_flags & NFSLCK_WRITEACCESS))
2764 1.2.10.2 tls nd->nd_repstat = nfsvno_accchk(vp, VWRITE, nd->nd_cred,
2765 1.2.10.2 tls exp, p, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, NULL);
2766 1.2.10.2 tls if (!nd->nd_repstat && (stp->ls_flags & NFSLCK_READACCESS)) {
2767 1.2.10.2 tls nd->nd_repstat = nfsvno_accchk(vp, VREAD, nd->nd_cred,
2768 1.2.10.2 tls exp, p, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, NULL);
2769 1.2.10.2 tls if (nd->nd_repstat)
2770 1.2.10.2 tls nd->nd_repstat = nfsvno_accchk(vp, VEXEC,
2771 1.2.10.2 tls nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER,
2772 1.2.10.2 tls NFSACCCHK_VPISLOCKED, NULL);
2773 1.2.10.2 tls }
2774 1.2.10.2 tls
2775 1.2.10.2 tls if (!nd->nd_repstat) {
2776 1.2.10.2 tls nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1);
2777 1.2.10.2 tls if (!nd->nd_repstat) {
2778 1.2.10.2 tls tverf[0] = nva.na_atime.tv_sec;
2779 1.2.10.2 tls tverf[1] = nva.na_atime.tv_nsec;
2780 1.2.10.2 tls }
2781 1.2.10.2 tls }
2782 1.2.10.2 tls if (!nd->nd_repstat && exclusive_flag && (cverf[0] != tverf[0] ||
2783 1.2.10.2 tls cverf[1] != tverf[1]))
2784 1.2.10.2 tls nd->nd_repstat = EEXIST;
2785 1.2.10.2 tls /*
2786 1.2.10.2 tls * Do the open locking/delegation stuff.
2787 1.2.10.2 tls */
2788 1.2.10.2 tls if (!nd->nd_repstat)
2789 1.2.10.2 tls nd->nd_repstat = nfsrv_openctrl(nd, vp, &stp, clientid, &stateid,
2790 1.2.10.2 tls &delegstateid, &rflags, exp, p, nva.na_filerev);
2791 1.2.10.2 tls
2792 1.2.10.2 tls /*
2793 1.2.10.2 tls * vp must be unlocked before the call to nfsvno_getattr(dirp,...)
2794 1.2.10.2 tls * below, to avoid a deadlock with the lookup in nfsvno_namei() above.
2795 1.2.10.2 tls * (ie: Leave the NFSVOPUNLOCK() about here.)
2796 1.2.10.2 tls */
2797 1.2.10.2 tls if (vp)
2798 1.2.10.2 tls NFSVOPUNLOCK(vp, 0);
2799 1.2.10.2 tls if (stp)
2800 1.2.10.2 tls FREE((caddr_t)stp, M_NFSDSTATE);
2801 1.2.10.2 tls if (!nd->nd_repstat && dirp)
2802 1.2.10.2 tls nd->nd_repstat = nfsvno_getattr(dirp, &diraft, nd->nd_cred, p,
2803 1.2.10.2 tls 0);
2804 1.2.10.2 tls if (!nd->nd_repstat) {
2805 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID + 6 * NFSX_UNSIGNED);
2806 1.2.10.2 tls *tl++ = txdr_unsigned(stateid.seqid);
2807 1.2.10.2 tls NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
2808 1.2.10.2 tls tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
2809 1.2.10.2 tls if (claim == NFSV4OPEN_CLAIMPREVIOUS) {
2810 1.2.10.2 tls *tl++ = newnfs_true;
2811 1.2.10.2 tls *tl++ = 0;
2812 1.2.10.2 tls *tl++ = 0;
2813 1.2.10.2 tls *tl++ = 0;
2814 1.2.10.2 tls *tl++ = 0;
2815 1.2.10.2 tls } else {
2816 1.2.10.2 tls *tl++ = newnfs_false; /* Since dirp is not locked */
2817 1.2.10.2 tls txdr_hyper(dirfor.na_filerev, tl);
2818 1.2.10.2 tls tl += 2;
2819 1.2.10.2 tls txdr_hyper(diraft.na_filerev, tl);
2820 1.2.10.2 tls tl += 2;
2821 1.2.10.2 tls }
2822 1.2.10.2 tls *tl = txdr_unsigned(rflags & NFSV4OPEN_RFLAGS);
2823 1.2.10.2 tls (void) nfsrv_putattrbit(nd, &attrbits);
2824 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2825 1.2.10.2 tls if (rflags & NFSV4OPEN_READDELEGATE)
2826 1.2.10.2 tls *tl = txdr_unsigned(NFSV4OPEN_DELEGATEREAD);
2827 1.2.10.2 tls else if (rflags & NFSV4OPEN_WRITEDELEGATE)
2828 1.2.10.2 tls *tl = txdr_unsigned(NFSV4OPEN_DELEGATEWRITE);
2829 1.2.10.2 tls else
2830 1.2.10.2 tls *tl = txdr_unsigned(NFSV4OPEN_DELEGATENONE);
2831 1.2.10.2 tls if (rflags & (NFSV4OPEN_READDELEGATE|NFSV4OPEN_WRITEDELEGATE)) {
2832 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID+NFSX_UNSIGNED);
2833 1.2.10.2 tls *tl++ = txdr_unsigned(delegstateid.seqid);
2834 1.2.10.2 tls NFSBCOPY((caddr_t)delegstateid.other, (caddr_t)tl,
2835 1.2.10.2 tls NFSX_STATEIDOTHER);
2836 1.2.10.2 tls tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
2837 1.2.10.2 tls if (rflags & NFSV4OPEN_RECALL)
2838 1.2.10.2 tls *tl = newnfs_true;
2839 1.2.10.2 tls else
2840 1.2.10.2 tls *tl = newnfs_false;
2841 1.2.10.2 tls if (rflags & NFSV4OPEN_WRITEDELEGATE) {
2842 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2843 1.2.10.2 tls *tl++ = txdr_unsigned(NFSV4OPEN_LIMITSIZE);
2844 1.2.10.2 tls txdr_hyper(nva.na_size, tl);
2845 1.2.10.2 tls }
2846 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2847 1.2.10.2 tls *tl++ = txdr_unsigned(NFSV4ACE_ALLOWEDTYPE);
2848 1.2.10.2 tls *tl++ = txdr_unsigned(0x0);
2849 1.2.10.2 tls acemask = NFSV4ACE_ALLFILESMASK;
2850 1.2.10.2 tls if (nva.na_mode & S_IRUSR)
2851 1.2.10.2 tls acemask |= NFSV4ACE_READMASK;
2852 1.2.10.2 tls if (nva.na_mode & S_IWUSR)
2853 1.2.10.2 tls acemask |= NFSV4ACE_WRITEMASK;
2854 1.2.10.2 tls if (nva.na_mode & S_IXUSR)
2855 1.2.10.2 tls acemask |= NFSV4ACE_EXECUTEMASK;
2856 1.2.10.2 tls *tl = txdr_unsigned(acemask);
2857 1.2.10.2 tls (void) nfsm_strtom(nd, "OWNER@", 6);
2858 1.2.10.2 tls }
2859 1.2.10.2 tls *vpp = vp;
2860 1.2.10.2 tls } else if (vp) {
2861 1.2.10.2 tls vrele(vp);
2862 1.2.10.2 tls }
2863 1.2.10.2 tls if (dirp)
2864 1.2.10.2 tls vrele(dirp);
2865 1.2.10.2 tls #ifdef NFS4_ACL_EXTATTR_NAME
2866 1.2.10.2 tls acl_free(aclp);
2867 1.2.10.2 tls #endif
2868 1.2.10.2 tls NFSEXITCODE2(0, nd);
2869 1.2.10.2 tls return (0);
2870 1.2.10.2 tls nfsmout:
2871 1.2.10.2 tls vrele(dp);
2872 1.2.10.2 tls #ifdef NFS4_ACL_EXTATTR_NAME
2873 1.2.10.2 tls acl_free(aclp);
2874 1.2.10.2 tls #endif
2875 1.2.10.2 tls if (stp)
2876 1.2.10.2 tls FREE((caddr_t)stp, M_NFSDSTATE);
2877 1.2.10.2 tls NFSEXITCODE2(error, nd);
2878 1.2.10.2 tls return (error);
2879 1.2.10.2 tls }
2880 1.2.10.2 tls
2881 1.2.10.2 tls /*
2882 1.2.10.2 tls * nfsv4 close service
2883 1.2.10.2 tls */
2884 1.2.10.2 tls APPLESTATIC int
2885 1.2.10.2 tls nfsrvd_close(struct nfsrv_descript *nd, __unused int isdgram,
2886 1.2.10.2 tls vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp)
2887 1.2.10.2 tls {
2888 1.2.10.2 tls u_int32_t *tl;
2889 1.2.10.2 tls struct nfsstate st, *stp = &st;
2890 1.2.10.2 tls int error = 0;
2891 1.2.10.2 tls nfsv4stateid_t stateid;
2892 1.2.10.2 tls nfsquad_t clientid;
2893 1.2.10.2 tls
2894 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID);
2895 1.2.10.2 tls stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++);
2896 1.2.10.2 tls stp->ls_ownerlen = 0;
2897 1.2.10.2 tls stp->ls_op = nd->nd_rp;
2898 1.2.10.2 tls stp->ls_uid = nd->nd_cred->cr_uid;
2899 1.2.10.2 tls stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
2900 1.2.10.2 tls NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
2901 1.2.10.2 tls NFSX_STATEIDOTHER);
2902 1.2.10.2 tls stp->ls_flags = NFSLCK_CLOSE;
2903 1.2.10.2 tls clientid.lval[0] = stp->ls_stateid.other[0];
2904 1.2.10.2 tls clientid.lval[1] = stp->ls_stateid.other[1];
2905 1.2.10.2 tls if (nd->nd_flag & ND_IMPLIEDCLID) {
2906 1.2.10.2 tls if (nd->nd_clientid.qval != clientid.qval)
2907 1.2.10.2 tls printf("EEK! multiple clids\n");
2908 1.2.10.2 tls } else {
2909 1.2.10.2 tls nd->nd_flag |= ND_IMPLIEDCLID;
2910 1.2.10.2 tls nd->nd_clientid.qval = clientid.qval;
2911 1.2.10.2 tls }
2912 1.2.10.2 tls nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p);
2913 1.2.10.2 tls vput(vp);
2914 1.2.10.2 tls if (!nd->nd_repstat) {
2915 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
2916 1.2.10.2 tls *tl++ = txdr_unsigned(stateid.seqid);
2917 1.2.10.2 tls NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
2918 1.2.10.2 tls }
2919 1.2.10.2 tls NFSEXITCODE2(0, nd);
2920 1.2.10.2 tls return (0);
2921 1.2.10.2 tls nfsmout:
2922 1.2.10.2 tls vput(vp);
2923 1.2.10.2 tls NFSEXITCODE2(error, nd);
2924 1.2.10.2 tls return (error);
2925 1.2.10.2 tls }
2926 1.2.10.2 tls
2927 1.2.10.2 tls /*
2928 1.2.10.2 tls * nfsv4 delegpurge service
2929 1.2.10.2 tls */
2930 1.2.10.2 tls APPLESTATIC int
2931 1.2.10.2 tls nfsrvd_delegpurge(struct nfsrv_descript *nd, __unused int isdgram,
2932 1.2.10.2 tls __unused vnode_t vp, __unused NFSPROC_T *p, __unused struct nfsexstuff *exp)
2933 1.2.10.2 tls {
2934 1.2.10.2 tls u_int32_t *tl;
2935 1.2.10.2 tls int error = 0;
2936 1.2.10.2 tls nfsquad_t clientid;
2937 1.2.10.2 tls
2938 1.2.10.2 tls if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
2939 1.2.10.2 tls nd->nd_repstat = NFSERR_WRONGSEC;
2940 1.2.10.2 tls goto nfsmout;
2941 1.2.10.2 tls }
2942 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2943 1.2.10.2 tls clientid.lval[0] = *tl++;
2944 1.2.10.2 tls clientid.lval[1] = *tl;
2945 1.2.10.2 tls if (nd->nd_flag & ND_IMPLIEDCLID) {
2946 1.2.10.2 tls if (nd->nd_clientid.qval != clientid.qval)
2947 1.2.10.2 tls printf("EEK! multiple clids\n");
2948 1.2.10.2 tls } else {
2949 1.2.10.2 tls nd->nd_flag |= ND_IMPLIEDCLID;
2950 1.2.10.2 tls nd->nd_clientid.qval = clientid.qval;
2951 1.2.10.2 tls }
2952 1.2.10.2 tls nd->nd_repstat = nfsrv_delegupdate(clientid, NULL, NULL,
2953 1.2.10.2 tls NFSV4OP_DELEGPURGE, nd->nd_cred, p);
2954 1.2.10.2 tls nfsmout:
2955 1.2.10.2 tls NFSEXITCODE2(error, nd);
2956 1.2.10.2 tls return (error);
2957 1.2.10.2 tls }
2958 1.2.10.2 tls
2959 1.2.10.2 tls /*
2960 1.2.10.2 tls * nfsv4 delegreturn service
2961 1.2.10.2 tls */
2962 1.2.10.2 tls APPLESTATIC int
2963 1.2.10.2 tls nfsrvd_delegreturn(struct nfsrv_descript *nd, __unused int isdgram,
2964 1.2.10.2 tls vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp)
2965 1.2.10.2 tls {
2966 1.2.10.2 tls u_int32_t *tl;
2967 1.2.10.2 tls int error = 0;
2968 1.2.10.2 tls nfsv4stateid_t stateid;
2969 1.2.10.2 tls nfsquad_t clientid;
2970 1.2.10.2 tls
2971 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
2972 1.2.10.2 tls stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
2973 1.2.10.2 tls NFSBCOPY((caddr_t)tl, (caddr_t)stateid.other, NFSX_STATEIDOTHER);
2974 1.2.10.2 tls clientid.lval[0] = stateid.other[0];
2975 1.2.10.2 tls clientid.lval[1] = stateid.other[1];
2976 1.2.10.2 tls if (nd->nd_flag & ND_IMPLIEDCLID) {
2977 1.2.10.2 tls if (nd->nd_clientid.qval != clientid.qval)
2978 1.2.10.2 tls printf("EEK! multiple clids\n");
2979 1.2.10.2 tls } else {
2980 1.2.10.2 tls nd->nd_flag |= ND_IMPLIEDCLID;
2981 1.2.10.2 tls nd->nd_clientid.qval = clientid.qval;
2982 1.2.10.2 tls }
2983 1.2.10.2 tls nd->nd_repstat = nfsrv_delegupdate(clientid, &stateid, vp,
2984 1.2.10.2 tls NFSV4OP_DELEGRETURN, nd->nd_cred, p);
2985 1.2.10.2 tls nfsmout:
2986 1.2.10.2 tls vput(vp);
2987 1.2.10.2 tls NFSEXITCODE2(error, nd);
2988 1.2.10.2 tls return (error);
2989 1.2.10.2 tls }
2990 1.2.10.2 tls
2991 1.2.10.2 tls /*
2992 1.2.10.2 tls * nfsv4 get file handle service
2993 1.2.10.2 tls */
2994 1.2.10.2 tls APPLESTATIC int
2995 1.2.10.2 tls nfsrvd_getfh(struct nfsrv_descript *nd, __unused int isdgram,
2996 1.2.10.2 tls vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp)
2997 1.2.10.2 tls {
2998 1.2.10.2 tls fhandle_t fh;
2999 1.2.10.2 tls
3000 1.2.10.2 tls nd->nd_repstat = nfsvno_getfh(vp, &fh, p);
3001 1.2.10.2 tls vput(vp);
3002 1.2.10.2 tls if (!nd->nd_repstat)
3003 1.2.10.2 tls (void) nfsm_fhtom(nd, (u_int8_t *)&fh, 0, 0);
3004 1.2.10.2 tls NFSEXITCODE2(0, nd);
3005 1.2.10.2 tls return (0);
3006 1.2.10.2 tls }
3007 1.2.10.2 tls
3008 1.2.10.2 tls /*
3009 1.2.10.2 tls * nfsv4 open confirm service
3010 1.2.10.2 tls */
3011 1.2.10.2 tls APPLESTATIC int
3012 1.2.10.2 tls nfsrvd_openconfirm(struct nfsrv_descript *nd, __unused int isdgram,
3013 1.2.10.2 tls vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp)
3014 1.2.10.2 tls {
3015 1.2.10.2 tls u_int32_t *tl;
3016 1.2.10.2 tls struct nfsstate st, *stp = &st;
3017 1.2.10.2 tls int error = 0;
3018 1.2.10.2 tls nfsv4stateid_t stateid;
3019 1.2.10.2 tls nfsquad_t clientid;
3020 1.2.10.2 tls
3021 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + NFSX_UNSIGNED);
3022 1.2.10.2 tls stp->ls_ownerlen = 0;
3023 1.2.10.2 tls stp->ls_op = nd->nd_rp;
3024 1.2.10.2 tls stp->ls_uid = nd->nd_cred->cr_uid;
3025 1.2.10.2 tls stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
3026 1.2.10.2 tls NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
3027 1.2.10.2 tls NFSX_STATEIDOTHER);
3028 1.2.10.2 tls tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
3029 1.2.10.2 tls stp->ls_seq = fxdr_unsigned(u_int32_t, *tl);
3030 1.2.10.2 tls stp->ls_flags = NFSLCK_CONFIRM;
3031 1.2.10.2 tls clientid.lval[0] = stp->ls_stateid.other[0];
3032 1.2.10.2 tls clientid.lval[1] = stp->ls_stateid.other[1];
3033 1.2.10.2 tls if (nd->nd_flag & ND_IMPLIEDCLID) {
3034 1.2.10.2 tls if (nd->nd_clientid.qval != clientid.qval)
3035 1.2.10.2 tls printf("EEK! multiple clids\n");
3036 1.2.10.2 tls } else {
3037 1.2.10.2 tls nd->nd_flag |= ND_IMPLIEDCLID;
3038 1.2.10.2 tls nd->nd_clientid.qval = clientid.qval;
3039 1.2.10.2 tls }
3040 1.2.10.2 tls nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p);
3041 1.2.10.2 tls if (!nd->nd_repstat) {
3042 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
3043 1.2.10.2 tls *tl++ = txdr_unsigned(stateid.seqid);
3044 1.2.10.2 tls NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
3045 1.2.10.2 tls }
3046 1.2.10.2 tls nfsmout:
3047 1.2.10.2 tls vput(vp);
3048 1.2.10.2 tls NFSEXITCODE2(error, nd);
3049 1.2.10.2 tls return (error);
3050 1.2.10.2 tls }
3051 1.2.10.2 tls
3052 1.2.10.2 tls /*
3053 1.2.10.2 tls * nfsv4 open downgrade service
3054 1.2.10.2 tls */
3055 1.2.10.2 tls APPLESTATIC int
3056 1.2.10.2 tls nfsrvd_opendowngrade(struct nfsrv_descript *nd, __unused int isdgram,
3057 1.2.10.2 tls vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp)
3058 1.2.10.2 tls {
3059 1.2.10.2 tls u_int32_t *tl;
3060 1.2.10.2 tls int i;
3061 1.2.10.2 tls struct nfsstate st, *stp = &st;
3062 1.2.10.2 tls int error = 0;
3063 1.2.10.2 tls nfsv4stateid_t stateid;
3064 1.2.10.2 tls nfsquad_t clientid;
3065 1.2.10.2 tls
3066 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + 3 * NFSX_UNSIGNED);
3067 1.2.10.2 tls stp->ls_ownerlen = 0;
3068 1.2.10.2 tls stp->ls_op = nd->nd_rp;
3069 1.2.10.2 tls stp->ls_uid = nd->nd_cred->cr_uid;
3070 1.2.10.2 tls stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
3071 1.2.10.2 tls NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
3072 1.2.10.2 tls NFSX_STATEIDOTHER);
3073 1.2.10.2 tls tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
3074 1.2.10.2 tls stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++);
3075 1.2.10.2 tls i = fxdr_unsigned(int, *tl++);
3076 1.2.10.2 tls switch (i) {
3077 1.2.10.2 tls case NFSV4OPEN_ACCESSREAD:
3078 1.2.10.2 tls stp->ls_flags = (NFSLCK_READACCESS | NFSLCK_DOWNGRADE);
3079 1.2.10.2 tls break;
3080 1.2.10.2 tls case NFSV4OPEN_ACCESSWRITE:
3081 1.2.10.2 tls stp->ls_flags = (NFSLCK_WRITEACCESS | NFSLCK_DOWNGRADE);
3082 1.2.10.2 tls break;
3083 1.2.10.2 tls case NFSV4OPEN_ACCESSBOTH:
3084 1.2.10.2 tls stp->ls_flags = (NFSLCK_READACCESS | NFSLCK_WRITEACCESS |
3085 1.2.10.2 tls NFSLCK_DOWNGRADE);
3086 1.2.10.2 tls break;
3087 1.2.10.2 tls default:
3088 1.2.10.2 tls nd->nd_repstat = NFSERR_BADXDR;
3089 1.2.10.2 tls };
3090 1.2.10.2 tls i = fxdr_unsigned(int, *tl);
3091 1.2.10.2 tls switch (i) {
3092 1.2.10.2 tls case NFSV4OPEN_DENYNONE:
3093 1.2.10.2 tls break;
3094 1.2.10.2 tls case NFSV4OPEN_DENYREAD:
3095 1.2.10.2 tls stp->ls_flags |= NFSLCK_READDENY;
3096 1.2.10.2 tls break;
3097 1.2.10.2 tls case NFSV4OPEN_DENYWRITE:
3098 1.2.10.2 tls stp->ls_flags |= NFSLCK_WRITEDENY;
3099 1.2.10.2 tls break;
3100 1.2.10.2 tls case NFSV4OPEN_DENYBOTH:
3101 1.2.10.2 tls stp->ls_flags |= (NFSLCK_READDENY | NFSLCK_WRITEDENY);
3102 1.2.10.2 tls break;
3103 1.2.10.2 tls default:
3104 1.2.10.2 tls nd->nd_repstat = NFSERR_BADXDR;
3105 1.2.10.2 tls };
3106 1.2.10.2 tls
3107 1.2.10.2 tls clientid.lval[0] = stp->ls_stateid.other[0];
3108 1.2.10.2 tls clientid.lval[1] = stp->ls_stateid.other[1];
3109 1.2.10.2 tls if (nd->nd_flag & ND_IMPLIEDCLID) {
3110 1.2.10.2 tls if (nd->nd_clientid.qval != clientid.qval)
3111 1.2.10.2 tls printf("EEK! multiple clids\n");
3112 1.2.10.2 tls } else {
3113 1.2.10.2 tls nd->nd_flag |= ND_IMPLIEDCLID;
3114 1.2.10.2 tls nd->nd_clientid.qval = clientid.qval;
3115 1.2.10.2 tls }
3116 1.2.10.2 tls if (!nd->nd_repstat)
3117 1.2.10.2 tls nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid,
3118 1.2.10.2 tls nd, p);
3119 1.2.10.2 tls if (!nd->nd_repstat) {
3120 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
3121 1.2.10.2 tls *tl++ = txdr_unsigned(stateid.seqid);
3122 1.2.10.2 tls NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
3123 1.2.10.2 tls }
3124 1.2.10.2 tls nfsmout:
3125 1.2.10.2 tls vput(vp);
3126 1.2.10.2 tls NFSEXITCODE2(error, nd);
3127 1.2.10.2 tls return (error);
3128 1.2.10.2 tls }
3129 1.2.10.2 tls
3130 1.2.10.2 tls /*
3131 1.2.10.2 tls * nfsv4 renew lease service
3132 1.2.10.2 tls */
3133 1.2.10.2 tls APPLESTATIC int
3134 1.2.10.2 tls nfsrvd_renew(struct nfsrv_descript *nd, __unused int isdgram,
3135 1.2.10.2 tls __unused vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp)
3136 1.2.10.2 tls {
3137 1.2.10.2 tls u_int32_t *tl;
3138 1.2.10.2 tls int error = 0;
3139 1.2.10.2 tls nfsquad_t clientid;
3140 1.2.10.2 tls
3141 1.2.10.2 tls if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
3142 1.2.10.2 tls nd->nd_repstat = NFSERR_WRONGSEC;
3143 1.2.10.2 tls goto nfsmout;
3144 1.2.10.2 tls }
3145 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
3146 1.2.10.2 tls clientid.lval[0] = *tl++;
3147 1.2.10.2 tls clientid.lval[1] = *tl;
3148 1.2.10.2 tls if (nd->nd_flag & ND_IMPLIEDCLID) {
3149 1.2.10.2 tls if (nd->nd_clientid.qval != clientid.qval)
3150 1.2.10.2 tls printf("EEK! multiple clids\n");
3151 1.2.10.2 tls } else {
3152 1.2.10.2 tls nd->nd_flag |= ND_IMPLIEDCLID;
3153 1.2.10.2 tls nd->nd_clientid.qval = clientid.qval;
3154 1.2.10.2 tls }
3155 1.2.10.2 tls nd->nd_repstat = nfsrv_getclient(clientid, (CLOPS_RENEWOP|CLOPS_RENEW),
3156 1.2.10.2 tls NULL, (nfsquad_t)((u_quad_t)0), nd, p);
3157 1.2.10.2 tls nfsmout:
3158 1.2.10.2 tls NFSEXITCODE2(error, nd);
3159 1.2.10.2 tls return (error);
3160 1.2.10.2 tls }
3161 1.2.10.2 tls
3162 1.2.10.2 tls /*
3163 1.2.10.2 tls * nfsv4 security info service
3164 1.2.10.2 tls */
3165 1.2.10.2 tls APPLESTATIC int
3166 1.2.10.2 tls nfsrvd_secinfo(struct nfsrv_descript *nd, int isdgram,
3167 1.2.10.2 tls vnode_t dp, NFSPROC_T *p, struct nfsexstuff *exp)
3168 1.2.10.2 tls {
3169 1.2.10.2 tls u_int32_t *tl;
3170 1.2.10.2 tls int len;
3171 1.2.10.2 tls struct nameidata named;
3172 1.2.10.2 tls vnode_t dirp = NULL, vp;
3173 1.2.10.2 tls struct nfsrvfh fh;
3174 1.2.10.2 tls struct nfsexstuff retnes;
3175 1.2.10.2 tls u_int32_t *sizp;
3176 1.2.10.2 tls int error = 0, savflag, i;
3177 1.2.10.2 tls char *bufp;
3178 1.2.10.2 tls u_long *hashp;
3179 1.2.10.2 tls
3180 1.2.10.2 tls /*
3181 1.2.10.2 tls * All this just to get the export flags for the name.
3182 1.2.10.2 tls */
3183 1.2.10.2 tls NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP,
3184 1.2.10.2 tls LOCKLEAF | SAVESTART);
3185 1.2.10.2 tls nfsvno_setpathbuf(&named, &bufp, &hashp);
3186 1.2.10.2 tls error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
3187 1.2.10.2 tls if (error) {
3188 1.2.10.2 tls vput(dp);
3189 1.2.10.2 tls nfsvno_relpathbuf(&named);
3190 1.2.10.2 tls goto out;
3191 1.2.10.2 tls }
3192 1.2.10.2 tls if (!nd->nd_repstat) {
3193 1.2.10.2 tls nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, p, &dirp);
3194 1.2.10.2 tls } else {
3195 1.2.10.2 tls vput(dp);
3196 1.2.10.2 tls nfsvno_relpathbuf(&named);
3197 1.2.10.2 tls }
3198 1.2.10.2 tls if (dirp)
3199 1.2.10.2 tls vrele(dirp);
3200 1.2.10.2 tls if (nd->nd_repstat)
3201 1.2.10.2 tls goto out;
3202 1.2.10.2 tls vrele(named.ni_startdir);
3203 1.2.10.2 tls nfsvno_relpathbuf(&named);
3204 1.2.10.2 tls fh.nfsrvfh_len = NFSX_MYFH;
3205 1.2.10.2 tls vp = named.ni_vp;
3206 1.2.10.2 tls nd->nd_repstat = nfsvno_getfh(vp, (fhandle_t *)fh.nfsrvfh_data, p);
3207 1.2.10.2 tls vput(vp);
3208 1.2.10.2 tls savflag = nd->nd_flag;
3209 1.2.10.2 tls if (!nd->nd_repstat) {
3210 1.2.10.2 tls nfsd_fhtovp(nd, &fh, LK_SHARED, &vp, &retnes, NULL, 0, p);
3211 1.2.10.2 tls if (vp)
3212 1.2.10.2 tls vput(vp);
3213 1.2.10.2 tls }
3214 1.2.10.2 tls nd->nd_flag = savflag;
3215 1.2.10.2 tls if (nd->nd_repstat)
3216 1.2.10.2 tls goto out;
3217 1.2.10.2 tls
3218 1.2.10.2 tls /*
3219 1.2.10.2 tls * Finally have the export flags for name, so we can create
3220 1.2.10.2 tls * the security info.
3221 1.2.10.2 tls */
3222 1.2.10.2 tls len = 0;
3223 1.2.10.2 tls NFSM_BUILD(sizp, u_int32_t *, NFSX_UNSIGNED);
3224 1.2.10.2 tls for (i = 0; i < retnes.nes_numsecflavor; i++) {
3225 1.2.10.2 tls if (retnes.nes_secflavors[i] == AUTH_SYS) {
3226 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3227 1.2.10.2 tls *tl = txdr_unsigned(RPCAUTH_UNIX);
3228 1.2.10.2 tls len++;
3229 1.2.10.2 tls } else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5) {
3230 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3231 1.2.10.2 tls *tl++ = txdr_unsigned(RPCAUTH_GSS);
3232 1.2.10.2 tls (void) nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
3233 1.2.10.2 tls nfsgss_mechlist[KERBV_MECH].len);
3234 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
3235 1.2.10.2 tls *tl++ = txdr_unsigned(GSS_KERBV_QOP);
3236 1.2.10.2 tls *tl = txdr_unsigned(RPCAUTHGSS_SVCNONE);
3237 1.2.10.2 tls len++;
3238 1.2.10.2 tls } else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5I) {
3239 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3240 1.2.10.2 tls *tl++ = txdr_unsigned(RPCAUTH_GSS);
3241 1.2.10.2 tls (void) nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
3242 1.2.10.2 tls nfsgss_mechlist[KERBV_MECH].len);
3243 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
3244 1.2.10.2 tls *tl++ = txdr_unsigned(GSS_KERBV_QOP);
3245 1.2.10.2 tls *tl = txdr_unsigned(RPCAUTHGSS_SVCINTEGRITY);
3246 1.2.10.2 tls len++;
3247 1.2.10.2 tls } else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5P) {
3248 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3249 1.2.10.2 tls *tl++ = txdr_unsigned(RPCAUTH_GSS);
3250 1.2.10.2 tls (void) nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
3251 1.2.10.2 tls nfsgss_mechlist[KERBV_MECH].len);
3252 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
3253 1.2.10.2 tls *tl++ = txdr_unsigned(GSS_KERBV_QOP);
3254 1.2.10.2 tls *tl = txdr_unsigned(RPCAUTHGSS_SVCPRIVACY);
3255 1.2.10.2 tls len++;
3256 1.2.10.2 tls }
3257 1.2.10.2 tls }
3258 1.2.10.2 tls *sizp = txdr_unsigned(len);
3259 1.2.10.2 tls
3260 1.2.10.2 tls out:
3261 1.2.10.2 tls NFSEXITCODE2(error, nd);
3262 1.2.10.2 tls return (error);
3263 1.2.10.2 tls }
3264 1.2.10.2 tls
3265 1.2.10.2 tls /*
3266 1.2.10.2 tls * nfsv4 set client id service
3267 1.2.10.2 tls */
3268 1.2.10.2 tls APPLESTATIC int
3269 1.2.10.2 tls nfsrvd_setclientid(struct nfsrv_descript *nd, __unused int isdgram,
3270 1.2.10.2 tls __unused vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp)
3271 1.2.10.2 tls {
3272 1.2.10.2 tls u_int32_t *tl;
3273 1.2.10.2 tls int i;
3274 1.2.10.2 tls int error = 0, idlen;
3275 1.2.10.2 tls struct nfsclient *clp = NULL;
3276 1.2.10.2 tls struct sockaddr_in *rad;
3277 1.2.10.2 tls u_char *verf, *ucp, *ucp2, addrbuf[24];
3278 1.2.10.2 tls nfsquad_t clientid, confirm;
3279 1.2.10.2 tls
3280 1.2.10.2 tls if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
3281 1.2.10.2 tls nd->nd_repstat = NFSERR_WRONGSEC;
3282 1.2.10.2 tls goto out;
3283 1.2.10.2 tls }
3284 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF + NFSX_UNSIGNED);
3285 1.2.10.2 tls verf = (u_char *)tl;
3286 1.2.10.2 tls tl += (NFSX_VERF / NFSX_UNSIGNED);
3287 1.2.10.2 tls i = fxdr_unsigned(int, *tl);
3288 1.2.10.2 tls if (i > NFSV4_OPAQUELIMIT || i <= 0) {
3289 1.2.10.2 tls nd->nd_repstat = NFSERR_BADXDR;
3290 1.2.10.2 tls goto nfsmout;
3291 1.2.10.2 tls }
3292 1.2.10.2 tls idlen = i;
3293 1.2.10.2 tls if (nd->nd_flag & ND_GSS)
3294 1.2.10.2 tls i += nd->nd_princlen;
3295 1.2.10.2 tls MALLOC(clp, struct nfsclient *, sizeof (struct nfsclient) + i,
3296 1.2.10.2 tls M_NFSDCLIENT, M_WAITOK);
3297 1.2.10.2 tls NFSBZERO((caddr_t)clp, sizeof (struct nfsclient) + i);
3298 1.2.10.2 tls NFSINITSOCKMUTEX(&clp->lc_req.nr_mtx);
3299 1.2.10.2 tls NFSSOCKADDRALLOC(clp->lc_req.nr_nam);
3300 1.2.10.2 tls NFSSOCKADDRSIZE(clp->lc_req.nr_nam, sizeof (struct sockaddr_in));
3301 1.2.10.2 tls clp->lc_req.nr_cred = NULL;
3302 1.2.10.2 tls NFSBCOPY(verf, clp->lc_verf, NFSX_VERF);
3303 1.2.10.2 tls clp->lc_idlen = idlen;
3304 1.2.10.2 tls error = nfsrv_mtostr(nd, clp->lc_id, idlen);
3305 1.2.10.2 tls if (error)
3306 1.2.10.2 tls goto nfsmout;
3307 1.2.10.2 tls if (nd->nd_flag & ND_GSS) {
3308 1.2.10.2 tls clp->lc_flags = LCL_GSS;
3309 1.2.10.2 tls if (nd->nd_flag & ND_GSSINTEGRITY)
3310 1.2.10.2 tls clp->lc_flags |= LCL_GSSINTEGRITY;
3311 1.2.10.2 tls else if (nd->nd_flag & ND_GSSPRIVACY)
3312 1.2.10.2 tls clp->lc_flags |= LCL_GSSPRIVACY;
3313 1.2.10.2 tls } else {
3314 1.2.10.2 tls clp->lc_flags = 0;
3315 1.2.10.2 tls }
3316 1.2.10.2 tls if ((nd->nd_flag & ND_GSS) && nd->nd_princlen > 0) {
3317 1.2.10.2 tls clp->lc_flags |= LCL_NAME;
3318 1.2.10.2 tls clp->lc_namelen = nd->nd_princlen;
3319 1.2.10.2 tls clp->lc_name = &clp->lc_id[idlen];
3320 1.2.10.2 tls NFSBCOPY(nd->nd_principal, clp->lc_name, clp->lc_namelen);
3321 1.2.10.2 tls } else {
3322 1.2.10.2 tls clp->lc_uid = nd->nd_cred->cr_uid;
3323 1.2.10.2 tls clp->lc_gid = nd->nd_cred->cr_gid;
3324 1.2.10.2 tls }
3325 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
3326 1.2.10.2 tls clp->lc_program = fxdr_unsigned(u_int32_t, *tl);
3327 1.2.10.2 tls error = nfsrv_getclientipaddr(nd, clp);
3328 1.2.10.2 tls if (error)
3329 1.2.10.2 tls goto nfsmout;
3330 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
3331 1.2.10.2 tls clp->lc_callback = fxdr_unsigned(u_int32_t, *tl);
3332 1.2.10.2 tls
3333 1.2.10.2 tls /*
3334 1.2.10.2 tls * nfsrv_setclient() does the actual work of adding it to the
3335 1.2.10.2 tls * client list. If there is no error, the structure has been
3336 1.2.10.2 tls * linked into the client list and clp should no longer be used
3337 1.2.10.2 tls * here. When an error is returned, it has not been linked in,
3338 1.2.10.2 tls * so it should be free'd.
3339 1.2.10.2 tls */
3340 1.2.10.2 tls nd->nd_repstat = nfsrv_setclient(nd, &clp, &clientid, &confirm, p);
3341 1.2.10.2 tls if (nd->nd_repstat == NFSERR_CLIDINUSE) {
3342 1.2.10.2 tls if (clp->lc_flags & LCL_TCPCALLBACK)
3343 1.2.10.2 tls (void) nfsm_strtom(nd, "tcp", 3);
3344 1.2.10.2 tls else
3345 1.2.10.2 tls (void) nfsm_strtom(nd, "udp", 3);
3346 1.2.10.2 tls rad = NFSSOCKADDR(clp->lc_req.nr_nam, struct sockaddr_in *);
3347 1.2.10.2 tls ucp = (u_char *)&rad->sin_addr.s_addr;
3348 1.2.10.2 tls ucp2 = (u_char *)&rad->sin_port;
3349 1.2.10.2 tls snprintf(addrbuf, sizeof(addrbuf), "%d.%d.%d.%d.%d.%d",
3350 1.2.10.2 tls ucp[0] & 0xff, ucp[1] & 0xff, ucp[2] & 0xff, ucp[3] & 0xff,
3351 1.2.10.2 tls ucp2[0] & 0xff, ucp2[1] & 0xff);
3352 1.2.10.2 tls (void) nfsm_strtom(nd, addrbuf, strlen(addrbuf));
3353 1.2.10.2 tls }
3354 1.2.10.2 tls if (clp) {
3355 1.2.10.2 tls NFSSOCKADDRFREE(clp->lc_req.nr_nam);
3356 1.2.10.2 tls NFSFREEMUTEX(&clp->lc_req.nr_mtx);
3357 1.2.10.2 tls free((caddr_t)clp, M_NFSDCLIENT);
3358 1.2.10.2 tls }
3359 1.2.10.2 tls if (!nd->nd_repstat) {
3360 1.2.10.2 tls NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_HYPER);
3361 1.2.10.2 tls *tl++ = clientid.lval[0];
3362 1.2.10.2 tls *tl++ = clientid.lval[1];
3363 1.2.10.2 tls *tl++ = confirm.lval[0];
3364 1.2.10.2 tls *tl = confirm.lval[1];
3365 1.2.10.2 tls }
3366 1.2.10.2 tls
3367 1.2.10.2 tls out:
3368 1.2.10.2 tls NFSEXITCODE2(0, nd);
3369 1.2.10.2 tls return (0);
3370 1.2.10.2 tls nfsmout:
3371 1.2.10.2 tls if (clp) {
3372 1.2.10.2 tls NFSSOCKADDRFREE(clp->lc_req.nr_nam);
3373 1.2.10.2 tls NFSFREEMUTEX(&clp->lc_req.nr_mtx);
3374 1.2.10.2 tls free((caddr_t)clp, M_NFSDCLIENT);
3375 1.2.10.2 tls }
3376 1.2.10.2 tls NFSEXITCODE2(error, nd);
3377 1.2.10.2 tls return (error);
3378 1.2.10.2 tls }
3379 1.2.10.2 tls
3380 1.2.10.2 tls /*
3381 1.2.10.2 tls * nfsv4 set client id confirm service
3382 1.2.10.2 tls */
3383 1.2.10.2 tls APPLESTATIC int
3384 1.2.10.2 tls nfsrvd_setclientidcfrm(struct nfsrv_descript *nd,
3385 1.2.10.2 tls __unused int isdgram, __unused vnode_t vp, NFSPROC_T *p,
3386 1.2.10.2 tls __unused struct nfsexstuff *exp)
3387 1.2.10.2 tls {
3388 1.2.10.2 tls u_int32_t *tl;
3389 1.2.10.2 tls int error = 0;
3390 1.2.10.2 tls nfsquad_t clientid, confirm;
3391 1.2.10.2 tls
3392 1.2.10.2 tls if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
3393 1.2.10.2 tls nd->nd_repstat = NFSERR_WRONGSEC;
3394 1.2.10.2 tls goto nfsmout;
3395 1.2.10.2 tls }
3396 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_HYPER);
3397 1.2.10.2 tls clientid.lval[0] = *tl++;
3398 1.2.10.2 tls clientid.lval[1] = *tl++;
3399 1.2.10.2 tls confirm.lval[0] = *tl++;
3400 1.2.10.2 tls confirm.lval[1] = *tl;
3401 1.2.10.2 tls
3402 1.2.10.2 tls /*
3403 1.2.10.2 tls * nfsrv_getclient() searches the client list for a match and
3404 1.2.10.2 tls * returns the appropriate NFSERR status.
3405 1.2.10.2 tls */
3406 1.2.10.2 tls nd->nd_repstat = nfsrv_getclient(clientid, (CLOPS_CONFIRM|CLOPS_RENEW),
3407 1.2.10.2 tls NULL, confirm, nd, p);
3408 1.2.10.2 tls nfsmout:
3409 1.2.10.2 tls NFSEXITCODE2(error, nd);
3410 1.2.10.2 tls return (error);
3411 1.2.10.2 tls }
3412 1.2.10.2 tls
3413 1.2.10.2 tls /*
3414 1.2.10.2 tls * nfsv4 verify service
3415 1.2.10.2 tls */
3416 1.2.10.2 tls APPLESTATIC int
3417 1.2.10.2 tls nfsrvd_verify(struct nfsrv_descript *nd, int isdgram,
3418 1.2.10.2 tls vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp)
3419 1.2.10.2 tls {
3420 1.2.10.2 tls int error = 0, ret, fhsize = NFSX_MYFH;
3421 1.2.10.2 tls struct nfsvattr nva;
3422 1.2.10.2 tls struct statfs sf;
3423 1.2.10.2 tls struct nfsfsinfo fs;
3424 1.2.10.2 tls fhandle_t fh;
3425 1.2.10.2 tls
3426 1.2.10.2 tls nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1);
3427 1.2.10.2 tls if (!nd->nd_repstat)
3428 1.2.10.2 tls nd->nd_repstat = nfsvno_statfs(vp, &sf);
3429 1.2.10.2 tls if (!nd->nd_repstat)
3430 1.2.10.2 tls nd->nd_repstat = nfsvno_getfh(vp, &fh, p);
3431 1.2.10.2 tls if (!nd->nd_repstat) {
3432 1.2.10.2 tls nfsvno_getfs(&fs, isdgram);
3433 1.2.10.2 tls error = nfsv4_loadattr(nd, vp, &nva, NULL, &fh, fhsize, NULL,
3434 1.2.10.2 tls &sf, NULL, &fs, NULL, 1, &ret, NULL, NULL, p, nd->nd_cred);
3435 1.2.10.2 tls if (!error) {
3436 1.2.10.2 tls if (nd->nd_procnum == NFSV4OP_NVERIFY) {
3437 1.2.10.2 tls if (ret == 0)
3438 1.2.10.2 tls nd->nd_repstat = NFSERR_SAME;
3439 1.2.10.2 tls else if (ret != NFSERR_NOTSAME)
3440 1.2.10.2 tls nd->nd_repstat = ret;
3441 1.2.10.2 tls } else if (ret)
3442 1.2.10.2 tls nd->nd_repstat = ret;
3443 1.2.10.2 tls }
3444 1.2.10.2 tls }
3445 1.2.10.2 tls vput(vp);
3446 1.2.10.2 tls NFSEXITCODE2(error, nd);
3447 1.2.10.2 tls return (error);
3448 1.2.10.2 tls }
3449 1.2.10.2 tls
3450 1.2.10.2 tls /*
3451 1.2.10.2 tls * nfs openattr rpc
3452 1.2.10.2 tls */
3453 1.2.10.2 tls APPLESTATIC int
3454 1.2.10.2 tls nfsrvd_openattr(struct nfsrv_descript *nd, __unused int isdgram,
3455 1.2.10.2 tls vnode_t dp, __unused vnode_t *vpp, __unused fhandle_t *fhp,
3456 1.2.10.2 tls __unused NFSPROC_T *p, __unused struct nfsexstuff *exp)
3457 1.2.10.2 tls {
3458 1.2.10.2 tls u_int32_t *tl;
3459 1.2.10.2 tls int error = 0, createdir;
3460 1.2.10.2 tls
3461 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
3462 1.2.10.2 tls createdir = fxdr_unsigned(int, *tl);
3463 1.2.10.2 tls nd->nd_repstat = NFSERR_NOTSUPP;
3464 1.2.10.2 tls nfsmout:
3465 1.2.10.2 tls vrele(dp);
3466 1.2.10.2 tls NFSEXITCODE2(error, nd);
3467 1.2.10.2 tls return (error);
3468 1.2.10.2 tls }
3469 1.2.10.2 tls
3470 1.2.10.2 tls /*
3471 1.2.10.2 tls * nfsv4 release lock owner service
3472 1.2.10.2 tls */
3473 1.2.10.2 tls APPLESTATIC int
3474 1.2.10.2 tls nfsrvd_releaselckown(struct nfsrv_descript *nd, __unused int isdgram,
3475 1.2.10.2 tls __unused vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp)
3476 1.2.10.2 tls {
3477 1.2.10.2 tls u_int32_t *tl;
3478 1.2.10.2 tls struct nfsstate *stp = NULL;
3479 1.2.10.2 tls int error = 0, len;
3480 1.2.10.2 tls nfsquad_t clientid;
3481 1.2.10.2 tls
3482 1.2.10.2 tls if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
3483 1.2.10.2 tls nd->nd_repstat = NFSERR_WRONGSEC;
3484 1.2.10.2 tls goto nfsmout;
3485 1.2.10.2 tls }
3486 1.2.10.2 tls NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
3487 1.2.10.2 tls len = fxdr_unsigned(int, *(tl + 2));
3488 1.2.10.2 tls if (len <= 0 || len > NFSV4_OPAQUELIMIT) {
3489 1.2.10.2 tls nd->nd_repstat = NFSERR_BADXDR;
3490 1.2.10.2 tls goto nfsmout;
3491 1.2.10.2 tls }
3492 1.2.10.2 tls MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate) + len,
3493 1.2.10.2 tls M_NFSDSTATE, M_WAITOK);
3494 1.2.10.2 tls stp->ls_ownerlen = len;
3495 1.2.10.2 tls stp->ls_op = NULL;
3496 1.2.10.2 tls stp->ls_flags = NFSLCK_RELEASE;
3497 1.2.10.2 tls stp->ls_uid = nd->nd_cred->cr_uid;
3498 1.2.10.2 tls clientid.lval[0] = *tl++;
3499 1.2.10.2 tls clientid.lval[1] = *tl;
3500 1.2.10.2 tls if (nd->nd_flag & ND_IMPLIEDCLID) {
3501 1.2.10.2 tls if (nd->nd_clientid.qval != clientid.qval)
3502 1.2.10.2 tls printf("EEK! multiple clids\n");
3503 1.2.10.2 tls } else {
3504 1.2.10.2 tls nd->nd_flag |= ND_IMPLIEDCLID;
3505 1.2.10.2 tls nd->nd_clientid.qval = clientid.qval;
3506 1.2.10.2 tls }
3507 1.2.10.2 tls error = nfsrv_mtostr(nd, stp->ls_owner, len);
3508 1.2.10.2 tls if (error)
3509 1.2.10.2 tls goto nfsmout;
3510 1.2.10.2 tls nd->nd_repstat = nfsrv_releaselckown(stp, clientid, p);
3511 1.2.10.2 tls FREE((caddr_t)stp, M_NFSDSTATE);
3512 1.2.10.2 tls
3513 1.2.10.2 tls NFSEXITCODE2(0, nd);
3514 1.2.10.2 tls return (0);
3515 1.2.10.2 tls nfsmout:
3516 1.2.10.2 tls if (stp)
3517 1.2.10.2 tls free((caddr_t)stp, M_NFSDSTATE);
3518 1.2.10.2 tls NFSEXITCODE2(error, nd);
3519 1.2.10.2 tls return (error);
3520 1.2.10.2 tls }
3521