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