xref: /freebsd/sys/fs/nfsserver/nfs_nfsdserv.c (revision dd41de95a84d979615a2ef11df6850622bf6184e)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1989, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Rick Macklem at The University of Guelph.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  */
35 
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38 
39 #include "opt_inet.h"
40 #include "opt_inet6.h"
41 /*
42  * nfs version 2, 3 and 4 server calls to vnode ops
43  * - these routines generally have 3 phases
44  *   1 - break down and validate rpc request in mbuf list
45  *   2 - do the vnode ops for the request, usually by calling a nfsvno_XXX()
46  *       function in nfsd_port.c
47  *   3 - build the rpc reply in an mbuf list
48  * For nfsv4, these functions are called for each Op within the Compound RPC.
49  */
50 
51 #include <fs/nfs/nfsport.h>
52 #include <sys/extattr.h>
53 #include <sys/filio.h>
54 
55 /* Global vars */
56 extern u_int32_t newnfs_false, newnfs_true;
57 extern enum vtype nv34tov_type[8];
58 extern struct timeval nfsboottime;
59 extern int nfsrv_enable_crossmntpt;
60 extern int nfsrv_statehashsize;
61 extern int nfsrv_layouthashsize;
62 extern time_t nfsdev_time;
63 extern volatile int nfsrv_devidcnt;
64 extern int nfsd_debuglevel;
65 extern u_long sb_max_adj;
66 extern int nfsrv_pnfsatime;
67 extern int nfsrv_maxpnfsmirror;
68 extern int nfs_maxcopyrange;
69 
70 static int	nfs_async = 0;
71 SYSCTL_DECL(_vfs_nfsd);
72 SYSCTL_INT(_vfs_nfsd, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0,
73     "Tell client that writes were synced even though they were not");
74 extern int	nfsrv_doflexfile;
75 SYSCTL_INT(_vfs_nfsd, OID_AUTO, default_flexfile, CTLFLAG_RW,
76     &nfsrv_doflexfile, 0, "Make Flex File Layout the default for pNFS");
77 static int	nfsrv_linux42server = 1;
78 SYSCTL_INT(_vfs_nfsd, OID_AUTO, linux42server, CTLFLAG_RW,
79     &nfsrv_linux42server, 0,
80     "Enable Linux style NFSv4.2 server (non-RFC compliant)");
81 static bool	nfsrv_openaccess = true;
82 SYSCTL_BOOL(_vfs_nfsd, OID_AUTO, v4openaccess, CTLFLAG_RW,
83     &nfsrv_openaccess, 0,
84     "Enable Linux style NFSv4 Open access check");
85 
86 /*
87  * This list defines the GSS mechanisms supported.
88  * (Don't ask me how you get these strings from the RFC stuff like
89  *  iso(1), org(3)... but someone did it, so I don't need to know.)
90  */
91 static struct nfsgss_mechlist nfsgss_mechlist[] = {
92 	{ 9, "\052\206\110\206\367\022\001\002\002", 11 },
93 	{ 0, "", 0 },
94 };
95 
96 /* local functions */
97 static void nfsrvd_symlinksub(struct nfsrv_descript *nd, struct nameidata *ndp,
98     struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp,
99     vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp,
100     int *diraft_retp, nfsattrbit_t *attrbitp,
101     NFSACL_T *aclp, NFSPROC_T *p, struct nfsexstuff *exp, char *pathcp,
102     int pathlen);
103 static void nfsrvd_mkdirsub(struct nfsrv_descript *nd, struct nameidata *ndp,
104     struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp,
105     vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp,
106     int *diraft_retp, nfsattrbit_t *attrbitp, NFSACL_T *aclp,
107     NFSPROC_T *p, struct nfsexstuff *exp);
108 
109 /*
110  * nfs access service (not a part of NFS V2)
111  */
112 int
113 nfsrvd_access(struct nfsrv_descript *nd, __unused int isdgram,
114     vnode_t vp, struct nfsexstuff *exp)
115 {
116 	u_int32_t *tl;
117 	int getret, error = 0;
118 	struct nfsvattr nva;
119 	u_int32_t testmode, nfsmode, supported = 0;
120 	accmode_t deletebit;
121 	struct thread *p = curthread;
122 
123 	if (nd->nd_repstat) {
124 		nfsrv_postopattr(nd, 1, &nva);
125 		goto out;
126 	}
127 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
128 	nfsmode = fxdr_unsigned(u_int32_t, *tl);
129 	if ((nd->nd_flag & ND_NFSV4) &&
130 	    (nfsmode & ~(NFSACCESS_READ | NFSACCESS_LOOKUP |
131 	     NFSACCESS_MODIFY | NFSACCESS_EXTEND | NFSACCESS_DELETE |
132 	     NFSACCESS_EXECUTE | NFSACCESS_XAREAD | NFSACCESS_XAWRITE |
133 	     NFSACCESS_XALIST))) {
134 		nd->nd_repstat = NFSERR_INVAL;
135 		vput(vp);
136 		goto out;
137 	}
138 	if (nfsmode & NFSACCESS_READ) {
139 		supported |= NFSACCESS_READ;
140 		if (nfsvno_accchk(vp, VREAD, nd->nd_cred, exp, p,
141 		    NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported))
142 			nfsmode &= ~NFSACCESS_READ;
143 	}
144 	if (nfsmode & NFSACCESS_MODIFY) {
145 		supported |= NFSACCESS_MODIFY;
146 		if (nfsvno_accchk(vp, VWRITE, nd->nd_cred, exp, p,
147 		    NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported))
148 			nfsmode &= ~NFSACCESS_MODIFY;
149 	}
150 	if (nfsmode & NFSACCESS_EXTEND) {
151 		supported |= NFSACCESS_EXTEND;
152 		if (nfsvno_accchk(vp, VWRITE | VAPPEND, nd->nd_cred, exp, p,
153 		    NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported))
154 			nfsmode &= ~NFSACCESS_EXTEND;
155 	}
156 	if (nfsmode & NFSACCESS_XAREAD) {
157 		supported |= NFSACCESS_XAREAD;
158 		if (nfsvno_accchk(vp, VREAD, nd->nd_cred, exp, p,
159 		    NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported))
160 			nfsmode &= ~NFSACCESS_XAREAD;
161 	}
162 	if (nfsmode & NFSACCESS_XAWRITE) {
163 		supported |= NFSACCESS_XAWRITE;
164 		if (nfsvno_accchk(vp, VWRITE, nd->nd_cred, exp, p,
165 		    NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported))
166 			nfsmode &= ~NFSACCESS_XAWRITE;
167 	}
168 	if (nfsmode & NFSACCESS_XALIST) {
169 		supported |= NFSACCESS_XALIST;
170 		if (nfsvno_accchk(vp, VREAD, nd->nd_cred, exp, p,
171 		    NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported))
172 			nfsmode &= ~NFSACCESS_XALIST;
173 	}
174 	if (nfsmode & NFSACCESS_DELETE) {
175 		supported |= NFSACCESS_DELETE;
176 		if (vp->v_type == VDIR)
177 			deletebit = VDELETE_CHILD;
178 		else
179 			deletebit = VDELETE;
180 		if (nfsvno_accchk(vp, deletebit, nd->nd_cred, exp, p,
181 		    NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported))
182 			nfsmode &= ~NFSACCESS_DELETE;
183 	}
184 	if (vnode_vtype(vp) == VDIR)
185 		testmode = NFSACCESS_LOOKUP;
186 	else
187 		testmode = NFSACCESS_EXECUTE;
188 	if (nfsmode & testmode) {
189 		supported |= (nfsmode & testmode);
190 		if (nfsvno_accchk(vp, VEXEC, nd->nd_cred, exp, p,
191 		    NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported))
192 			nfsmode &= ~testmode;
193 	}
194 	nfsmode &= supported;
195 	if (nd->nd_flag & ND_NFSV3) {
196 		getret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
197 		nfsrv_postopattr(nd, getret, &nva);
198 	}
199 	vput(vp);
200 	if (nd->nd_flag & ND_NFSV4) {
201 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
202 		*tl++ = txdr_unsigned(supported);
203 	} else
204 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
205 	*tl = txdr_unsigned(nfsmode);
206 
207 out:
208 	NFSEXITCODE2(0, nd);
209 	return (0);
210 nfsmout:
211 	vput(vp);
212 	NFSEXITCODE2(error, nd);
213 	return (error);
214 }
215 
216 /*
217  * nfs getattr service
218  */
219 int
220 nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram,
221     vnode_t vp, __unused struct nfsexstuff *exp)
222 {
223 	struct nfsvattr nva;
224 	fhandle_t fh;
225 	int at_root = 0, error = 0, supports_nfsv4acls;
226 	struct nfsreferral *refp;
227 	nfsattrbit_t attrbits, tmpbits;
228 	struct mount *mp;
229 	struct vnode *tvp = NULL;
230 	struct vattr va;
231 	uint64_t mounted_on_fileno = 0;
232 	accmode_t accmode;
233 	struct thread *p = curthread;
234 
235 	if (nd->nd_repstat)
236 		goto out;
237 	if (nd->nd_flag & ND_NFSV4) {
238 		error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
239 		if (error) {
240 			vput(vp);
241 			goto out;
242 		}
243 
244 		/*
245 		 * Check for a referral.
246 		 */
247 		refp = nfsv4root_getreferral(vp, NULL, 0);
248 		if (refp != NULL) {
249 			(void) nfsrv_putreferralattr(nd, &attrbits, refp, 1,
250 			    &nd->nd_repstat);
251 			vput(vp);
252 			goto out;
253 		}
254 		if (nd->nd_repstat == 0) {
255 			accmode = 0;
256 			NFSSET_ATTRBIT(&tmpbits, &attrbits);
257 
258 			/*
259 			 * GETATTR with write-only attr time_access_set and time_modify_set
260 			 * should return NFS4ERR_INVAL.
261 			 */
262 			if (NFSISSET_ATTRBIT(&tmpbits, NFSATTRBIT_TIMEACCESSSET) ||
263 					NFSISSET_ATTRBIT(&tmpbits, NFSATTRBIT_TIMEMODIFYSET)){
264 				error = NFSERR_INVAL;
265 				vput(vp);
266 				goto out;
267 			}
268 			if (NFSISSET_ATTRBIT(&tmpbits, NFSATTRBIT_ACL)) {
269 				NFSCLRBIT_ATTRBIT(&tmpbits, NFSATTRBIT_ACL);
270 				accmode |= VREAD_ACL;
271 			}
272 			if (NFSNONZERO_ATTRBIT(&tmpbits))
273 				accmode |= VREAD_ATTRIBUTES;
274 			if (accmode != 0)
275 				nd->nd_repstat = nfsvno_accchk(vp, accmode,
276 				    nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE,
277 				    NFSACCCHK_VPISLOCKED, NULL);
278 		}
279 	}
280 	if (!nd->nd_repstat)
281 		nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, &attrbits);
282 	if (!nd->nd_repstat) {
283 		if (nd->nd_flag & ND_NFSV4) {
284 			if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_FILEHANDLE))
285 				nd->nd_repstat = nfsvno_getfh(vp, &fh, p);
286 			if (!nd->nd_repstat)
287 				nd->nd_repstat = nfsrv_checkgetattr(nd, vp,
288 				    &nva, &attrbits, p);
289 			if (nd->nd_repstat == 0) {
290 				supports_nfsv4acls = nfs_supportsnfsv4acls(vp);
291 				mp = vp->v_mount;
292 				if (nfsrv_enable_crossmntpt != 0 &&
293 				    vp->v_type == VDIR &&
294 				    (vp->v_vflag & VV_ROOT) != 0 &&
295 				    vp != rootvnode) {
296 					tvp = mp->mnt_vnodecovered;
297 					VREF(tvp);
298 					at_root = 1;
299 				} else
300 					at_root = 0;
301 				vfs_ref(mp);
302 				NFSVOPUNLOCK(vp);
303 				if (at_root != 0) {
304 					if ((nd->nd_repstat =
305 					     NFSVOPLOCK(tvp, LK_SHARED)) == 0) {
306 						nd->nd_repstat = VOP_GETATTR(
307 						    tvp, &va, nd->nd_cred);
308 						vput(tvp);
309 					} else
310 						vrele(tvp);
311 					if (nd->nd_repstat == 0)
312 						mounted_on_fileno = (uint64_t)
313 						    va.va_fileid;
314 					else
315 						at_root = 0;
316 				}
317 				if (nd->nd_repstat == 0)
318 					nd->nd_repstat = vfs_busy(mp, 0);
319 				vfs_rel(mp);
320 				if (nd->nd_repstat == 0) {
321 					(void)nfsvno_fillattr(nd, mp, vp, &nva,
322 					    &fh, 0, &attrbits, nd->nd_cred, p,
323 					    isdgram, 1, supports_nfsv4acls,
324 					    at_root, mounted_on_fileno);
325 					vfs_unbusy(mp);
326 				}
327 				vrele(vp);
328 			} else
329 				vput(vp);
330 		} else {
331 			nfsrv_fillattr(nd, &nva);
332 			vput(vp);
333 		}
334 	} else {
335 		vput(vp);
336 	}
337 
338 out:
339 	NFSEXITCODE2(error, nd);
340 	return (error);
341 }
342 
343 /*
344  * nfs setattr service
345  */
346 int
347 nfsrvd_setattr(struct nfsrv_descript *nd, __unused int isdgram,
348     vnode_t vp, struct nfsexstuff *exp)
349 {
350 	struct nfsvattr nva, nva2;
351 	u_int32_t *tl;
352 	int preat_ret = 1, postat_ret = 1, gcheck = 0, error = 0;
353 	int gotproxystateid;
354 	struct timespec guard = { 0, 0 };
355 	nfsattrbit_t attrbits, retbits;
356 	nfsv4stateid_t stateid;
357 	NFSACL_T *aclp = NULL;
358 	struct thread *p = curthread;
359 
360 	if (nd->nd_repstat) {
361 		nfsrv_wcc(nd, preat_ret, &nva2, postat_ret, &nva);
362 		goto out;
363 	}
364 #ifdef NFS4_ACL_EXTATTR_NAME
365 	aclp = acl_alloc(M_WAITOK);
366 	aclp->acl_cnt = 0;
367 #endif
368 	gotproxystateid = 0;
369 	NFSVNO_ATTRINIT(&nva);
370 	if (nd->nd_flag & ND_NFSV4) {
371 		NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
372 		stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
373 		stateid.other[0] = *tl++;
374 		stateid.other[1] = *tl++;
375 		stateid.other[2] = *tl;
376 		if (stateid.other[0] == 0x55555555 &&
377 		    stateid.other[1] == 0x55555555 &&
378 		    stateid.other[2] == 0x55555555 &&
379 		    stateid.seqid == 0xffffffff)
380 			gotproxystateid = 1;
381 	}
382 	error = nfsrv_sattr(nd, vp, &nva, &attrbits, aclp, p);
383 	if (error)
384 		goto nfsmout;
385 
386 	/* For NFSv4, only va_uid is used from nva2. */
387 	NFSZERO_ATTRBIT(&retbits);
388 	NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_OWNER);
389 	preat_ret = nfsvno_getattr(vp, &nva2, nd, p, 1, &retbits);
390 	if (!nd->nd_repstat)
391 		nd->nd_repstat = preat_ret;
392 
393 	NFSZERO_ATTRBIT(&retbits);
394 	if (nd->nd_flag & ND_NFSV3) {
395 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
396 		gcheck = fxdr_unsigned(int, *tl);
397 		if (gcheck) {
398 			NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
399 			fxdr_nfsv3time(tl, &guard);
400 		}
401 		if (!nd->nd_repstat && gcheck &&
402 		    (nva2.na_ctime.tv_sec != guard.tv_sec ||
403 		     nva2.na_ctime.tv_nsec != guard.tv_nsec))
404 			nd->nd_repstat = NFSERR_NOT_SYNC;
405 		if (nd->nd_repstat) {
406 			vput(vp);
407 #ifdef NFS4_ACL_EXTATTR_NAME
408 			acl_free(aclp);
409 #endif
410 			nfsrv_wcc(nd, preat_ret, &nva2, postat_ret, &nva);
411 			goto out;
412 		}
413 	} else if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV4))
414 		nd->nd_repstat = nfsrv_checkuidgid(nd, &nva);
415 
416 	/*
417 	 * Now that we have all the fields, lets do it.
418 	 * If the size is being changed write access is required, otherwise
419 	 * just check for a read only file system.
420 	 */
421 	if (!nd->nd_repstat) {
422 		if (NFSVNO_NOTSETSIZE(&nva)) {
423 			if (NFSVNO_EXRDONLY(exp) ||
424 			    (vfs_flags(vp->v_mount) & MNT_RDONLY))
425 				nd->nd_repstat = EROFS;
426 		} else {
427 			if (vnode_vtype(vp) != VREG)
428 				nd->nd_repstat = EINVAL;
429 			else if (nva2.na_uid != nd->nd_cred->cr_uid ||
430 			    NFSVNO_EXSTRICTACCESS(exp))
431 				nd->nd_repstat = nfsvno_accchk(vp,
432 				    VWRITE, nd->nd_cred, exp, p,
433 				    NFSACCCHK_NOOVERRIDE,
434 				    NFSACCCHK_VPISLOCKED, NULL);
435 		}
436 	}
437 	/*
438 	 * Proxy operations from the MDS are allowed via the all 0s special
439 	 * stateid.
440 	 */
441 	if (nd->nd_repstat == 0 && (nd->nd_flag & ND_NFSV4) != 0 &&
442 	    gotproxystateid == 0)
443 		nd->nd_repstat = nfsrv_checksetattr(vp, nd, &stateid,
444 		    &nva, &attrbits, exp, p);
445 
446 	if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV4)) {
447 	    /*
448 	     * For V4, try setting the attrbutes in sets, so that the
449 	     * reply bitmap will be correct for an error case.
450 	     */
451 	    if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_OWNER) ||
452 		NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_OWNERGROUP)) {
453 		NFSVNO_ATTRINIT(&nva2);
454 		NFSVNO_SETATTRVAL(&nva2, uid, nva.na_uid);
455 		NFSVNO_SETATTRVAL(&nva2, gid, nva.na_gid);
456 		nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p,
457 		    exp);
458 		if (!nd->nd_repstat) {
459 		    if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_OWNER))
460 			NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_OWNER);
461 		    if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_OWNERGROUP))
462 			NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_OWNERGROUP);
463 		}
464 	    }
465 	    if (!nd->nd_repstat &&
466 		NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_SIZE)) {
467 		NFSVNO_ATTRINIT(&nva2);
468 		NFSVNO_SETATTRVAL(&nva2, size, nva.na_size);
469 		nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p,
470 		    exp);
471 		if (!nd->nd_repstat)
472 		    NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_SIZE);
473 	    }
474 	    if (!nd->nd_repstat &&
475 		(NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESSSET) ||
476 		 NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFYSET))) {
477 		NFSVNO_ATTRINIT(&nva2);
478 		NFSVNO_SETATTRVAL(&nva2, atime, nva.na_atime);
479 		NFSVNO_SETATTRVAL(&nva2, mtime, nva.na_mtime);
480 		if (nva.na_vaflags & VA_UTIMES_NULL) {
481 			nva2.na_vaflags |= VA_UTIMES_NULL;
482 			NFSVNO_SETACTIVE(&nva2, vaflags);
483 		}
484 		nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p,
485 		    exp);
486 		if (!nd->nd_repstat) {
487 		    if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESSSET))
488 			NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_TIMEACCESSSET);
489 		    if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFYSET))
490 			NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_TIMEMODIFYSET);
491 		}
492 	    }
493 	    if (!nd->nd_repstat &&
494 		NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMECREATE)) {
495 		NFSVNO_ATTRINIT(&nva2);
496 		NFSVNO_SETATTRVAL(&nva2, btime, nva.na_btime);
497 		nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p,
498 		    exp);
499 		if (!nd->nd_repstat)
500 		    NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_TIMECREATE);
501 	    }
502 	    if (!nd->nd_repstat &&
503 		(NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODE) ||
504 		 NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODESETMASKED))) {
505 		NFSVNO_ATTRINIT(&nva2);
506 		NFSVNO_SETATTRVAL(&nva2, mode, nva.na_mode);
507 		nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p,
508 		    exp);
509 		if (!nd->nd_repstat) {
510 		    if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODE))
511 			NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_MODE);
512 		    if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODESETMASKED))
513 			NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_MODESETMASKED);
514 		}
515 	    }
516 
517 #ifdef NFS4_ACL_EXTATTR_NAME
518 	    if (!nd->nd_repstat && aclp->acl_cnt > 0 &&
519 		NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_ACL)) {
520 		nd->nd_repstat = nfsrv_setacl(vp, aclp, nd->nd_cred, p);
521 		if (!nd->nd_repstat)
522 		    NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_ACL);
523 	    }
524 #endif
525 	} else if (!nd->nd_repstat) {
526 		nd->nd_repstat = nfsvno_setattr(vp, &nva, nd->nd_cred, p,
527 		    exp);
528 	}
529 	if (nd->nd_flag & (ND_NFSV2 | ND_NFSV3)) {
530 		postat_ret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
531 		if (!nd->nd_repstat)
532 			nd->nd_repstat = postat_ret;
533 	}
534 	vput(vp);
535 #ifdef NFS4_ACL_EXTATTR_NAME
536 	acl_free(aclp);
537 #endif
538 	if (nd->nd_flag & ND_NFSV3)
539 		nfsrv_wcc(nd, preat_ret, &nva2, postat_ret, &nva);
540 	else if (nd->nd_flag & ND_NFSV4)
541 		(void) nfsrv_putattrbit(nd, &retbits);
542 	else if (!nd->nd_repstat)
543 		nfsrv_fillattr(nd, &nva);
544 
545 out:
546 	NFSEXITCODE2(0, nd);
547 	return (0);
548 nfsmout:
549 	vput(vp);
550 #ifdef NFS4_ACL_EXTATTR_NAME
551 	acl_free(aclp);
552 #endif
553 	if (nd->nd_flag & ND_NFSV4) {
554 		/*
555 		 * For all nd_repstat, the V4 reply includes a bitmap,
556 		 * even NFSERR_BADXDR, which is what this will end up
557 		 * returning.
558 		 */
559 		(void) nfsrv_putattrbit(nd, &retbits);
560 	}
561 	NFSEXITCODE2(error, nd);
562 	return (error);
563 }
564 
565 /*
566  * nfs lookup rpc
567  * (Also performs lookup parent for v4)
568  */
569 int
570 nfsrvd_lookup(struct nfsrv_descript *nd, __unused int isdgram,
571     vnode_t dp, vnode_t *vpp, fhandle_t *fhp, struct nfsexstuff *exp)
572 {
573 	struct nameidata named;
574 	vnode_t vp, dirp = NULL;
575 	int error = 0, dattr_ret = 1;
576 	struct nfsvattr nva, dattr;
577 	char *bufp;
578 	u_long *hashp;
579 	struct thread *p = curthread;
580 
581 	if (nd->nd_repstat) {
582 		nfsrv_postopattr(nd, dattr_ret, &dattr);
583 		goto out;
584 	}
585 
586 	/*
587 	 * For some reason, if dp is a symlink, the error
588 	 * returned is supposed to be NFSERR_SYMLINK and not NFSERR_NOTDIR.
589 	 */
590 	if (dp->v_type == VLNK && (nd->nd_flag & ND_NFSV4)) {
591 		nd->nd_repstat = NFSERR_SYMLINK;
592 		vrele(dp);
593 		goto out;
594 	}
595 
596 	NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP,
597 	    LOCKLEAF | SAVESTART);
598 	nfsvno_setpathbuf(&named, &bufp, &hashp);
599 	error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
600 	if (error) {
601 		vrele(dp);
602 		nfsvno_relpathbuf(&named);
603 		goto out;
604 	}
605 	if (!nd->nd_repstat) {
606 		nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp);
607 	} else {
608 		vrele(dp);
609 		nfsvno_relpathbuf(&named);
610 	}
611 	if (nd->nd_repstat) {
612 		if (dirp) {
613 			if (nd->nd_flag & ND_NFSV3)
614 				dattr_ret = nfsvno_getattr(dirp, &dattr, nd, p,
615 				    0, NULL);
616 			vrele(dirp);
617 		}
618 		if (nd->nd_flag & ND_NFSV3)
619 			nfsrv_postopattr(nd, dattr_ret, &dattr);
620 		goto out;
621 	}
622 	if (named.ni_startdir)
623 		vrele(named.ni_startdir);
624 	nfsvno_relpathbuf(&named);
625 	vp = named.ni_vp;
626 	if ((nd->nd_flag & ND_NFSV4) != 0 && !NFSVNO_EXPORTED(exp) &&
627 	    vp->v_type != VDIR && vp->v_type != VLNK)
628 		/*
629 		 * Only allow lookup of VDIR and VLNK for traversal of
630 		 * non-exported volumes during NFSv4 mounting.
631 		 */
632 		nd->nd_repstat = ENOENT;
633 	if (nd->nd_repstat == 0)
634 		nd->nd_repstat = nfsvno_getfh(vp, fhp, p);
635 	if (!(nd->nd_flag & ND_NFSV4) && !nd->nd_repstat)
636 		nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
637 	if (vpp != NULL && nd->nd_repstat == 0)
638 		*vpp = vp;
639 	else
640 		vput(vp);
641 	if (dirp) {
642 		if (nd->nd_flag & ND_NFSV3)
643 			dattr_ret = nfsvno_getattr(dirp, &dattr, nd, p, 0,
644 			    NULL);
645 		vrele(dirp);
646 	}
647 	if (nd->nd_repstat) {
648 		if (nd->nd_flag & ND_NFSV3)
649 			nfsrv_postopattr(nd, dattr_ret, &dattr);
650 		goto out;
651 	}
652 	if (nd->nd_flag & ND_NFSV2) {
653 		(void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 0);
654 		nfsrv_fillattr(nd, &nva);
655 	} else if (nd->nd_flag & ND_NFSV3) {
656 		(void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 0);
657 		nfsrv_postopattr(nd, 0, &nva);
658 		nfsrv_postopattr(nd, dattr_ret, &dattr);
659 	}
660 
661 out:
662 	NFSEXITCODE2(error, nd);
663 	return (error);
664 }
665 
666 /*
667  * nfs readlink service
668  */
669 int
670 nfsrvd_readlink(struct nfsrv_descript *nd, __unused int isdgram,
671     vnode_t vp, __unused struct nfsexstuff *exp)
672 {
673 	u_int32_t *tl;
674 	struct mbuf *mp = NULL, *mpend = NULL;
675 	int getret = 1, len;
676 	struct nfsvattr nva;
677 	struct thread *p = curthread;
678 	uint16_t off;
679 
680 	if (nd->nd_repstat) {
681 		nfsrv_postopattr(nd, getret, &nva);
682 		goto out;
683 	}
684 	if (vnode_vtype(vp) != VLNK) {
685 		if (nd->nd_flag & ND_NFSV2)
686 			nd->nd_repstat = ENXIO;
687 		else
688 			nd->nd_repstat = EINVAL;
689 	}
690 	if (nd->nd_repstat == 0) {
691 		if ((nd->nd_flag & ND_EXTPG) != 0)
692 			nd->nd_repstat = nfsvno_readlink(vp, nd->nd_cred,
693 			    nd->nd_maxextsiz, p, &mp, &mpend, &len);
694 		else
695 			nd->nd_repstat = nfsvno_readlink(vp, nd->nd_cred,
696 			    0, p, &mp, &mpend, &len);
697 	}
698 	if (nd->nd_flag & ND_NFSV3)
699 		getret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
700 	vput(vp);
701 	if (nd->nd_flag & ND_NFSV3)
702 		nfsrv_postopattr(nd, getret, &nva);
703 	if (nd->nd_repstat)
704 		goto out;
705 	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
706 	*tl = txdr_unsigned(len);
707 	if (mp != NULL) {
708 		nd->nd_mb->m_next = mp;
709 		nd->nd_mb = mpend;
710 		if ((mpend->m_flags & M_EXTPG) != 0) {
711 			nd->nd_bextpg = mpend->m_epg_npgs - 1;
712 			nd->nd_bpos = (char *)(void *)
713 			    PHYS_TO_DMAP(mpend->m_epg_pa[nd->nd_bextpg]);
714 			off = (nd->nd_bextpg == 0) ? mpend->m_epg_1st_off : 0;
715 			nd->nd_bpos += off + mpend->m_epg_last_len;
716 			nd->nd_bextpgsiz = PAGE_SIZE - mpend->m_epg_last_len -
717 			    off;
718 		} else
719 			nd->nd_bpos = mtod(mpend, char *) + mpend->m_len;
720 	}
721 
722 out:
723 	NFSEXITCODE2(0, nd);
724 	return (0);
725 }
726 
727 /*
728  * nfs read service
729  */
730 int
731 nfsrvd_read(struct nfsrv_descript *nd, __unused int isdgram,
732     vnode_t vp, struct nfsexstuff *exp)
733 {
734 	u_int32_t *tl;
735 	int error = 0, cnt, getret = 1, gotproxystateid, reqlen, eof = 0;
736 	struct mbuf *m2, *m3;
737 	struct nfsvattr nva;
738 	off_t off = 0x0;
739 	struct nfsstate st, *stp = &st;
740 	struct nfslock lo, *lop = &lo;
741 	nfsv4stateid_t stateid;
742 	nfsquad_t clientid;
743 	struct thread *p = curthread;
744 	uint16_t poff;
745 
746 	if (nd->nd_repstat) {
747 		nfsrv_postopattr(nd, getret, &nva);
748 		goto out;
749 	}
750 	if (nd->nd_flag & ND_NFSV2) {
751 		NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
752 		off = (off_t)fxdr_unsigned(u_int32_t, *tl++);
753 		reqlen = fxdr_unsigned(int, *tl);
754 	} else if (nd->nd_flag & ND_NFSV3) {
755 		NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
756 		off = fxdr_hyper(tl);
757 		tl += 2;
758 		reqlen = fxdr_unsigned(int, *tl);
759 	} else {
760 		NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + 3*NFSX_UNSIGNED);
761 		reqlen = fxdr_unsigned(int, *(tl + 6));
762 	}
763 	if (reqlen > NFS_SRVMAXDATA(nd)) {
764 		reqlen = NFS_SRVMAXDATA(nd);
765 	} else if (reqlen < 0) {
766 		error = EBADRPC;
767 		goto nfsmout;
768 	}
769 	gotproxystateid = 0;
770 	if (nd->nd_flag & ND_NFSV4) {
771 		stp->ls_flags = (NFSLCK_CHECK | NFSLCK_READACCESS);
772 		lop->lo_flags = NFSLCK_READ;
773 		stp->ls_ownerlen = 0;
774 		stp->ls_op = NULL;
775 		stp->ls_uid = nd->nd_cred->cr_uid;
776 		stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
777 		clientid.lval[0] = stp->ls_stateid.other[0] = *tl++;
778 		clientid.lval[1] = stp->ls_stateid.other[1] = *tl++;
779 		if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
780 			if ((nd->nd_flag & ND_NFSV41) != 0)
781 				clientid.qval = nd->nd_clientid.qval;
782 			else if (nd->nd_clientid.qval != clientid.qval)
783 				printf("EEK1 multiple clids\n");
784 		} else {
785 			if ((nd->nd_flag & ND_NFSV41) != 0)
786 				printf("EEK! no clientid from session\n");
787 			nd->nd_flag |= ND_IMPLIEDCLID;
788 			nd->nd_clientid.qval = clientid.qval;
789 		}
790 		stp->ls_stateid.other[2] = *tl++;
791 		/*
792 		 * Don't allow the client to use a special stateid for a DS op.
793 		 */
794 		if ((nd->nd_flag & ND_DSSERVER) != 0 &&
795 		    ((stp->ls_stateid.other[0] == 0x0 &&
796 		    stp->ls_stateid.other[1] == 0x0 &&
797 		    stp->ls_stateid.other[2] == 0x0) ||
798 		    (stp->ls_stateid.other[0] == 0xffffffff &&
799 		    stp->ls_stateid.other[1] == 0xffffffff &&
800 		    stp->ls_stateid.other[2] == 0xffffffff) ||
801 		    stp->ls_stateid.seqid != 0))
802 			nd->nd_repstat = NFSERR_BADSTATEID;
803 		/* However, allow the proxy stateid. */
804 		if (stp->ls_stateid.seqid == 0xffffffff &&
805 		    stp->ls_stateid.other[0] == 0x55555555 &&
806 		    stp->ls_stateid.other[1] == 0x55555555 &&
807 		    stp->ls_stateid.other[2] == 0x55555555)
808 			gotproxystateid = 1;
809 		off = fxdr_hyper(tl);
810 		lop->lo_first = off;
811 		tl += 2;
812 		lop->lo_end = off + reqlen;
813 		/*
814 		 * Paranoia, just in case it wraps around.
815 		 */
816 		if (lop->lo_end < off)
817 			lop->lo_end = NFS64BITSSET;
818 	}
819 	if (vnode_vtype(vp) != VREG) {
820 		if (nd->nd_flag & ND_NFSV3)
821 			nd->nd_repstat = EINVAL;
822 		else
823 			nd->nd_repstat = (vnode_vtype(vp) == VDIR) ? EISDIR :
824 			    EINVAL;
825 	}
826 	getret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
827 	if (!nd->nd_repstat)
828 		nd->nd_repstat = getret;
829 	if (!nd->nd_repstat &&
830 	    (nva.na_uid != nd->nd_cred->cr_uid ||
831 	     NFSVNO_EXSTRICTACCESS(exp))) {
832 		nd->nd_repstat = nfsvno_accchk(vp, VREAD,
833 		    nd->nd_cred, exp, p,
834 		    NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, NULL);
835 		if (nd->nd_repstat)
836 			nd->nd_repstat = nfsvno_accchk(vp, VEXEC,
837 			    nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER,
838 			    NFSACCCHK_VPISLOCKED, NULL);
839 	}
840 	/*
841 	 * DS reads are marked by ND_DSSERVER or use the proxy special
842 	 * stateid.
843 	 */
844 	if (nd->nd_repstat == 0 && (nd->nd_flag & (ND_NFSV4 | ND_DSSERVER)) ==
845 	    ND_NFSV4 && gotproxystateid == 0)
846 		nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid,
847 		    &stateid, exp, nd, p);
848 	if (nd->nd_repstat) {
849 		vput(vp);
850 		if (nd->nd_flag & ND_NFSV3)
851 			nfsrv_postopattr(nd, getret, &nva);
852 		goto out;
853 	}
854 	if (off >= nva.na_size) {
855 		cnt = 0;
856 		eof = 1;
857 	} else if (reqlen == 0)
858 		cnt = 0;
859 	else if ((off + reqlen) >= nva.na_size) {
860 		cnt = nva.na_size - off;
861 		eof = 1;
862 	} else
863 		cnt = reqlen;
864 	m3 = NULL;
865 	if (cnt > 0) {
866 		/*
867 		 * If cnt > MCLBYTES and the reply will not be saved, use
868 		 * ext_pgs mbufs for TLS.
869 		 * For NFSv4.0, we do not know for sure if the reply will
870 		 * be saved, so do not use ext_pgs mbufs for NFSv4.0.
871 		 * Always use ext_pgs mbufs if ND_EXTPG is set.
872 		 */
873 		if ((nd->nd_flag & ND_EXTPG) != 0 || (cnt > MCLBYTES &&
874 		    (nd->nd_flag & (ND_TLS | ND_SAVEREPLY)) == ND_TLS &&
875 		    (nd->nd_flag & (ND_NFSV4 | ND_NFSV41)) != ND_NFSV4))
876 			nd->nd_repstat = nfsvno_read(vp, off, cnt, nd->nd_cred,
877 			    nd->nd_maxextsiz, p, &m3, &m2);
878 		else
879 			nd->nd_repstat = nfsvno_read(vp, off, cnt, nd->nd_cred,
880 			    0, p, &m3, &m2);
881 		if (!(nd->nd_flag & ND_NFSV4)) {
882 			getret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
883 			if (!nd->nd_repstat)
884 				nd->nd_repstat = getret;
885 		}
886 		if (nd->nd_repstat) {
887 			vput(vp);
888 			if (m3)
889 				m_freem(m3);
890 			if (nd->nd_flag & ND_NFSV3)
891 				nfsrv_postopattr(nd, getret, &nva);
892 			goto out;
893 		}
894 	}
895 	vput(vp);
896 	if (nd->nd_flag & ND_NFSV2) {
897 		nfsrv_fillattr(nd, &nva);
898 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
899 	} else {
900 		if (nd->nd_flag & ND_NFSV3) {
901 			nfsrv_postopattr(nd, getret, &nva);
902 			NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
903 			*tl++ = txdr_unsigned(cnt);
904 		} else
905 			NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
906 		if (eof)
907 			*tl++ = newnfs_true;
908 		else
909 			*tl++ = newnfs_false;
910 	}
911 	*tl = txdr_unsigned(cnt);
912 	if (m3) {
913 		nd->nd_mb->m_next = m3;
914 		nd->nd_mb = m2;
915 		if ((m2->m_flags & M_EXTPG) != 0) {
916 			nd->nd_flag |= ND_EXTPG;
917 			nd->nd_bextpg = m2->m_epg_npgs - 1;
918 			nd->nd_bpos = (char *)(void *)
919 			    PHYS_TO_DMAP(m2->m_epg_pa[nd->nd_bextpg]);
920 			poff = (nd->nd_bextpg == 0) ? m2->m_epg_1st_off : 0;
921 			nd->nd_bpos += poff + m2->m_epg_last_len;
922 			nd->nd_bextpgsiz = PAGE_SIZE - m2->m_epg_last_len -
923 			    poff;
924 		} else
925 			nd->nd_bpos = mtod(m2, char *) + m2->m_len;
926 	}
927 
928 out:
929 	NFSEXITCODE2(0, nd);
930 	return (0);
931 nfsmout:
932 	vput(vp);
933 	NFSEXITCODE2(error, nd);
934 	return (error);
935 }
936 
937 /*
938  * nfs write service
939  */
940 int
941 nfsrvd_write(struct nfsrv_descript *nd, __unused int isdgram,
942     vnode_t vp, struct nfsexstuff *exp)
943 {
944 	u_int32_t *tl;
945 	struct nfsvattr nva, forat;
946 	int aftat_ret = 1, retlen, len, error = 0, forat_ret = 1;
947 	int gotproxystateid, stable = NFSWRITE_FILESYNC;
948 	off_t off;
949 	struct nfsstate st, *stp = &st;
950 	struct nfslock lo, *lop = &lo;
951 	nfsv4stateid_t stateid;
952 	nfsquad_t clientid;
953 	nfsattrbit_t attrbits;
954 	struct thread *p = curthread;
955 
956 	if (nd->nd_repstat) {
957 		nfsrv_wcc(nd, forat_ret, &forat, aftat_ret, &nva);
958 		goto out;
959 	}
960 	gotproxystateid = 0;
961 	if (nd->nd_flag & ND_NFSV2) {
962 		NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
963 		off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
964 		tl += 2;
965 		retlen = len = fxdr_unsigned(int32_t, *tl);
966 	} else if (nd->nd_flag & ND_NFSV3) {
967 		NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
968 		off = fxdr_hyper(tl);
969 		tl += 3;
970 		stable = fxdr_unsigned(int, *tl++);
971 		retlen = len = fxdr_unsigned(int32_t, *tl);
972 	} else {
973 		NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + 4 * NFSX_UNSIGNED);
974 		stp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS);
975 		lop->lo_flags = NFSLCK_WRITE;
976 		stp->ls_ownerlen = 0;
977 		stp->ls_op = NULL;
978 		stp->ls_uid = nd->nd_cred->cr_uid;
979 		stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
980 		clientid.lval[0] = stp->ls_stateid.other[0] = *tl++;
981 		clientid.lval[1] = stp->ls_stateid.other[1] = *tl++;
982 		if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
983 			if ((nd->nd_flag & ND_NFSV41) != 0)
984 				clientid.qval = nd->nd_clientid.qval;
985 			else if (nd->nd_clientid.qval != clientid.qval)
986 				printf("EEK2 multiple clids\n");
987 		} else {
988 			if ((nd->nd_flag & ND_NFSV41) != 0)
989 				printf("EEK! no clientid from session\n");
990 			nd->nd_flag |= ND_IMPLIEDCLID;
991 			nd->nd_clientid.qval = clientid.qval;
992 		}
993 		stp->ls_stateid.other[2] = *tl++;
994 		/*
995 		 * Don't allow the client to use a special stateid for a DS op.
996 		 */
997 		if ((nd->nd_flag & ND_DSSERVER) != 0 &&
998 		    ((stp->ls_stateid.other[0] == 0x0 &&
999 		    stp->ls_stateid.other[1] == 0x0 &&
1000 		    stp->ls_stateid.other[2] == 0x0) ||
1001 		    (stp->ls_stateid.other[0] == 0xffffffff &&
1002 		    stp->ls_stateid.other[1] == 0xffffffff &&
1003 		    stp->ls_stateid.other[2] == 0xffffffff) ||
1004 		    stp->ls_stateid.seqid != 0))
1005 			nd->nd_repstat = NFSERR_BADSTATEID;
1006 		/* However, allow the proxy stateid. */
1007 		if (stp->ls_stateid.seqid == 0xffffffff &&
1008 		    stp->ls_stateid.other[0] == 0x55555555 &&
1009 		    stp->ls_stateid.other[1] == 0x55555555 &&
1010 		    stp->ls_stateid.other[2] == 0x55555555)
1011 			gotproxystateid = 1;
1012 		off = fxdr_hyper(tl);
1013 		lop->lo_first = off;
1014 		tl += 2;
1015 		stable = fxdr_unsigned(int, *tl++);
1016 		retlen = len = fxdr_unsigned(int32_t, *tl);
1017 		lop->lo_end = off + len;
1018 		/*
1019 		 * Paranoia, just in case it wraps around, which shouldn't
1020 		 * ever happen anyhow.
1021 		 */
1022 		if (lop->lo_end < lop->lo_first)
1023 			lop->lo_end = NFS64BITSSET;
1024 	}
1025 
1026 	if (retlen > NFS_SRVMAXIO || retlen < 0)
1027 		nd->nd_repstat = EIO;
1028 	if (vnode_vtype(vp) != VREG && !nd->nd_repstat) {
1029 		if (nd->nd_flag & ND_NFSV3)
1030 			nd->nd_repstat = EINVAL;
1031 		else
1032 			nd->nd_repstat = (vnode_vtype(vp) == VDIR) ? EISDIR :
1033 			    EINVAL;
1034 	}
1035 	NFSZERO_ATTRBIT(&attrbits);
1036 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNER);
1037 	forat_ret = nfsvno_getattr(vp, &forat, nd, p, 1, &attrbits);
1038 	if (!nd->nd_repstat)
1039 		nd->nd_repstat = forat_ret;
1040 	if (!nd->nd_repstat &&
1041 	    (forat.na_uid != nd->nd_cred->cr_uid ||
1042 	     NFSVNO_EXSTRICTACCESS(exp)))
1043 		nd->nd_repstat = nfsvno_accchk(vp, VWRITE,
1044 		    nd->nd_cred, exp, p,
1045 		    NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, NULL);
1046 	/*
1047 	 * DS reads are marked by ND_DSSERVER or use the proxy special
1048 	 * stateid.
1049 	 */
1050 	if (nd->nd_repstat == 0 && (nd->nd_flag & (ND_NFSV4 | ND_DSSERVER)) ==
1051 	    ND_NFSV4 && gotproxystateid == 0)
1052 		nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid,
1053 		    &stateid, exp, nd, p);
1054 	if (nd->nd_repstat) {
1055 		vput(vp);
1056 		if (nd->nd_flag & ND_NFSV3)
1057 			nfsrv_wcc(nd, forat_ret, &forat, aftat_ret, &nva);
1058 		goto out;
1059 	}
1060 
1061 	/*
1062 	 * For NFS Version 2, it is not obvious what a write of zero length
1063 	 * should do, but I might as well be consistent with Version 3,
1064 	 * which is to return ok so long as there are no permission problems.
1065 	 */
1066 	if (retlen > 0) {
1067 		nd->nd_repstat = nfsvno_write(vp, off, retlen, &stable,
1068 		    nd->nd_md, nd->nd_dpos, nd->nd_cred, p);
1069 		error = nfsm_advance(nd, NFSM_RNDUP(retlen), -1);
1070 		if (error)
1071 			goto nfsmout;
1072 	}
1073 	if (nd->nd_flag & ND_NFSV4)
1074 		aftat_ret = 0;
1075 	else
1076 		aftat_ret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
1077 	vput(vp);
1078 	if (!nd->nd_repstat)
1079 		nd->nd_repstat = aftat_ret;
1080 	if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
1081 		if (nd->nd_flag & ND_NFSV3)
1082 			nfsrv_wcc(nd, forat_ret, &forat, aftat_ret, &nva);
1083 		if (nd->nd_repstat)
1084 			goto out;
1085 		NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1086 		*tl++ = txdr_unsigned(retlen);
1087 		/*
1088 		 * If nfs_async is set, then pretend the write was FILESYNC.
1089 		 * Warning: Doing this violates RFC1813 and runs a risk
1090 		 * of data written by a client being lost when the server
1091 		 * crashes/reboots.
1092 		 */
1093 		if (stable == NFSWRITE_UNSTABLE && nfs_async == 0)
1094 			*tl++ = txdr_unsigned(stable);
1095 		else
1096 			*tl++ = txdr_unsigned(NFSWRITE_FILESYNC);
1097 		/*
1098 		 * Actually, there is no need to txdr these fields,
1099 		 * but it may make the values more human readable,
1100 		 * for debugging purposes.
1101 		 */
1102 		*tl++ = txdr_unsigned(nfsboottime.tv_sec);
1103 		*tl = txdr_unsigned(nfsboottime.tv_usec);
1104 	} else if (!nd->nd_repstat)
1105 		nfsrv_fillattr(nd, &nva);
1106 
1107 out:
1108 	NFSEXITCODE2(0, nd);
1109 	return (0);
1110 nfsmout:
1111 	vput(vp);
1112 	NFSEXITCODE2(error, nd);
1113 	return (error);
1114 }
1115 
1116 /*
1117  * nfs create service (creates regular files for V2 and V3. Spec. files for V2.)
1118  * now does a truncate to 0 length via. setattr if it already exists
1119  * The core creation routine has been extracted out into nfsrv_creatsub(),
1120  * so it can also be used by nfsrv_open() for V4.
1121  */
1122 int
1123 nfsrvd_create(struct nfsrv_descript *nd, __unused int isdgram,
1124     vnode_t dp, struct nfsexstuff *exp)
1125 {
1126 	struct nfsvattr nva, dirfor, diraft;
1127 	struct nfsv2_sattr *sp;
1128 	struct nameidata named;
1129 	u_int32_t *tl;
1130 	int error = 0, tsize, dirfor_ret = 1, diraft_ret = 1;
1131 	int how = NFSCREATE_UNCHECKED, exclusive_flag = 0;
1132 	NFSDEV_T rdev = 0;
1133 	vnode_t vp = NULL, dirp = NULL;
1134 	fhandle_t fh;
1135 	char *bufp;
1136 	u_long *hashp;
1137 	enum vtype vtyp;
1138 	int32_t cverf[2], tverf[2] = { 0, 0 };
1139 	struct thread *p = curthread;
1140 
1141 	if (nd->nd_repstat) {
1142 		nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1143 		goto out;
1144 	}
1145 	NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
1146 	    LOCKPARENT | LOCKLEAF | SAVESTART | NOCACHE);
1147 	nfsvno_setpathbuf(&named, &bufp, &hashp);
1148 	error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
1149 	if (error)
1150 		goto nfsmout;
1151 	if (!nd->nd_repstat) {
1152 		NFSVNO_ATTRINIT(&nva);
1153 		if (nd->nd_flag & ND_NFSV2) {
1154 			NFSM_DISSECT(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1155 			vtyp = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
1156 			if (vtyp == VNON)
1157 				vtyp = VREG;
1158 			NFSVNO_SETATTRVAL(&nva, type, vtyp);
1159 			NFSVNO_SETATTRVAL(&nva, mode,
1160 			    nfstov_mode(sp->sa_mode));
1161 			switch (nva.na_type) {
1162 			case VREG:
1163 				tsize = fxdr_unsigned(int32_t, sp->sa_size);
1164 				if (tsize != -1)
1165 					NFSVNO_SETATTRVAL(&nva, size,
1166 					    (u_quad_t)tsize);
1167 				break;
1168 			case VCHR:
1169 			case VBLK:
1170 			case VFIFO:
1171 				rdev = fxdr_unsigned(NFSDEV_T, sp->sa_size);
1172 				break;
1173 			default:
1174 				break;
1175 			}
1176 		} else {
1177 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1178 			how = fxdr_unsigned(int, *tl);
1179 			switch (how) {
1180 			case NFSCREATE_GUARDED:
1181 			case NFSCREATE_UNCHECKED:
1182 				error = nfsrv_sattr(nd, NULL, &nva, NULL, NULL, p);
1183 				if (error)
1184 					goto nfsmout;
1185 				break;
1186 			case NFSCREATE_EXCLUSIVE:
1187 				NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF);
1188 				cverf[0] = *tl++;
1189 				cverf[1] = *tl;
1190 				exclusive_flag = 1;
1191 				break;
1192 			}
1193 			NFSVNO_SETATTRVAL(&nva, type, VREG);
1194 		}
1195 	}
1196 	if (nd->nd_repstat) {
1197 		nfsvno_relpathbuf(&named);
1198 		if (nd->nd_flag & ND_NFSV3) {
1199 			dirfor_ret = nfsvno_getattr(dp, &dirfor, nd, p, 1,
1200 			    NULL);
1201 			nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
1202 			    &diraft);
1203 		}
1204 		vput(dp);
1205 		goto out;
1206 	}
1207 
1208 	nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, p, &dirp);
1209 	if (dirp) {
1210 		if (nd->nd_flag & ND_NFSV2) {
1211 			vrele(dirp);
1212 			dirp = NULL;
1213 		} else {
1214 			dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0,
1215 			    NULL);
1216 		}
1217 	}
1218 	if (nd->nd_repstat) {
1219 		if (nd->nd_flag & ND_NFSV3)
1220 			nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
1221 			    &diraft);
1222 		if (dirp)
1223 			vrele(dirp);
1224 		goto out;
1225 	}
1226 
1227 	if (!(nd->nd_flag & ND_NFSV2)) {
1228 		switch (how) {
1229 		case NFSCREATE_GUARDED:
1230 			if (named.ni_vp)
1231 				nd->nd_repstat = EEXIST;
1232 			break;
1233 		case NFSCREATE_UNCHECKED:
1234 			break;
1235 		case NFSCREATE_EXCLUSIVE:
1236 			if (named.ni_vp == NULL)
1237 				NFSVNO_SETATTRVAL(&nva, mode, 0);
1238 			break;
1239 		}
1240 	}
1241 
1242 	/*
1243 	 * Iff doesn't exist, create it
1244 	 * otherwise just truncate to 0 length
1245 	 *   should I set the mode too ?
1246 	 */
1247 	nd->nd_repstat = nfsvno_createsub(nd, &named, &vp, &nva,
1248 	    &exclusive_flag, cverf, rdev, exp);
1249 
1250 	if (!nd->nd_repstat) {
1251 		nd->nd_repstat = nfsvno_getfh(vp, &fh, p);
1252 		if (!nd->nd_repstat)
1253 			nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1,
1254 			    NULL);
1255 		vput(vp);
1256 		if (!nd->nd_repstat) {
1257 			tverf[0] = nva.na_atime.tv_sec;
1258 			tverf[1] = nva.na_atime.tv_nsec;
1259 		}
1260 	}
1261 	if (nd->nd_flag & ND_NFSV2) {
1262 		if (!nd->nd_repstat) {
1263 			(void) nfsm_fhtom(nd, (u_int8_t *)&fh, 0, 0);
1264 			nfsrv_fillattr(nd, &nva);
1265 		}
1266 	} else {
1267 		if (exclusive_flag && !nd->nd_repstat && (cverf[0] != tverf[0]
1268 		    || cverf[1] != tverf[1]))
1269 			nd->nd_repstat = EEXIST;
1270 		diraft_ret = nfsvno_getattr(dirp, &diraft, nd, p, 0, NULL);
1271 		vrele(dirp);
1272 		if (!nd->nd_repstat) {
1273 			(void) nfsm_fhtom(nd, (u_int8_t *)&fh, 0, 1);
1274 			nfsrv_postopattr(nd, 0, &nva);
1275 		}
1276 		nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1277 	}
1278 
1279 out:
1280 	NFSEXITCODE2(0, nd);
1281 	return (0);
1282 nfsmout:
1283 	vput(dp);
1284 	nfsvno_relpathbuf(&named);
1285 	NFSEXITCODE2(error, nd);
1286 	return (error);
1287 }
1288 
1289 /*
1290  * nfs v3 mknod service (and v4 create)
1291  */
1292 int
1293 nfsrvd_mknod(struct nfsrv_descript *nd, __unused int isdgram,
1294     vnode_t dp, vnode_t *vpp, fhandle_t *fhp, struct nfsexstuff *exp)
1295 {
1296 	struct nfsvattr nva, dirfor, diraft;
1297 	u_int32_t *tl;
1298 	struct nameidata named;
1299 	int error = 0, dirfor_ret = 1, diraft_ret = 1, pathlen;
1300 	u_int32_t major, minor;
1301 	enum vtype vtyp = VNON;
1302 	nfstype nfs4type = NFNON;
1303 	vnode_t vp, dirp = NULL;
1304 	nfsattrbit_t attrbits;
1305 	char *bufp = NULL, *pathcp = NULL;
1306 	u_long *hashp, cnflags;
1307 	NFSACL_T *aclp = NULL;
1308 	struct thread *p = curthread;
1309 
1310 	NFSVNO_ATTRINIT(&nva);
1311 	cnflags = (LOCKPARENT | SAVESTART);
1312 	if (nd->nd_repstat) {
1313 		nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1314 		goto out;
1315 	}
1316 #ifdef NFS4_ACL_EXTATTR_NAME
1317 	aclp = acl_alloc(M_WAITOK);
1318 	aclp->acl_cnt = 0;
1319 #endif
1320 
1321 	/*
1322 	 * For V4, the creation stuff is here, Yuck!
1323 	 */
1324 	if (nd->nd_flag & ND_NFSV4) {
1325 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1326 		vtyp = nfsv34tov_type(*tl);
1327 		nfs4type = fxdr_unsigned(nfstype, *tl);
1328 		switch (nfs4type) {
1329 		case NFLNK:
1330 			error = nfsvno_getsymlink(nd, &nva, p, &pathcp,
1331 			    &pathlen);
1332 			if (error)
1333 				goto nfsmout;
1334 			break;
1335 		case NFCHR:
1336 		case NFBLK:
1337 			NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1338 			major = fxdr_unsigned(u_int32_t, *tl++);
1339 			minor = fxdr_unsigned(u_int32_t, *tl);
1340 			nva.na_rdev = NFSMAKEDEV(major, minor);
1341 			break;
1342 		case NFSOCK:
1343 		case NFFIFO:
1344 			break;
1345 		case NFDIR:
1346 			cnflags = (LOCKPARENT | SAVENAME);
1347 			break;
1348 		default:
1349 			nd->nd_repstat = NFSERR_BADTYPE;
1350 			vrele(dp);
1351 #ifdef NFS4_ACL_EXTATTR_NAME
1352 			acl_free(aclp);
1353 #endif
1354 			goto out;
1355 		}
1356 	}
1357 	NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, cnflags | NOCACHE);
1358 	nfsvno_setpathbuf(&named, &bufp, &hashp);
1359 	error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
1360 	if (error)
1361 		goto nfsmout;
1362 	if (!nd->nd_repstat) {
1363 		if (nd->nd_flag & ND_NFSV3) {
1364 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1365 			vtyp = nfsv34tov_type(*tl);
1366 		}
1367 		error = nfsrv_sattr(nd, NULL, &nva, &attrbits, aclp, p);
1368 		if (error)
1369 			goto nfsmout;
1370 		nva.na_type = vtyp;
1371 		if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV3) &&
1372 		    (vtyp == VCHR || vtyp == VBLK)) {
1373 			NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1374 			major = fxdr_unsigned(u_int32_t, *tl++);
1375 			minor = fxdr_unsigned(u_int32_t, *tl);
1376 			nva.na_rdev = NFSMAKEDEV(major, minor);
1377 		}
1378 	}
1379 
1380 	dirfor_ret = nfsvno_getattr(dp, &dirfor, nd, p, 0, NULL);
1381 	if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV4)) {
1382 		if (!dirfor_ret && NFSVNO_ISSETGID(&nva) &&
1383 		    dirfor.na_gid == nva.na_gid)
1384 			NFSVNO_UNSET(&nva, gid);
1385 		nd->nd_repstat = nfsrv_checkuidgid(nd, &nva);
1386 	}
1387 	if (nd->nd_repstat) {
1388 		vrele(dp);
1389 #ifdef NFS4_ACL_EXTATTR_NAME
1390 		acl_free(aclp);
1391 #endif
1392 		nfsvno_relpathbuf(&named);
1393 		if (pathcp)
1394 			free(pathcp, M_TEMP);
1395 		if (nd->nd_flag & ND_NFSV3)
1396 			nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
1397 			    &diraft);
1398 		goto out;
1399 	}
1400 
1401 	/*
1402 	 * Yuck! For V4, mkdir and link are here and some V4 clients don't fill
1403 	 * in va_mode, so we'll have to set a default here.
1404 	 */
1405 	if (NFSVNO_NOTSETMODE(&nva)) {
1406 		if (vtyp == VLNK)
1407 			nva.na_mode = 0755;
1408 		else
1409 			nva.na_mode = 0400;
1410 	}
1411 
1412 	if (vtyp == VDIR)
1413 		named.ni_cnd.cn_flags |= WILLBEDIR;
1414 	nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp);
1415 	if (nd->nd_repstat) {
1416 		if (dirp) {
1417 			if (nd->nd_flag & ND_NFSV3)
1418 				dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd,
1419 				    p, 0, NULL);
1420 			vrele(dirp);
1421 		}
1422 #ifdef NFS4_ACL_EXTATTR_NAME
1423 		acl_free(aclp);
1424 #endif
1425 		if (nd->nd_flag & ND_NFSV3)
1426 			nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
1427 			    &diraft);
1428 		goto out;
1429 	}
1430 	if (dirp)
1431 		dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0, NULL);
1432 
1433 	if ((nd->nd_flag & ND_NFSV4) && (vtyp == VDIR || vtyp == VLNK)) {
1434 		if (vtyp == VDIR) {
1435 			nfsrvd_mkdirsub(nd, &named, &nva, fhp, vpp, dirp,
1436 			    &dirfor, &diraft, &diraft_ret, &attrbits, aclp, p,
1437 			    exp);
1438 #ifdef NFS4_ACL_EXTATTR_NAME
1439 			acl_free(aclp);
1440 #endif
1441 			goto out;
1442 		} else if (vtyp == VLNK) {
1443 			nfsrvd_symlinksub(nd, &named, &nva, fhp, vpp, dirp,
1444 			    &dirfor, &diraft, &diraft_ret, &attrbits,
1445 			    aclp, p, exp, pathcp, pathlen);
1446 #ifdef NFS4_ACL_EXTATTR_NAME
1447 			acl_free(aclp);
1448 #endif
1449 			free(pathcp, M_TEMP);
1450 			goto out;
1451 		}
1452 	}
1453 
1454 	nd->nd_repstat = nfsvno_mknod(&named, &nva, nd->nd_cred, p);
1455 	if (!nd->nd_repstat) {
1456 		vp = named.ni_vp;
1457 		nfsrv_fixattr(nd, vp, &nva, aclp, p, &attrbits, exp);
1458 		nd->nd_repstat = nfsvno_getfh(vp, fhp, p);
1459 		if ((nd->nd_flag & ND_NFSV3) && !nd->nd_repstat)
1460 			nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1,
1461 			    NULL);
1462 		if (vpp != NULL && nd->nd_repstat == 0) {
1463 			NFSVOPUNLOCK(vp);
1464 			*vpp = vp;
1465 		} else
1466 			vput(vp);
1467 	}
1468 
1469 	diraft_ret = nfsvno_getattr(dirp, &diraft, nd, p, 0, NULL);
1470 	vrele(dirp);
1471 	if (!nd->nd_repstat) {
1472 		if (nd->nd_flag & ND_NFSV3) {
1473 			(void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 1);
1474 			nfsrv_postopattr(nd, 0, &nva);
1475 		} else {
1476 			NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1477 			*tl++ = newnfs_false;
1478 			txdr_hyper(dirfor.na_filerev, tl);
1479 			tl += 2;
1480 			txdr_hyper(diraft.na_filerev, tl);
1481 			(void) nfsrv_putattrbit(nd, &attrbits);
1482 		}
1483 	}
1484 	if (nd->nd_flag & ND_NFSV3)
1485 		nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1486 #ifdef NFS4_ACL_EXTATTR_NAME
1487 	acl_free(aclp);
1488 #endif
1489 
1490 out:
1491 	NFSEXITCODE2(0, nd);
1492 	return (0);
1493 nfsmout:
1494 	vrele(dp);
1495 #ifdef NFS4_ACL_EXTATTR_NAME
1496 	acl_free(aclp);
1497 #endif
1498 	if (bufp)
1499 		nfsvno_relpathbuf(&named);
1500 	if (pathcp)
1501 		free(pathcp, M_TEMP);
1502 
1503 	NFSEXITCODE2(error, nd);
1504 	return (error);
1505 }
1506 
1507 /*
1508  * nfs remove service
1509  */
1510 int
1511 nfsrvd_remove(struct nfsrv_descript *nd, __unused int isdgram,
1512     vnode_t dp, struct nfsexstuff *exp)
1513 {
1514 	struct nameidata named;
1515 	u_int32_t *tl;
1516 	int error = 0, dirfor_ret = 1, diraft_ret = 1;
1517 	vnode_t dirp = NULL;
1518 	struct nfsvattr dirfor, diraft;
1519 	char *bufp;
1520 	u_long *hashp;
1521 	struct thread *p = curthread;
1522 
1523 	if (nd->nd_repstat) {
1524 		nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1525 		goto out;
1526 	}
1527 	NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, DELETE,
1528 	    LOCKPARENT | LOCKLEAF);
1529 	nfsvno_setpathbuf(&named, &bufp, &hashp);
1530 	error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
1531 	if (error) {
1532 		vput(dp);
1533 		nfsvno_relpathbuf(&named);
1534 		goto out;
1535 	}
1536 	if (!nd->nd_repstat) {
1537 		nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, p, &dirp);
1538 	} else {
1539 		vput(dp);
1540 		nfsvno_relpathbuf(&named);
1541 	}
1542 	if (dirp) {
1543 		if (!(nd->nd_flag & ND_NFSV2)) {
1544 			dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0,
1545 			    NULL);
1546 		} else {
1547 			vrele(dirp);
1548 			dirp = NULL;
1549 		}
1550 	}
1551 	if (!nd->nd_repstat) {
1552 		if (nd->nd_flag & ND_NFSV4) {
1553 			if (vnode_vtype(named.ni_vp) == VDIR)
1554 				nd->nd_repstat = nfsvno_rmdirsub(&named, 1,
1555 				    nd->nd_cred, p, exp);
1556 			else
1557 				nd->nd_repstat = nfsvno_removesub(&named, 1,
1558 				    nd->nd_cred, p, exp);
1559 		} else if (nd->nd_procnum == NFSPROC_RMDIR) {
1560 			nd->nd_repstat = nfsvno_rmdirsub(&named, 0,
1561 			    nd->nd_cred, p, exp);
1562 		} else {
1563 			nd->nd_repstat = nfsvno_removesub(&named, 0,
1564 			    nd->nd_cred, p, exp);
1565 		}
1566 	}
1567 	if (!(nd->nd_flag & ND_NFSV2)) {
1568 		if (dirp) {
1569 			diraft_ret = nfsvno_getattr(dirp, &diraft, nd, p, 0,
1570 			    NULL);
1571 			vrele(dirp);
1572 		}
1573 		if (nd->nd_flag & ND_NFSV3) {
1574 			nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
1575 			    &diraft);
1576 		} else if (!nd->nd_repstat) {
1577 			NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1578 			*tl++ = newnfs_false;
1579 			txdr_hyper(dirfor.na_filerev, tl);
1580 			tl += 2;
1581 			txdr_hyper(diraft.na_filerev, tl);
1582 		}
1583 	}
1584 
1585 out:
1586 	NFSEXITCODE2(error, nd);
1587 	return (error);
1588 }
1589 
1590 /*
1591  * nfs rename service
1592  */
1593 int
1594 nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
1595     vnode_t dp, vnode_t todp, struct nfsexstuff *exp, struct nfsexstuff *toexp)
1596 {
1597 	u_int32_t *tl;
1598 	int error = 0, fdirfor_ret = 1, fdiraft_ret = 1;
1599 	int tdirfor_ret = 1, tdiraft_ret = 1;
1600 	struct nameidata fromnd, tond;
1601 	vnode_t fdirp = NULL, tdirp = NULL, tdp = NULL;
1602 	struct nfsvattr fdirfor, fdiraft, tdirfor, tdiraft;
1603 	struct nfsexstuff tnes;
1604 	struct nfsrvfh tfh;
1605 	char *bufp, *tbufp = NULL;
1606 	u_long *hashp;
1607 	fhandle_t fh;
1608 	struct thread *p = curthread;
1609 
1610 	if (nd->nd_repstat) {
1611 		nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
1612 		nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
1613 		goto out;
1614 	}
1615 	if (!(nd->nd_flag & ND_NFSV2))
1616 		fdirfor_ret = nfsvno_getattr(dp, &fdirfor, nd, p, 1, NULL);
1617 	tond.ni_cnd.cn_nameiop = 0;
1618 	tond.ni_startdir = NULL;
1619 	NFSNAMEICNDSET(&fromnd.ni_cnd, nd->nd_cred, DELETE, WANTPARENT | SAVESTART);
1620 	nfsvno_setpathbuf(&fromnd, &bufp, &hashp);
1621 	error = nfsrv_parsename(nd, bufp, hashp, &fromnd.ni_pathlen);
1622 	if (error) {
1623 		vput(dp);
1624 		if (todp)
1625 			vrele(todp);
1626 		nfsvno_relpathbuf(&fromnd);
1627 		goto out;
1628 	}
1629 	/*
1630 	 * Unlock dp in this code section, so it is unlocked before
1631 	 * tdp gets locked. This avoids a potential LOR if tdp is the
1632 	 * parent directory of dp.
1633 	 */
1634 	if (nd->nd_flag & ND_NFSV4) {
1635 		tdp = todp;
1636 		tnes = *toexp;
1637 		if (dp != tdp) {
1638 			NFSVOPUNLOCK(dp);
1639 			/* Might lock tdp. */
1640 			tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd, p, 0,
1641 			    NULL);
1642 		} else {
1643 			tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd, p, 1,
1644 			    NULL);
1645 			NFSVOPUNLOCK(dp);
1646 		}
1647 	} else {
1648 		tfh.nfsrvfh_len = 0;
1649 		error = nfsrv_mtofh(nd, &tfh);
1650 		if (error == 0)
1651 			error = nfsvno_getfh(dp, &fh, p);
1652 		if (error) {
1653 			vput(dp);
1654 			/* todp is always NULL except NFSv4 */
1655 			nfsvno_relpathbuf(&fromnd);
1656 			goto out;
1657 		}
1658 
1659 		/* If this is the same file handle, just VREF() the vnode. */
1660 		if (tfh.nfsrvfh_len == NFSX_MYFH &&
1661 		    !NFSBCMP(tfh.nfsrvfh_data, &fh, NFSX_MYFH)) {
1662 			VREF(dp);
1663 			tdp = dp;
1664 			tnes = *exp;
1665 			tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd, p, 1,
1666 			    NULL);
1667 			NFSVOPUNLOCK(dp);
1668 		} else {
1669 			NFSVOPUNLOCK(dp);
1670 			nd->nd_cred->cr_uid = nd->nd_saveduid;
1671 			nfsd_fhtovp(nd, &tfh, LK_EXCLUSIVE, &tdp, &tnes, NULL,
1672 			    0);	/* Locks tdp. */
1673 			if (tdp) {
1674 				tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd,
1675 				    p, 1, NULL);
1676 				NFSVOPUNLOCK(tdp);
1677 			}
1678 		}
1679 	}
1680 	NFSNAMEICNDSET(&tond.ni_cnd, nd->nd_cred, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART);
1681 	nfsvno_setpathbuf(&tond, &tbufp, &hashp);
1682 	if (!nd->nd_repstat) {
1683 		error = nfsrv_parsename(nd, tbufp, hashp, &tond.ni_pathlen);
1684 		if (error) {
1685 			if (tdp)
1686 				vrele(tdp);
1687 			vrele(dp);
1688 			nfsvno_relpathbuf(&fromnd);
1689 			nfsvno_relpathbuf(&tond);
1690 			goto out;
1691 		}
1692 	}
1693 	if (nd->nd_repstat) {
1694 		if (nd->nd_flag & ND_NFSV3) {
1695 			nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret,
1696 			    &fdiraft);
1697 			nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret,
1698 			    &tdiraft);
1699 		}
1700 		if (tdp)
1701 			vrele(tdp);
1702 		vrele(dp);
1703 		nfsvno_relpathbuf(&fromnd);
1704 		nfsvno_relpathbuf(&tond);
1705 		goto out;
1706 	}
1707 
1708 	/*
1709 	 * Done parsing, now down to business.
1710 	 */
1711 	nd->nd_repstat = nfsvno_namei(nd, &fromnd, dp, 0, exp, p, &fdirp);
1712 	if (nd->nd_repstat) {
1713 		if (nd->nd_flag & ND_NFSV3) {
1714 			nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret,
1715 			    &fdiraft);
1716 			nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret,
1717 			    &tdiraft);
1718 		}
1719 		if (fdirp)
1720 			vrele(fdirp);
1721 		if (tdp)
1722 			vrele(tdp);
1723 		nfsvno_relpathbuf(&tond);
1724 		goto out;
1725 	}
1726 	if (vnode_vtype(fromnd.ni_vp) == VDIR)
1727 		tond.ni_cnd.cn_flags |= WILLBEDIR;
1728 	nd->nd_repstat = nfsvno_namei(nd, &tond, tdp, 0, &tnes, p, &tdirp);
1729 	nd->nd_repstat = nfsvno_rename(&fromnd, &tond, nd->nd_repstat,
1730 	    nd->nd_flag, nd->nd_cred, p);
1731 	if (fdirp)
1732 		fdiraft_ret = nfsvno_getattr(fdirp, &fdiraft, nd, p, 0, NULL);
1733 	if (tdirp)
1734 		tdiraft_ret = nfsvno_getattr(tdirp, &tdiraft, nd, p, 0, NULL);
1735 	if (fdirp)
1736 		vrele(fdirp);
1737 	if (tdirp)
1738 		vrele(tdirp);
1739 	if (nd->nd_flag & ND_NFSV3) {
1740 		nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
1741 		nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
1742 	} else if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) {
1743 		NFSM_BUILD(tl, u_int32_t *, 10 * NFSX_UNSIGNED);
1744 		*tl++ = newnfs_false;
1745 		txdr_hyper(fdirfor.na_filerev, tl);
1746 		tl += 2;
1747 		txdr_hyper(fdiraft.na_filerev, tl);
1748 		tl += 2;
1749 		*tl++ = newnfs_false;
1750 		txdr_hyper(tdirfor.na_filerev, tl);
1751 		tl += 2;
1752 		txdr_hyper(tdiraft.na_filerev, tl);
1753 	}
1754 
1755 out:
1756 	NFSEXITCODE2(error, nd);
1757 	return (error);
1758 }
1759 
1760 /*
1761  * nfs link service
1762  */
1763 int
1764 nfsrvd_link(struct nfsrv_descript *nd, int isdgram,
1765     vnode_t vp, vnode_t tovp, struct nfsexstuff *exp, struct nfsexstuff *toexp)
1766 {
1767 	struct nameidata named;
1768 	u_int32_t *tl;
1769 	int error = 0, dirfor_ret = 1, diraft_ret = 1, getret = 1;
1770 	vnode_t dirp = NULL, dp = NULL;
1771 	struct nfsvattr dirfor, diraft, at;
1772 	struct nfsexstuff tnes;
1773 	struct nfsrvfh dfh;
1774 	char *bufp;
1775 	u_long *hashp;
1776 	struct thread *p = curthread;
1777 
1778 	if (nd->nd_repstat) {
1779 		nfsrv_postopattr(nd, getret, &at);
1780 		nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1781 		goto out;
1782 	}
1783 	NFSVOPUNLOCK(vp);
1784 	if (vnode_vtype(vp) == VDIR) {
1785 		if (nd->nd_flag & ND_NFSV4)
1786 			nd->nd_repstat = NFSERR_ISDIR;
1787 		else
1788 			nd->nd_repstat = NFSERR_INVAL;
1789 		if (tovp)
1790 			vrele(tovp);
1791 	}
1792 	if (!nd->nd_repstat) {
1793 		if (nd->nd_flag & ND_NFSV4) {
1794 			dp = tovp;
1795 			tnes = *toexp;
1796 		} else {
1797 			error = nfsrv_mtofh(nd, &dfh);
1798 			if (error) {
1799 				vrele(vp);
1800 				/* tovp is always NULL unless NFSv4 */
1801 				goto out;
1802 			}
1803 			nfsd_fhtovp(nd, &dfh, LK_EXCLUSIVE, &dp, &tnes, NULL, 0);
1804 			if (dp)
1805 				NFSVOPUNLOCK(dp);
1806 		}
1807 	}
1808 	NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
1809 	    LOCKPARENT | SAVENAME | NOCACHE);
1810 	if (!nd->nd_repstat) {
1811 		nfsvno_setpathbuf(&named, &bufp, &hashp);
1812 		error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
1813 		if (error) {
1814 			vrele(vp);
1815 			if (dp)
1816 				vrele(dp);
1817 			nfsvno_relpathbuf(&named);
1818 			goto out;
1819 		}
1820 		if (!nd->nd_repstat) {
1821 			nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, &tnes,
1822 			    p, &dirp);
1823 		} else {
1824 			if (dp)
1825 				vrele(dp);
1826 			nfsvno_relpathbuf(&named);
1827 		}
1828 	}
1829 	if (dirp) {
1830 		if (nd->nd_flag & ND_NFSV2) {
1831 			vrele(dirp);
1832 			dirp = NULL;
1833 		} else {
1834 			dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0,
1835 			    NULL);
1836 		}
1837 	}
1838 	if (!nd->nd_repstat)
1839 		nd->nd_repstat = nfsvno_link(&named, vp, nd->nd_cred, p, exp);
1840 	if (nd->nd_flag & ND_NFSV3)
1841 		getret = nfsvno_getattr(vp, &at, nd, p, 0, NULL);
1842 	if (dirp) {
1843 		diraft_ret = nfsvno_getattr(dirp, &diraft, nd, p, 0, NULL);
1844 		vrele(dirp);
1845 	}
1846 	vrele(vp);
1847 	if (nd->nd_flag & ND_NFSV3) {
1848 		nfsrv_postopattr(nd, getret, &at);
1849 		nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1850 	} else if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) {
1851 		NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1852 		*tl++ = newnfs_false;
1853 		txdr_hyper(dirfor.na_filerev, tl);
1854 		tl += 2;
1855 		txdr_hyper(diraft.na_filerev, tl);
1856 	}
1857 
1858 out:
1859 	NFSEXITCODE2(error, nd);
1860 	return (error);
1861 }
1862 
1863 /*
1864  * nfs symbolic link service
1865  */
1866 int
1867 nfsrvd_symlink(struct nfsrv_descript *nd, __unused int isdgram,
1868     vnode_t dp, vnode_t *vpp, fhandle_t *fhp, struct nfsexstuff *exp)
1869 {
1870 	struct nfsvattr nva, dirfor, diraft;
1871 	struct nameidata named;
1872 	int error = 0, dirfor_ret = 1, diraft_ret = 1, pathlen;
1873 	vnode_t dirp = NULL;
1874 	char *bufp, *pathcp = NULL;
1875 	u_long *hashp;
1876 	struct thread *p = curthread;
1877 
1878 	if (nd->nd_repstat) {
1879 		nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1880 		goto out;
1881 	}
1882 	if (vpp)
1883 		*vpp = NULL;
1884 	NFSVNO_ATTRINIT(&nva);
1885 	NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
1886 	    LOCKPARENT | SAVESTART | NOCACHE);
1887 	nfsvno_setpathbuf(&named, &bufp, &hashp);
1888 	error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
1889 	if (!error && !nd->nd_repstat)
1890 		error = nfsvno_getsymlink(nd, &nva, p, &pathcp, &pathlen);
1891 	if (error) {
1892 		vrele(dp);
1893 		nfsvno_relpathbuf(&named);
1894 		goto out;
1895 	}
1896 	if (!nd->nd_repstat) {
1897 		nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp);
1898 	} else {
1899 		vrele(dp);
1900 		nfsvno_relpathbuf(&named);
1901 	}
1902 	if (dirp != NULL && !(nd->nd_flag & ND_NFSV3)) {
1903 		vrele(dirp);
1904 		dirp = NULL;
1905 	}
1906 
1907 	/*
1908 	 * And call nfsrvd_symlinksub() to do the common code. It will
1909 	 * return EBADRPC upon a parsing error, 0 otherwise.
1910 	 */
1911 	if (!nd->nd_repstat) {
1912 		if (dirp != NULL)
1913 			dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0,
1914 			    NULL);
1915 		nfsrvd_symlinksub(nd, &named, &nva, fhp, vpp, dirp,
1916 		    &dirfor, &diraft, &diraft_ret, NULL, NULL, p, exp,
1917 		    pathcp, pathlen);
1918 	} else if (dirp != NULL) {
1919 		dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0, NULL);
1920 		vrele(dirp);
1921 	}
1922 	if (pathcp)
1923 		free(pathcp, M_TEMP);
1924 
1925 	if (nd->nd_flag & ND_NFSV3) {
1926 		if (!nd->nd_repstat) {
1927 			(void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 1);
1928 			nfsrv_postopattr(nd, 0, &nva);
1929 		}
1930 		nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1931 	}
1932 
1933 out:
1934 	NFSEXITCODE2(error, nd);
1935 	return (error);
1936 }
1937 
1938 /*
1939  * Common code for creating a symbolic link.
1940  */
1941 static void
1942 nfsrvd_symlinksub(struct nfsrv_descript *nd, struct nameidata *ndp,
1943     struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp,
1944     vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp,
1945     int *diraft_retp, nfsattrbit_t *attrbitp,
1946     NFSACL_T *aclp, NFSPROC_T *p, struct nfsexstuff *exp, char *pathcp,
1947     int pathlen)
1948 {
1949 	u_int32_t *tl;
1950 
1951 	nd->nd_repstat = nfsvno_symlink(ndp, nvap, pathcp, pathlen,
1952 	    !(nd->nd_flag & ND_NFSV2), nd->nd_saveduid, nd->nd_cred, p, exp);
1953 	if (!nd->nd_repstat && !(nd->nd_flag & ND_NFSV2)) {
1954 		nfsrv_fixattr(nd, ndp->ni_vp, nvap, aclp, p, attrbitp, exp);
1955 		if (nd->nd_flag & ND_NFSV3) {
1956 			nd->nd_repstat = nfsvno_getfh(ndp->ni_vp, fhp, p);
1957 			if (!nd->nd_repstat)
1958 				nd->nd_repstat = nfsvno_getattr(ndp->ni_vp,
1959 				    nvap, nd, p, 1, NULL);
1960 		}
1961 		if (vpp != NULL && nd->nd_repstat == 0) {
1962 			NFSVOPUNLOCK(ndp->ni_vp);
1963 			*vpp = ndp->ni_vp;
1964 		} else
1965 			vput(ndp->ni_vp);
1966 	}
1967 	if (dirp) {
1968 		*diraft_retp = nfsvno_getattr(dirp, diraftp, nd, p, 0, NULL);
1969 		vrele(dirp);
1970 	}
1971 	if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) {
1972 		NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1973 		*tl++ = newnfs_false;
1974 		txdr_hyper(dirforp->na_filerev, tl);
1975 		tl += 2;
1976 		txdr_hyper(diraftp->na_filerev, tl);
1977 		(void) nfsrv_putattrbit(nd, attrbitp);
1978 	}
1979 
1980 	NFSEXITCODE2(0, nd);
1981 }
1982 
1983 /*
1984  * nfs mkdir service
1985  */
1986 int
1987 nfsrvd_mkdir(struct nfsrv_descript *nd, __unused int isdgram,
1988     vnode_t dp, vnode_t *vpp, fhandle_t *fhp, struct nfsexstuff *exp)
1989 {
1990 	struct nfsvattr nva, dirfor, diraft;
1991 	struct nameidata named;
1992 	u_int32_t *tl;
1993 	int error = 0, dirfor_ret = 1, diraft_ret = 1;
1994 	vnode_t dirp = NULL;
1995 	char *bufp;
1996 	u_long *hashp;
1997 	struct thread *p = curthread;
1998 
1999 	if (nd->nd_repstat) {
2000 		nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
2001 		goto out;
2002 	}
2003 	NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
2004 	    LOCKPARENT | SAVENAME | NOCACHE);
2005 	nfsvno_setpathbuf(&named, &bufp, &hashp);
2006 	error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
2007 	if (error)
2008 		goto nfsmout;
2009 	if (!nd->nd_repstat) {
2010 		NFSVNO_ATTRINIT(&nva);
2011 		if (nd->nd_flag & ND_NFSV3) {
2012 			error = nfsrv_sattr(nd, NULL, &nva, NULL, NULL, p);
2013 			if (error)
2014 				goto nfsmout;
2015 		} else {
2016 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2017 			nva.na_mode = nfstov_mode(*tl++);
2018 		}
2019 	}
2020 	if (!nd->nd_repstat) {
2021 		nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp);
2022 	} else {
2023 		vrele(dp);
2024 		nfsvno_relpathbuf(&named);
2025 	}
2026 	if (dirp != NULL && !(nd->nd_flag & ND_NFSV3)) {
2027 		vrele(dirp);
2028 		dirp = NULL;
2029 	}
2030 	if (nd->nd_repstat) {
2031 		if (dirp != NULL) {
2032 			dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0,
2033 			    NULL);
2034 			vrele(dirp);
2035 		}
2036 		if (nd->nd_flag & ND_NFSV3)
2037 			nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
2038 			    &diraft);
2039 		goto out;
2040 	}
2041 	if (dirp != NULL)
2042 		dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0, NULL);
2043 
2044 	/*
2045 	 * Call nfsrvd_mkdirsub() for the code common to V4 as well.
2046 	 */
2047 	nfsrvd_mkdirsub(nd, &named, &nva, fhp, vpp, dirp, &dirfor, &diraft,
2048 	    &diraft_ret, NULL, NULL, p, exp);
2049 
2050 	if (nd->nd_flag & ND_NFSV3) {
2051 		if (!nd->nd_repstat) {
2052 			(void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 1);
2053 			nfsrv_postopattr(nd, 0, &nva);
2054 		}
2055 		nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
2056 	} else if (!nd->nd_repstat) {
2057 		(void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 0);
2058 		nfsrv_fillattr(nd, &nva);
2059 	}
2060 
2061 out:
2062 	NFSEXITCODE2(0, nd);
2063 	return (0);
2064 nfsmout:
2065 	vrele(dp);
2066 	nfsvno_relpathbuf(&named);
2067 	NFSEXITCODE2(error, nd);
2068 	return (error);
2069 }
2070 
2071 /*
2072  * Code common to mkdir for V2,3 and 4.
2073  */
2074 static void
2075 nfsrvd_mkdirsub(struct nfsrv_descript *nd, struct nameidata *ndp,
2076     struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp,
2077     vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp,
2078     int *diraft_retp, nfsattrbit_t *attrbitp, NFSACL_T *aclp,
2079     NFSPROC_T *p, struct nfsexstuff *exp)
2080 {
2081 	vnode_t vp;
2082 	u_int32_t *tl;
2083 
2084 	NFSVNO_SETATTRVAL(nvap, type, VDIR);
2085 	nd->nd_repstat = nfsvno_mkdir(ndp, nvap, nd->nd_saveduid,
2086 	    nd->nd_cred, p, exp);
2087 	if (!nd->nd_repstat) {
2088 		vp = ndp->ni_vp;
2089 		nfsrv_fixattr(nd, vp, nvap, aclp, p, attrbitp, exp);
2090 		nd->nd_repstat = nfsvno_getfh(vp, fhp, p);
2091 		if (!(nd->nd_flag & ND_NFSV4) && !nd->nd_repstat)
2092 			nd->nd_repstat = nfsvno_getattr(vp, nvap, nd, p, 1,
2093 			    NULL);
2094 		if (vpp && !nd->nd_repstat) {
2095 			NFSVOPUNLOCK(vp);
2096 			*vpp = vp;
2097 		} else {
2098 			vput(vp);
2099 		}
2100 	}
2101 	if (dirp) {
2102 		*diraft_retp = nfsvno_getattr(dirp, diraftp, nd, p, 0, NULL);
2103 		vrele(dirp);
2104 	}
2105 	if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) {
2106 		NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
2107 		*tl++ = newnfs_false;
2108 		txdr_hyper(dirforp->na_filerev, tl);
2109 		tl += 2;
2110 		txdr_hyper(diraftp->na_filerev, tl);
2111 		(void) nfsrv_putattrbit(nd, attrbitp);
2112 	}
2113 
2114 	NFSEXITCODE2(0, nd);
2115 }
2116 
2117 /*
2118  * nfs commit service
2119  */
2120 int
2121 nfsrvd_commit(struct nfsrv_descript *nd, __unused int isdgram,
2122     vnode_t vp, __unused struct nfsexstuff *exp)
2123 {
2124 	struct nfsvattr bfor, aft;
2125 	u_int32_t *tl;
2126 	int error = 0, for_ret = 1, aft_ret = 1, cnt;
2127 	u_int64_t off;
2128 	struct thread *p = curthread;
2129 
2130        if (nd->nd_repstat) {
2131 		nfsrv_wcc(nd, for_ret, &bfor, aft_ret, &aft);
2132 		goto out;
2133 	}
2134 
2135 	/* Return NFSERR_ISDIR in NFSv4 when commit on a directory. */
2136 	if (vp->v_type != VREG) {
2137 		if (nd->nd_flag & ND_NFSV3)
2138 			error = NFSERR_NOTSUPP;
2139 		else
2140 			error = (vp->v_type == VDIR) ? NFSERR_ISDIR : NFSERR_INVAL;
2141 		goto nfsmout;
2142 	}
2143 	NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2144 
2145 	/*
2146 	 * XXX At this time VOP_FSYNC() does not accept offset and byte
2147 	 * count parameters, so these arguments are useless (someday maybe).
2148 	 */
2149 	off = fxdr_hyper(tl);
2150 	tl += 2;
2151 	cnt = fxdr_unsigned(int, *tl);
2152 	if (nd->nd_flag & ND_NFSV3)
2153 		for_ret = nfsvno_getattr(vp, &bfor, nd, p, 1, NULL);
2154 	nd->nd_repstat = nfsvno_fsync(vp, off, cnt, nd->nd_cred, p);
2155 	if (nd->nd_flag & ND_NFSV3) {
2156 		aft_ret = nfsvno_getattr(vp, &aft, nd, p, 1, NULL);
2157 		nfsrv_wcc(nd, for_ret, &bfor, aft_ret, &aft);
2158 	}
2159 	vput(vp);
2160 	if (!nd->nd_repstat) {
2161 		NFSM_BUILD(tl, u_int32_t *, NFSX_VERF);
2162 		*tl++ = txdr_unsigned(nfsboottime.tv_sec);
2163 		*tl = txdr_unsigned(nfsboottime.tv_usec);
2164 	}
2165 
2166 out:
2167 	NFSEXITCODE2(0, nd);
2168 	return (0);
2169 nfsmout:
2170 	vput(vp);
2171 	NFSEXITCODE2(error, nd);
2172 	return (error);
2173 }
2174 
2175 /*
2176  * nfs statfs service
2177  */
2178 int
2179 nfsrvd_statfs(struct nfsrv_descript *nd, __unused int isdgram,
2180     vnode_t vp, __unused struct nfsexstuff *exp)
2181 {
2182 	struct statfs *sf;
2183 	u_int32_t *tl;
2184 	int getret = 1;
2185 	struct nfsvattr at;
2186 	u_quad_t tval;
2187 	struct thread *p = curthread;
2188 
2189 	sf = NULL;
2190 	if (nd->nd_repstat) {
2191 		nfsrv_postopattr(nd, getret, &at);
2192 		goto out;
2193 	}
2194 	sf = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
2195 	nd->nd_repstat = nfsvno_statfs(vp, sf);
2196 	getret = nfsvno_getattr(vp, &at, nd, p, 1, NULL);
2197 	vput(vp);
2198 	if (nd->nd_flag & ND_NFSV3)
2199 		nfsrv_postopattr(nd, getret, &at);
2200 	if (nd->nd_repstat)
2201 		goto out;
2202 	if (nd->nd_flag & ND_NFSV2) {
2203 		NFSM_BUILD(tl, u_int32_t *, NFSX_V2STATFS);
2204 		*tl++ = txdr_unsigned(NFS_V2MAXDATA);
2205 		*tl++ = txdr_unsigned(sf->f_bsize);
2206 		*tl++ = txdr_unsigned(sf->f_blocks);
2207 		*tl++ = txdr_unsigned(sf->f_bfree);
2208 		*tl = txdr_unsigned(sf->f_bavail);
2209 	} else {
2210 		NFSM_BUILD(tl, u_int32_t *, NFSX_V3STATFS);
2211 		tval = (u_quad_t)sf->f_blocks;
2212 		tval *= (u_quad_t)sf->f_bsize;
2213 		txdr_hyper(tval, tl); tl += 2;
2214 		tval = (u_quad_t)sf->f_bfree;
2215 		tval *= (u_quad_t)sf->f_bsize;
2216 		txdr_hyper(tval, tl); tl += 2;
2217 		tval = (u_quad_t)sf->f_bavail;
2218 		tval *= (u_quad_t)sf->f_bsize;
2219 		txdr_hyper(tval, tl); tl += 2;
2220 		tval = (u_quad_t)sf->f_files;
2221 		txdr_hyper(tval, tl); tl += 2;
2222 		tval = (u_quad_t)sf->f_ffree;
2223 		txdr_hyper(tval, tl); tl += 2;
2224 		tval = (u_quad_t)sf->f_ffree;
2225 		txdr_hyper(tval, tl); tl += 2;
2226 		*tl = 0;
2227 	}
2228 
2229 out:
2230 	free(sf, M_STATFS);
2231 	NFSEXITCODE2(0, nd);
2232 	return (0);
2233 }
2234 
2235 /*
2236  * nfs fsinfo service
2237  */
2238 int
2239 nfsrvd_fsinfo(struct nfsrv_descript *nd, int isdgram,
2240     vnode_t vp, __unused struct nfsexstuff *exp)
2241 {
2242 	u_int32_t *tl;
2243 	struct nfsfsinfo fs;
2244 	int getret = 1;
2245 	struct nfsvattr at;
2246 	struct thread *p = curthread;
2247 
2248 	if (nd->nd_repstat) {
2249 		nfsrv_postopattr(nd, getret, &at);
2250 		goto out;
2251 	}
2252 	getret = nfsvno_getattr(vp, &at, nd, p, 1, NULL);
2253 	nfsvno_getfs(&fs, isdgram);
2254 	vput(vp);
2255 	nfsrv_postopattr(nd, getret, &at);
2256 	NFSM_BUILD(tl, u_int32_t *, NFSX_V3FSINFO);
2257 	*tl++ = txdr_unsigned(fs.fs_rtmax);
2258 	*tl++ = txdr_unsigned(fs.fs_rtpref);
2259 	*tl++ = txdr_unsigned(fs.fs_rtmult);
2260 	*tl++ = txdr_unsigned(fs.fs_wtmax);
2261 	*tl++ = txdr_unsigned(fs.fs_wtpref);
2262 	*tl++ = txdr_unsigned(fs.fs_wtmult);
2263 	*tl++ = txdr_unsigned(fs.fs_dtpref);
2264 	txdr_hyper(fs.fs_maxfilesize, tl);
2265 	tl += 2;
2266 	txdr_nfsv3time(&fs.fs_timedelta, tl);
2267 	tl += 2;
2268 	*tl = txdr_unsigned(fs.fs_properties);
2269 
2270 out:
2271 	NFSEXITCODE2(0, nd);
2272 	return (0);
2273 }
2274 
2275 /*
2276  * nfs pathconf service
2277  */
2278 int
2279 nfsrvd_pathconf(struct nfsrv_descript *nd, __unused int isdgram,
2280     vnode_t vp, __unused struct nfsexstuff *exp)
2281 {
2282 	struct nfsv3_pathconf *pc;
2283 	int getret = 1;
2284 	long linkmax, namemax, chownres, notrunc;
2285 	struct nfsvattr at;
2286 	struct thread *p = curthread;
2287 
2288 	if (nd->nd_repstat) {
2289 		nfsrv_postopattr(nd, getret, &at);
2290 		goto out;
2291 	}
2292 	nd->nd_repstat = nfsvno_pathconf(vp, _PC_LINK_MAX, &linkmax,
2293 	    nd->nd_cred, p);
2294 	if (!nd->nd_repstat)
2295 		nd->nd_repstat = nfsvno_pathconf(vp, _PC_NAME_MAX, &namemax,
2296 		    nd->nd_cred, p);
2297 	if (!nd->nd_repstat)
2298 		nd->nd_repstat=nfsvno_pathconf(vp, _PC_CHOWN_RESTRICTED,
2299 		    &chownres, nd->nd_cred, p);
2300 	if (!nd->nd_repstat)
2301 		nd->nd_repstat = nfsvno_pathconf(vp, _PC_NO_TRUNC, &notrunc,
2302 		    nd->nd_cred, p);
2303 	getret = nfsvno_getattr(vp, &at, nd, p, 1, NULL);
2304 	vput(vp);
2305 	nfsrv_postopattr(nd, getret, &at);
2306 	if (!nd->nd_repstat) {
2307 		NFSM_BUILD(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF);
2308 		pc->pc_linkmax = txdr_unsigned(linkmax);
2309 		pc->pc_namemax = txdr_unsigned(namemax);
2310 		pc->pc_notrunc = txdr_unsigned(notrunc);
2311 		pc->pc_chownrestricted = txdr_unsigned(chownres);
2312 
2313 		/*
2314 		 * These should probably be supported by VOP_PATHCONF(), but
2315 		 * until msdosfs is exportable (why would you want to?), the
2316 		 * Unix defaults should be ok.
2317 		 */
2318 		pc->pc_caseinsensitive = newnfs_false;
2319 		pc->pc_casepreserving = newnfs_true;
2320 	}
2321 
2322 out:
2323 	NFSEXITCODE2(0, nd);
2324 	return (0);
2325 }
2326 
2327 /*
2328  * nfsv4 lock service
2329  */
2330 int
2331 nfsrvd_lock(struct nfsrv_descript *nd, __unused int isdgram,
2332     vnode_t vp, struct nfsexstuff *exp)
2333 {
2334 	u_int32_t *tl;
2335 	int i;
2336 	struct nfsstate *stp = NULL;
2337 	struct nfslock *lop;
2338 	struct nfslockconflict cf;
2339 	int error = 0;
2340 	u_short flags = NFSLCK_LOCK, lflags;
2341 	u_int64_t offset, len;
2342 	nfsv4stateid_t stateid;
2343 	nfsquad_t clientid;
2344 	struct thread *p = curthread;
2345 
2346 	NFSM_DISSECT(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
2347 	i = fxdr_unsigned(int, *tl++);
2348 	switch (i) {
2349 	case NFSV4LOCKT_READW:
2350 		flags |= NFSLCK_BLOCKING;
2351 	case NFSV4LOCKT_READ:
2352 		lflags = NFSLCK_READ;
2353 		break;
2354 	case NFSV4LOCKT_WRITEW:
2355 		flags |= NFSLCK_BLOCKING;
2356 	case NFSV4LOCKT_WRITE:
2357 		lflags = NFSLCK_WRITE;
2358 		break;
2359 	default:
2360 		nd->nd_repstat = NFSERR_BADXDR;
2361 		goto nfsmout;
2362 	}
2363 	if (*tl++ == newnfs_true)
2364 		flags |= NFSLCK_RECLAIM;
2365 	offset = fxdr_hyper(tl);
2366 	tl += 2;
2367 	len = fxdr_hyper(tl);
2368 	tl += 2;
2369 	if (*tl == newnfs_true)
2370 		flags |= NFSLCK_OPENTOLOCK;
2371 	if (flags & NFSLCK_OPENTOLOCK) {
2372 		NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED + NFSX_STATEID);
2373 		i = fxdr_unsigned(int, *(tl+4+(NFSX_STATEID / NFSX_UNSIGNED)));
2374 		if (i <= 0 || i > NFSV4_OPAQUELIMIT) {
2375 			nd->nd_repstat = NFSERR_BADXDR;
2376 			goto nfsmout;
2377 		}
2378 		stp = malloc(sizeof (struct nfsstate) + i,
2379 			M_NFSDSTATE, M_WAITOK);
2380 		stp->ls_ownerlen = i;
2381 		stp->ls_op = nd->nd_rp;
2382 		stp->ls_seq = fxdr_unsigned(int, *tl++);
2383 		stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
2384 		NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
2385 			NFSX_STATEIDOTHER);
2386 		tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
2387 
2388 		/*
2389 		 * For the special stateid of other all 0s and seqid == 1, set
2390 		 * the stateid to the current stateid, if it is set.
2391 		 */
2392 		if ((nd->nd_flag & ND_NFSV41) != 0 &&
2393 		    stp->ls_stateid.seqid == 1 &&
2394 		    stp->ls_stateid.other[0] == 0 &&
2395 		    stp->ls_stateid.other[1] == 0 &&
2396 		    stp->ls_stateid.other[2] == 0) {
2397 			if ((nd->nd_flag & ND_CURSTATEID) != 0) {
2398 				stp->ls_stateid = nd->nd_curstateid;
2399 				stp->ls_stateid.seqid = 0;
2400 			} else {
2401 				nd->nd_repstat = NFSERR_BADSTATEID;
2402 				goto nfsmout;
2403 			}
2404 		}
2405 
2406 		stp->ls_opentolockseq = fxdr_unsigned(int, *tl++);
2407 		clientid.lval[0] = *tl++;
2408 		clientid.lval[1] = *tl++;
2409 		if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
2410 			if ((nd->nd_flag & ND_NFSV41) != 0)
2411 				clientid.qval = nd->nd_clientid.qval;
2412 			else if (nd->nd_clientid.qval != clientid.qval)
2413 				printf("EEK3 multiple clids\n");
2414 		} else {
2415 			if ((nd->nd_flag & ND_NFSV41) != 0)
2416 				printf("EEK! no clientid from session\n");
2417 			nd->nd_flag |= ND_IMPLIEDCLID;
2418 			nd->nd_clientid.qval = clientid.qval;
2419 		}
2420 		error = nfsrv_mtostr(nd, stp->ls_owner, stp->ls_ownerlen);
2421 		if (error)
2422 			goto nfsmout;
2423 	} else {
2424 		NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + NFSX_UNSIGNED);
2425 		stp = malloc(sizeof (struct nfsstate),
2426 			M_NFSDSTATE, M_WAITOK);
2427 		stp->ls_ownerlen = 0;
2428 		stp->ls_op = nd->nd_rp;
2429 		stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
2430 		NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
2431 			NFSX_STATEIDOTHER);
2432 		tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
2433 
2434 		/*
2435 		 * For the special stateid of other all 0s and seqid == 1, set
2436 		 * the stateid to the current stateid, if it is set.
2437 		 */
2438 		if ((nd->nd_flag & ND_NFSV41) != 0 &&
2439 		    stp->ls_stateid.seqid == 1 &&
2440 		    stp->ls_stateid.other[0] == 0 &&
2441 		    stp->ls_stateid.other[1] == 0 &&
2442 		    stp->ls_stateid.other[2] == 0) {
2443 			if ((nd->nd_flag & ND_CURSTATEID) != 0) {
2444 				stp->ls_stateid = nd->nd_curstateid;
2445 				stp->ls_stateid.seqid = 0;
2446 			} else {
2447 				nd->nd_repstat = NFSERR_BADSTATEID;
2448 				goto nfsmout;
2449 			}
2450 		}
2451 
2452 		stp->ls_seq = fxdr_unsigned(int, *tl);
2453 		clientid.lval[0] = stp->ls_stateid.other[0];
2454 		clientid.lval[1] = stp->ls_stateid.other[1];
2455 		if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
2456 			if ((nd->nd_flag & ND_NFSV41) != 0)
2457 				clientid.qval = nd->nd_clientid.qval;
2458 			else if (nd->nd_clientid.qval != clientid.qval)
2459 				printf("EEK4 multiple clids\n");
2460 		} else {
2461 			if ((nd->nd_flag & ND_NFSV41) != 0)
2462 				printf("EEK! no clientid from session\n");
2463 			nd->nd_flag |= ND_IMPLIEDCLID;
2464 			nd->nd_clientid.qval = clientid.qval;
2465 		}
2466 	}
2467 	lop = malloc(sizeof (struct nfslock),
2468 		M_NFSDLOCK, M_WAITOK);
2469 	lop->lo_first = offset;
2470 	if (len == NFS64BITSSET) {
2471 		lop->lo_end = NFS64BITSSET;
2472 	} else {
2473 		lop->lo_end = offset + len;
2474 		if (lop->lo_end <= lop->lo_first)
2475 			nd->nd_repstat = NFSERR_INVAL;
2476 	}
2477 	lop->lo_flags = lflags;
2478 	stp->ls_flags = flags;
2479 	stp->ls_uid = nd->nd_cred->cr_uid;
2480 
2481 	/*
2482 	 * Do basic access checking.
2483 	 */
2484 	if (!nd->nd_repstat && vnode_vtype(vp) != VREG) {
2485 	    if (vnode_vtype(vp) == VDIR)
2486 		nd->nd_repstat = NFSERR_ISDIR;
2487 	    else
2488 		nd->nd_repstat = NFSERR_INVAL;
2489 	}
2490 	if (!nd->nd_repstat) {
2491 	    if (lflags & NFSLCK_WRITE) {
2492 		nd->nd_repstat = nfsvno_accchk(vp, VWRITE,
2493 		    nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER,
2494 		    NFSACCCHK_VPISLOCKED, NULL);
2495 	    } else {
2496 		nd->nd_repstat = nfsvno_accchk(vp, VREAD,
2497 		    nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER,
2498 		    NFSACCCHK_VPISLOCKED, NULL);
2499 		if (nd->nd_repstat)
2500 		    nd->nd_repstat = nfsvno_accchk(vp, VEXEC,
2501 			nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER,
2502 			NFSACCCHK_VPISLOCKED, NULL);
2503 	    }
2504 	}
2505 
2506 	/*
2507 	 * We call nfsrv_lockctrl() even if nd_repstat set, so that the
2508 	 * seqid# gets updated. nfsrv_lockctrl() will return the value
2509 	 * of nd_repstat, if it gets that far.
2510 	 */
2511 	nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, &cf, clientid,
2512 		&stateid, exp, nd, p);
2513 	if (lop)
2514 		free(lop, M_NFSDLOCK);
2515 	if (stp)
2516 		free(stp, M_NFSDSTATE);
2517 	if (!nd->nd_repstat) {
2518 		/* For NFSv4.1, set the Current StateID. */
2519 		if ((nd->nd_flag & ND_NFSV41) != 0) {
2520 			nd->nd_curstateid = stateid;
2521 			nd->nd_flag |= ND_CURSTATEID;
2522 		}
2523 		NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
2524 		*tl++ = txdr_unsigned(stateid.seqid);
2525 		NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
2526 	} else if (nd->nd_repstat == NFSERR_DENIED) {
2527 		NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
2528 		txdr_hyper(cf.cl_first, tl);
2529 		tl += 2;
2530 		if (cf.cl_end == NFS64BITSSET)
2531 			len = NFS64BITSSET;
2532 		else
2533 			len = cf.cl_end - cf.cl_first;
2534 		txdr_hyper(len, tl);
2535 		tl += 2;
2536 		if (cf.cl_flags == NFSLCK_WRITE)
2537 			*tl++ = txdr_unsigned(NFSV4LOCKT_WRITE);
2538 		else
2539 			*tl++ = txdr_unsigned(NFSV4LOCKT_READ);
2540 		*tl++ = stateid.other[0];
2541 		*tl = stateid.other[1];
2542 		(void) nfsm_strtom(nd, cf.cl_owner, cf.cl_ownerlen);
2543 	}
2544 	vput(vp);
2545 	NFSEXITCODE2(0, nd);
2546 	return (0);
2547 nfsmout:
2548 	vput(vp);
2549 	if (stp)
2550 		free(stp, M_NFSDSTATE);
2551 	NFSEXITCODE2(error, nd);
2552 	return (error);
2553 }
2554 
2555 /*
2556  * nfsv4 lock test service
2557  */
2558 int
2559 nfsrvd_lockt(struct nfsrv_descript *nd, __unused int isdgram,
2560     vnode_t vp, struct nfsexstuff *exp)
2561 {
2562 	u_int32_t *tl;
2563 	int i;
2564 	struct nfsstate *stp = NULL;
2565 	struct nfslock lo, *lop = &lo;
2566 	struct nfslockconflict cf;
2567 	int error = 0;
2568 	nfsv4stateid_t stateid;
2569 	nfsquad_t clientid;
2570 	u_int64_t len;
2571 	struct thread *p = curthread;
2572 
2573 	NFSM_DISSECT(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
2574 	i = fxdr_unsigned(int, *(tl + 7));
2575 	if (i <= 0 || i > NFSV4_OPAQUELIMIT) {
2576 		nd->nd_repstat = NFSERR_BADXDR;
2577 		goto nfsmout;
2578 	}
2579 	stp = malloc(sizeof (struct nfsstate) + i,
2580 	    M_NFSDSTATE, M_WAITOK);
2581 	stp->ls_ownerlen = i;
2582 	stp->ls_op = NULL;
2583 	stp->ls_flags = NFSLCK_TEST;
2584 	stp->ls_uid = nd->nd_cred->cr_uid;
2585 	i = fxdr_unsigned(int, *tl++);
2586 	switch (i) {
2587 	case NFSV4LOCKT_READW:
2588 		stp->ls_flags |= NFSLCK_BLOCKING;
2589 	case NFSV4LOCKT_READ:
2590 		lo.lo_flags = NFSLCK_READ;
2591 		break;
2592 	case NFSV4LOCKT_WRITEW:
2593 		stp->ls_flags |= NFSLCK_BLOCKING;
2594 	case NFSV4LOCKT_WRITE:
2595 		lo.lo_flags = NFSLCK_WRITE;
2596 		break;
2597 	default:
2598 		nd->nd_repstat = NFSERR_BADXDR;
2599 		goto nfsmout;
2600 	}
2601 	lo.lo_first = fxdr_hyper(tl);
2602 	tl += 2;
2603 	len = fxdr_hyper(tl);
2604 	if (len == NFS64BITSSET) {
2605 		lo.lo_end = NFS64BITSSET;
2606 	} else {
2607 		lo.lo_end = lo.lo_first + len;
2608 		if (lo.lo_end <= lo.lo_first)
2609 			nd->nd_repstat = NFSERR_INVAL;
2610 	}
2611 	tl += 2;
2612 	clientid.lval[0] = *tl++;
2613 	clientid.lval[1] = *tl;
2614 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
2615 		if ((nd->nd_flag & ND_NFSV41) != 0)
2616 			clientid.qval = nd->nd_clientid.qval;
2617 		else if (nd->nd_clientid.qval != clientid.qval)
2618 			printf("EEK5 multiple clids\n");
2619 	} else {
2620 		if ((nd->nd_flag & ND_NFSV41) != 0)
2621 			printf("EEK! no clientid from session\n");
2622 		nd->nd_flag |= ND_IMPLIEDCLID;
2623 		nd->nd_clientid.qval = clientid.qval;
2624 	}
2625 	error = nfsrv_mtostr(nd, stp->ls_owner, stp->ls_ownerlen);
2626 	if (error)
2627 		goto nfsmout;
2628 	if (!nd->nd_repstat && vnode_vtype(vp) != VREG) {
2629 	    if (vnode_vtype(vp) == VDIR)
2630 		nd->nd_repstat = NFSERR_ISDIR;
2631 	    else
2632 		nd->nd_repstat = NFSERR_INVAL;
2633 	}
2634 	if (!nd->nd_repstat)
2635 	  nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, &cf, clientid,
2636 	    &stateid, exp, nd, p);
2637 	if (nd->nd_repstat) {
2638 	    if (nd->nd_repstat == NFSERR_DENIED) {
2639 		NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
2640 		txdr_hyper(cf.cl_first, tl);
2641 		tl += 2;
2642 		if (cf.cl_end == NFS64BITSSET)
2643 			len = NFS64BITSSET;
2644 		else
2645 			len = cf.cl_end - cf.cl_first;
2646 		txdr_hyper(len, tl);
2647 		tl += 2;
2648 		if (cf.cl_flags == NFSLCK_WRITE)
2649 			*tl++ = txdr_unsigned(NFSV4LOCKT_WRITE);
2650 		else
2651 			*tl++ = txdr_unsigned(NFSV4LOCKT_READ);
2652 		*tl++ = stp->ls_stateid.other[0];
2653 		*tl = stp->ls_stateid.other[1];
2654 		(void) nfsm_strtom(nd, cf.cl_owner, cf.cl_ownerlen);
2655 	    }
2656 	}
2657 	vput(vp);
2658 	if (stp)
2659 		free(stp, M_NFSDSTATE);
2660 	NFSEXITCODE2(0, nd);
2661 	return (0);
2662 nfsmout:
2663 	vput(vp);
2664 	if (stp)
2665 		free(stp, M_NFSDSTATE);
2666 	NFSEXITCODE2(error, nd);
2667 	return (error);
2668 }
2669 
2670 /*
2671  * nfsv4 unlock service
2672  */
2673 int
2674 nfsrvd_locku(struct nfsrv_descript *nd, __unused int isdgram,
2675     vnode_t vp, struct nfsexstuff *exp)
2676 {
2677 	u_int32_t *tl;
2678 	int i;
2679 	struct nfsstate *stp;
2680 	struct nfslock *lop;
2681 	int error = 0;
2682 	nfsv4stateid_t stateid;
2683 	nfsquad_t clientid;
2684 	u_int64_t len;
2685 	struct thread *p = curthread;
2686 
2687 	NFSM_DISSECT(tl, u_int32_t *, 6 * NFSX_UNSIGNED + NFSX_STATEID);
2688 	stp = malloc(sizeof (struct nfsstate),
2689 	    M_NFSDSTATE, M_WAITOK);
2690 	lop = malloc(sizeof (struct nfslock),
2691 	    M_NFSDLOCK, M_WAITOK);
2692 	stp->ls_flags = NFSLCK_UNLOCK;
2693 	lop->lo_flags = NFSLCK_UNLOCK;
2694 	stp->ls_op = nd->nd_rp;
2695 	i = fxdr_unsigned(int, *tl++);
2696 	switch (i) {
2697 	case NFSV4LOCKT_READW:
2698 		stp->ls_flags |= NFSLCK_BLOCKING;
2699 	case NFSV4LOCKT_READ:
2700 		break;
2701 	case NFSV4LOCKT_WRITEW:
2702 		stp->ls_flags |= NFSLCK_BLOCKING;
2703 	case NFSV4LOCKT_WRITE:
2704 		break;
2705 	default:
2706 		nd->nd_repstat = NFSERR_BADXDR;
2707 		free(stp, M_NFSDSTATE);
2708 		free(lop, M_NFSDLOCK);
2709 		goto nfsmout;
2710 	}
2711 	stp->ls_ownerlen = 0;
2712 	stp->ls_uid = nd->nd_cred->cr_uid;
2713 	stp->ls_seq = fxdr_unsigned(int, *tl++);
2714 	stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
2715 	NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
2716 	    NFSX_STATEIDOTHER);
2717 	tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
2718 
2719 	/*
2720 	 * For the special stateid of other all 0s and seqid == 1, set the
2721 	 * stateid to the current stateid, if it is set.
2722 	 */
2723 	if ((nd->nd_flag & ND_NFSV41) != 0 && stp->ls_stateid.seqid == 1 &&
2724 	    stp->ls_stateid.other[0] == 0 && stp->ls_stateid.other[1] == 0 &&
2725 	    stp->ls_stateid.other[2] == 0) {
2726 		if ((nd->nd_flag & ND_CURSTATEID) != 0) {
2727 			stp->ls_stateid = nd->nd_curstateid;
2728 			stp->ls_stateid.seqid = 0;
2729 		} else {
2730 			nd->nd_repstat = NFSERR_BADSTATEID;
2731 			free(stp, M_NFSDSTATE);
2732 			free(lop, M_NFSDLOCK);
2733 			goto nfsmout;
2734 		}
2735 	}
2736 
2737 	lop->lo_first = fxdr_hyper(tl);
2738 	tl += 2;
2739 	len = fxdr_hyper(tl);
2740 	if (len == NFS64BITSSET) {
2741 		lop->lo_end = NFS64BITSSET;
2742 	} else {
2743 		lop->lo_end = lop->lo_first + len;
2744 		if (lop->lo_end <= lop->lo_first)
2745 			nd->nd_repstat = NFSERR_INVAL;
2746 	}
2747 	clientid.lval[0] = stp->ls_stateid.other[0];
2748 	clientid.lval[1] = stp->ls_stateid.other[1];
2749 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
2750 		if ((nd->nd_flag & ND_NFSV41) != 0)
2751 			clientid.qval = nd->nd_clientid.qval;
2752 		else if (nd->nd_clientid.qval != clientid.qval)
2753 			printf("EEK6 multiple clids\n");
2754 	} else {
2755 		if ((nd->nd_flag & ND_NFSV41) != 0)
2756 			printf("EEK! no clientid from session\n");
2757 		nd->nd_flag |= ND_IMPLIEDCLID;
2758 		nd->nd_clientid.qval = clientid.qval;
2759 	}
2760 	if (!nd->nd_repstat && vnode_vtype(vp) != VREG) {
2761 	    if (vnode_vtype(vp) == VDIR)
2762 		nd->nd_repstat = NFSERR_ISDIR;
2763 	    else
2764 		nd->nd_repstat = NFSERR_INVAL;
2765 	}
2766 	/*
2767 	 * Call nfsrv_lockctrl() even if nd_repstat is set, so that the
2768 	 * seqid# gets incremented. nfsrv_lockctrl() will return the
2769 	 * value of nd_repstat, if it gets that far.
2770 	 */
2771 	nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid,
2772 	    &stateid, exp, nd, p);
2773 	if (stp)
2774 		free(stp, M_NFSDSTATE);
2775 	if (lop)
2776 		free(lop, M_NFSDLOCK);
2777 	if (!nd->nd_repstat) {
2778 		NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
2779 		*tl++ = txdr_unsigned(stateid.seqid);
2780 		NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
2781 	}
2782 nfsmout:
2783 	vput(vp);
2784 	NFSEXITCODE2(error, nd);
2785 	return (error);
2786 }
2787 
2788 /*
2789  * nfsv4 open service
2790  */
2791 int
2792 nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
2793     vnode_t dp, vnode_t *vpp, __unused fhandle_t *fhp, struct nfsexstuff *exp)
2794 {
2795 	u_int32_t *tl;
2796 	int i, retext;
2797 	struct nfsstate *stp = NULL;
2798 	int error = 0, create, claim, exclusive_flag = 0, override;
2799 	u_int32_t rflags = NFSV4OPEN_LOCKTYPEPOSIX, acemask;
2800 	int how = NFSCREATE_UNCHECKED;
2801 	int32_t cverf[2], tverf[2] = { 0, 0 };
2802 	vnode_t vp = NULL, dirp = NULL;
2803 	struct nfsvattr nva, dirfor, diraft;
2804 	struct nameidata named;
2805 	nfsv4stateid_t stateid, delegstateid;
2806 	nfsattrbit_t attrbits;
2807 	nfsquad_t clientid;
2808 	char *bufp = NULL;
2809 	u_long *hashp;
2810 	NFSACL_T *aclp = NULL;
2811 	struct thread *p = curthread;
2812 
2813 #ifdef NFS4_ACL_EXTATTR_NAME
2814 	aclp = acl_alloc(M_WAITOK);
2815 	aclp->acl_cnt = 0;
2816 #endif
2817 	NFSZERO_ATTRBIT(&attrbits);
2818 	named.ni_startdir = NULL;
2819 	named.ni_cnd.cn_nameiop = 0;
2820 	NFSM_DISSECT(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
2821 	i = fxdr_unsigned(int, *(tl + 5));
2822 	if (i <= 0 || i > NFSV4_OPAQUELIMIT) {
2823 		nd->nd_repstat = NFSERR_BADXDR;
2824 		goto nfsmout;
2825 	}
2826 	stp = malloc(sizeof (struct nfsstate) + i,
2827 	    M_NFSDSTATE, M_WAITOK);
2828 	stp->ls_ownerlen = i;
2829 	stp->ls_op = nd->nd_rp;
2830 	stp->ls_flags = NFSLCK_OPEN;
2831 	stp->ls_uid = nd->nd_cred->cr_uid;
2832 	stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++);
2833 	i = fxdr_unsigned(int, *tl++);
2834 	retext = 0;
2835 	if ((i & (NFSV4OPEN_WANTDELEGMASK | NFSV4OPEN_WANTSIGNALDELEG |
2836 	    NFSV4OPEN_WANTPUSHDELEG)) != 0 && (nd->nd_flag & ND_NFSV41) != 0) {
2837 		retext = 1;
2838 		/* For now, ignore these. */
2839 		i &= ~(NFSV4OPEN_WANTPUSHDELEG | NFSV4OPEN_WANTSIGNALDELEG);
2840 		switch (i & NFSV4OPEN_WANTDELEGMASK) {
2841 		case NFSV4OPEN_WANTANYDELEG:
2842 			stp->ls_flags |= (NFSLCK_WANTRDELEG |
2843 			    NFSLCK_WANTWDELEG);
2844 			i &= ~NFSV4OPEN_WANTDELEGMASK;
2845 			break;
2846 		case NFSV4OPEN_WANTREADDELEG:
2847 			stp->ls_flags |= NFSLCK_WANTRDELEG;
2848 			i &= ~NFSV4OPEN_WANTDELEGMASK;
2849 			break;
2850 		case NFSV4OPEN_WANTWRITEDELEG:
2851 			stp->ls_flags |= NFSLCK_WANTWDELEG;
2852 			i &= ~NFSV4OPEN_WANTDELEGMASK;
2853 			break;
2854 		case NFSV4OPEN_WANTNODELEG:
2855 			stp->ls_flags |= NFSLCK_WANTNODELEG;
2856 			i &= ~NFSV4OPEN_WANTDELEGMASK;
2857 			break;
2858 		case NFSV4OPEN_WANTCANCEL:
2859 			printf("NFSv4: ignore Open WantCancel\n");
2860 			i &= ~NFSV4OPEN_WANTDELEGMASK;
2861 			break;
2862 		default:
2863 			/* nd_repstat will be set to NFSERR_INVAL below. */
2864 			break;
2865 		}
2866 	}
2867 	switch (i) {
2868 	case NFSV4OPEN_ACCESSREAD:
2869 		stp->ls_flags |= NFSLCK_READACCESS;
2870 		break;
2871 	case NFSV4OPEN_ACCESSWRITE:
2872 		stp->ls_flags |= NFSLCK_WRITEACCESS;
2873 		break;
2874 	case NFSV4OPEN_ACCESSBOTH:
2875 		stp->ls_flags |= (NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
2876 		break;
2877 	default:
2878 		nd->nd_repstat = NFSERR_INVAL;
2879 	}
2880 	i = fxdr_unsigned(int, *tl++);
2881 	switch (i) {
2882 	case NFSV4OPEN_DENYNONE:
2883 		break;
2884 	case NFSV4OPEN_DENYREAD:
2885 		stp->ls_flags |= NFSLCK_READDENY;
2886 		break;
2887 	case NFSV4OPEN_DENYWRITE:
2888 		stp->ls_flags |= NFSLCK_WRITEDENY;
2889 		break;
2890 	case NFSV4OPEN_DENYBOTH:
2891 		stp->ls_flags |= (NFSLCK_READDENY | NFSLCK_WRITEDENY);
2892 		break;
2893 	default:
2894 		nd->nd_repstat = NFSERR_INVAL;
2895 	}
2896 	clientid.lval[0] = *tl++;
2897 	clientid.lval[1] = *tl;
2898 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
2899 		if ((nd->nd_flag & ND_NFSV41) != 0)
2900 			clientid.qval = nd->nd_clientid.qval;
2901 		else if (nd->nd_clientid.qval != clientid.qval)
2902 			printf("EEK7 multiple clids\n");
2903 	} else {
2904 		if ((nd->nd_flag & ND_NFSV41) != 0)
2905 			printf("EEK! no clientid from session\n");
2906 		nd->nd_flag |= ND_IMPLIEDCLID;
2907 		nd->nd_clientid.qval = clientid.qval;
2908 	}
2909 	error = nfsrv_mtostr(nd, stp->ls_owner, stp->ls_ownerlen);
2910 	if (error)
2911 		goto nfsmout;
2912 	NFSVNO_ATTRINIT(&nva);
2913 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2914 	create = fxdr_unsigned(int, *tl);
2915 	if (!nd->nd_repstat)
2916 		nd->nd_repstat = nfsvno_getattr(dp, &dirfor, nd, p, 0, NULL);
2917 	if (create == NFSV4OPEN_CREATE) {
2918 		nva.na_type = VREG;
2919 		nva.na_mode = 0;
2920 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2921 		how = fxdr_unsigned(int, *tl);
2922 		switch (how) {
2923 		case NFSCREATE_UNCHECKED:
2924 		case NFSCREATE_GUARDED:
2925 			error = nfsv4_sattr(nd, NULL, &nva, &attrbits, aclp, p);
2926 			if (error)
2927 				goto nfsmout;
2928 			/*
2929 			 * If the na_gid being set is the same as that of
2930 			 * the directory it is going in, clear it, since
2931 			 * that is what will be set by default. This allows
2932 			 * a user that isn't in that group to do the create.
2933 			 */
2934 			if (!nd->nd_repstat && NFSVNO_ISSETGID(&nva) &&
2935 			    nva.na_gid == dirfor.na_gid)
2936 				NFSVNO_UNSET(&nva, gid);
2937 			if (!nd->nd_repstat)
2938 				nd->nd_repstat = nfsrv_checkuidgid(nd, &nva);
2939 			break;
2940 		case NFSCREATE_EXCLUSIVE:
2941 			NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF);
2942 			cverf[0] = *tl++;
2943 			cverf[1] = *tl;
2944 			break;
2945 		case NFSCREATE_EXCLUSIVE41:
2946 			NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF);
2947 			cverf[0] = *tl++;
2948 			cverf[1] = *tl;
2949 			error = nfsv4_sattr(nd, NULL, &nva, &attrbits, aclp, p);
2950 			if (error != 0)
2951 				goto nfsmout;
2952 			if (NFSISSET_ATTRBIT(&attrbits,
2953 			    NFSATTRBIT_TIMEACCESSSET))
2954 				nd->nd_repstat = NFSERR_INVAL;
2955 			/*
2956 			 * If the na_gid being set is the same as that of
2957 			 * the directory it is going in, clear it, since
2958 			 * that is what will be set by default. This allows
2959 			 * a user that isn't in that group to do the create.
2960 			 */
2961 			if (nd->nd_repstat == 0 && NFSVNO_ISSETGID(&nva) &&
2962 			    nva.na_gid == dirfor.na_gid)
2963 				NFSVNO_UNSET(&nva, gid);
2964 			if (nd->nd_repstat == 0)
2965 				nd->nd_repstat = nfsrv_checkuidgid(nd, &nva);
2966 			break;
2967 		default:
2968 			nd->nd_repstat = NFSERR_BADXDR;
2969 			goto nfsmout;
2970 		}
2971 	} else if (create != NFSV4OPEN_NOCREATE) {
2972 		nd->nd_repstat = NFSERR_BADXDR;
2973 		goto nfsmout;
2974 	}
2975 
2976 	/*
2977 	 * Now, handle the claim, which usually includes looking up a
2978 	 * name in the directory referenced by dp. The exception is
2979 	 * NFSV4OPEN_CLAIMPREVIOUS.
2980 	 */
2981 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2982 	claim = fxdr_unsigned(int, *tl);
2983 	if (claim == NFSV4OPEN_CLAIMDELEGATECUR || claim ==
2984 	    NFSV4OPEN_CLAIMDELEGATECURFH) {
2985 		NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
2986 		stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
2987 		NFSBCOPY((caddr_t)tl,(caddr_t)stateid.other,NFSX_STATEIDOTHER);
2988 		stp->ls_flags |= NFSLCK_DELEGCUR;
2989 	} else if (claim == NFSV4OPEN_CLAIMDELEGATEPREV || claim ==
2990 	    NFSV4OPEN_CLAIMDELEGATEPREVFH) {
2991 		stp->ls_flags |= NFSLCK_DELEGPREV;
2992 	}
2993 	if (claim == NFSV4OPEN_CLAIMNULL || claim == NFSV4OPEN_CLAIMDELEGATECUR
2994 	    || claim == NFSV4OPEN_CLAIMDELEGATEPREV) {
2995 		if (!nd->nd_repstat && create == NFSV4OPEN_CREATE &&
2996 		    claim != NFSV4OPEN_CLAIMNULL)
2997 			nd->nd_repstat = NFSERR_INVAL;
2998 		if (nd->nd_repstat) {
2999 			nd->nd_repstat = nfsrv_opencheck(clientid,
3000 			    &stateid, stp, NULL, nd, p, nd->nd_repstat);
3001 			goto nfsmout;
3002 		}
3003 		if (create == NFSV4OPEN_CREATE)
3004 		    NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
3005 			LOCKPARENT | LOCKLEAF | SAVESTART | NOCACHE);
3006 		else
3007 		    NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP,
3008 			LOCKLEAF | SAVESTART);
3009 		nfsvno_setpathbuf(&named, &bufp, &hashp);
3010 		error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
3011 		if (error) {
3012 			vrele(dp);
3013 #ifdef NFS4_ACL_EXTATTR_NAME
3014 			acl_free(aclp);
3015 #endif
3016 			free(stp, M_NFSDSTATE);
3017 			nfsvno_relpathbuf(&named);
3018 			NFSEXITCODE2(error, nd);
3019 			return (error);
3020 		}
3021 		if (!nd->nd_repstat) {
3022 			nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp,
3023 			    p, &dirp);
3024 		} else {
3025 			vrele(dp);
3026 			nfsvno_relpathbuf(&named);
3027 		}
3028 		if (create == NFSV4OPEN_CREATE) {
3029 		    switch (how) {
3030 		    case NFSCREATE_UNCHECKED:
3031 			if (named.ni_vp) {
3032 				/*
3033 				 * Clear the setable attribute bits, except
3034 				 * for Size, if it is being truncated.
3035 				 */
3036 				NFSZERO_ATTRBIT(&attrbits);
3037 				if (NFSVNO_ISSETSIZE(&nva))
3038 					NFSSETBIT_ATTRBIT(&attrbits,
3039 					    NFSATTRBIT_SIZE);
3040 			}
3041 			break;
3042 		    case NFSCREATE_GUARDED:
3043 			if (named.ni_vp && !nd->nd_repstat)
3044 				nd->nd_repstat = EEXIST;
3045 			break;
3046 		    case NFSCREATE_EXCLUSIVE:
3047 			exclusive_flag = 1;
3048 			if (!named.ni_vp)
3049 				nva.na_mode = 0;
3050 			break;
3051 		    case NFSCREATE_EXCLUSIVE41:
3052 			exclusive_flag = 1;
3053 			break;
3054 		    }
3055 		}
3056 		nfsvno_open(nd, &named, clientid, &stateid, stp,
3057 		    &exclusive_flag, &nva, cverf, create, aclp, &attrbits,
3058 		    nd->nd_cred, exp, &vp);
3059 	} else if (claim == NFSV4OPEN_CLAIMPREVIOUS || claim ==
3060 	    NFSV4OPEN_CLAIMFH || claim == NFSV4OPEN_CLAIMDELEGATECURFH ||
3061 	    claim == NFSV4OPEN_CLAIMDELEGATEPREVFH) {
3062 		if (claim == NFSV4OPEN_CLAIMPREVIOUS) {
3063 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
3064 			i = fxdr_unsigned(int, *tl);
3065 			switch (i) {
3066 			case NFSV4OPEN_DELEGATEREAD:
3067 				stp->ls_flags |= NFSLCK_DELEGREAD;
3068 				break;
3069 			case NFSV4OPEN_DELEGATEWRITE:
3070 				stp->ls_flags |= NFSLCK_DELEGWRITE;
3071 			case NFSV4OPEN_DELEGATENONE:
3072 				break;
3073 			default:
3074 				nd->nd_repstat = NFSERR_BADXDR;
3075 				goto nfsmout;
3076 			}
3077 			stp->ls_flags |= NFSLCK_RECLAIM;
3078 		} else {
3079 			if (nd->nd_repstat == 0 && create == NFSV4OPEN_CREATE)
3080 				nd->nd_repstat = NFSERR_INVAL;
3081 		}
3082 		vp = dp;
3083 		NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
3084 		if (!VN_IS_DOOMED(vp))
3085 			nd->nd_repstat = nfsrv_opencheck(clientid, &stateid,
3086 			    stp, vp, nd, p, nd->nd_repstat);
3087 		else
3088 			nd->nd_repstat = NFSERR_PERM;
3089 	} else {
3090 		nd->nd_repstat = NFSERR_BADXDR;
3091 		goto nfsmout;
3092 	}
3093 
3094 	/*
3095 	 * Do basic access checking.
3096 	 */
3097 	if (!nd->nd_repstat && vnode_vtype(vp) != VREG) {
3098 		/*
3099 		 * The IETF working group decided that this is the correct
3100 		 * error return for all non-regular files.
3101 		 */
3102 		nd->nd_repstat = (vp->v_type == VDIR) ? NFSERR_ISDIR : NFSERR_SYMLINK;
3103 	}
3104 
3105 	/*
3106 	 * If the Open is being done for a file that already exists, apply
3107 	 * normal permission checking including for the file owner, if
3108 	 * vfs.nfsd.v4openaccess is set.
3109 	 * Previously, the owner was always allowed to open the file to
3110 	 * be consistent with the NFS tradition of always allowing the
3111 	 * owner of the file to write to the file regardless of permissions.
3112 	 * It now appears that the Linux client expects the owner
3113 	 * permissions to be checked for opens that are not creating the
3114 	 * file.  I believe the correct approach is to use the Access
3115 	 * operation's results to be consistent with NFSv3, but that is
3116 	 * not what the current Linux client appears to be doing.
3117 	 * Since both the Linux and OpenSolaris NFSv4 servers do this check,
3118 	 * I have enabled it by default.
3119 	 * If this semantic change causes a problem, it can be disabled by
3120 	 * setting the sysctl vfs.nfsd.v4openaccess to 0 to re-enable the
3121 	 * previous semantics.
3122 	 */
3123 	if (nfsrv_openaccess && create == NFSV4OPEN_NOCREATE)
3124 		override = NFSACCCHK_NOOVERRIDE;
3125 	else
3126 		override = NFSACCCHK_ALLOWOWNER;
3127 	if (!nd->nd_repstat && (stp->ls_flags & NFSLCK_WRITEACCESS))
3128 	    nd->nd_repstat = nfsvno_accchk(vp, VWRITE, nd->nd_cred,
3129 	        exp, p, override, NFSACCCHK_VPISLOCKED, NULL);
3130 	if (!nd->nd_repstat && (stp->ls_flags & NFSLCK_READACCESS)) {
3131 	    nd->nd_repstat = nfsvno_accchk(vp, VREAD, nd->nd_cred,
3132 	        exp, p, override, NFSACCCHK_VPISLOCKED, NULL);
3133 	    if (nd->nd_repstat)
3134 		nd->nd_repstat = nfsvno_accchk(vp, VEXEC,
3135 		    nd->nd_cred, exp, p, override,
3136 		    NFSACCCHK_VPISLOCKED, NULL);
3137 	}
3138 
3139 	if (!nd->nd_repstat) {
3140 		nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
3141 		if (!nd->nd_repstat) {
3142 			tverf[0] = nva.na_atime.tv_sec;
3143 			tverf[1] = nva.na_atime.tv_nsec;
3144 		}
3145 	}
3146 	if (!nd->nd_repstat && exclusive_flag && (cverf[0] != tverf[0] ||
3147 	    cverf[1] != tverf[1]))
3148 		nd->nd_repstat = EEXIST;
3149 	/*
3150 	 * Do the open locking/delegation stuff.
3151 	 */
3152 	if (!nd->nd_repstat)
3153 	    nd->nd_repstat = nfsrv_openctrl(nd, vp, &stp, clientid, &stateid,
3154 		&delegstateid, &rflags, exp, p, nva.na_filerev);
3155 
3156 	/*
3157 	 * vp must be unlocked before the call to nfsvno_getattr(dirp,...)
3158 	 * below, to avoid a deadlock with the lookup in nfsvno_namei() above.
3159 	 * (ie: Leave the NFSVOPUNLOCK() about here.)
3160 	 */
3161 	if (vp)
3162 		NFSVOPUNLOCK(vp);
3163 	if (stp)
3164 		free(stp, M_NFSDSTATE);
3165 	if (!nd->nd_repstat && dirp)
3166 		nd->nd_repstat = nfsvno_getattr(dirp, &diraft, nd, p, 0, NULL);
3167 	if (!nd->nd_repstat) {
3168 		/* For NFSv4.1, set the Current StateID. */
3169 		if ((nd->nd_flag & ND_NFSV41) != 0) {
3170 			nd->nd_curstateid = stateid;
3171 			nd->nd_flag |= ND_CURSTATEID;
3172 		}
3173 		NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID + 6 * NFSX_UNSIGNED);
3174 		*tl++ = txdr_unsigned(stateid.seqid);
3175 		NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
3176 		tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
3177 		if (claim == NFSV4OPEN_CLAIMPREVIOUS) {
3178 			*tl++ = newnfs_true;
3179 			*tl++ = 0;
3180 			*tl++ = 0;
3181 			*tl++ = 0;
3182 			*tl++ = 0;
3183 		} else {
3184 			*tl++ = newnfs_false;	/* Since dirp is not locked */
3185 			txdr_hyper(dirfor.na_filerev, tl);
3186 			tl += 2;
3187 			txdr_hyper(diraft.na_filerev, tl);
3188 			tl += 2;
3189 		}
3190 		*tl = txdr_unsigned(rflags & NFSV4OPEN_RFLAGS);
3191 		(void) nfsrv_putattrbit(nd, &attrbits);
3192 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3193 		if (rflags & NFSV4OPEN_READDELEGATE)
3194 			*tl = txdr_unsigned(NFSV4OPEN_DELEGATEREAD);
3195 		else if (rflags & NFSV4OPEN_WRITEDELEGATE)
3196 			*tl = txdr_unsigned(NFSV4OPEN_DELEGATEWRITE);
3197 		else if (retext != 0) {
3198 			*tl = txdr_unsigned(NFSV4OPEN_DELEGATENONEEXT);
3199 			if ((rflags & NFSV4OPEN_WDNOTWANTED) != 0) {
3200 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3201 				*tl = txdr_unsigned(NFSV4OPEN_NOTWANTED);
3202 			} else if ((rflags & NFSV4OPEN_WDSUPPFTYPE) != 0) {
3203 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3204 				*tl = txdr_unsigned(NFSV4OPEN_NOTSUPPFTYPE);
3205 			} else if ((rflags & NFSV4OPEN_WDCONTENTION) != 0) {
3206 				NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
3207 				*tl++ = txdr_unsigned(NFSV4OPEN_CONTENTION);
3208 				*tl = newnfs_false;
3209 			} else if ((rflags & NFSV4OPEN_WDRESOURCE) != 0) {
3210 				NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
3211 				*tl++ = txdr_unsigned(NFSV4OPEN_RESOURCE);
3212 				*tl = newnfs_false;
3213 			} else {
3214 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3215 				*tl = txdr_unsigned(NFSV4OPEN_NOTWANTED);
3216 			}
3217 		} else
3218 			*tl = txdr_unsigned(NFSV4OPEN_DELEGATENONE);
3219 		if (rflags & (NFSV4OPEN_READDELEGATE|NFSV4OPEN_WRITEDELEGATE)) {
3220 			NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID+NFSX_UNSIGNED);
3221 			*tl++ = txdr_unsigned(delegstateid.seqid);
3222 			NFSBCOPY((caddr_t)delegstateid.other, (caddr_t)tl,
3223 			    NFSX_STATEIDOTHER);
3224 			tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
3225 			if (rflags & NFSV4OPEN_RECALL)
3226 				*tl = newnfs_true;
3227 			else
3228 				*tl = newnfs_false;
3229 			if (rflags & NFSV4OPEN_WRITEDELEGATE) {
3230 				NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
3231 				*tl++ = txdr_unsigned(NFSV4OPEN_LIMITSIZE);
3232 				txdr_hyper(nva.na_size, tl);
3233 			}
3234 			NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
3235 			*tl++ = txdr_unsigned(NFSV4ACE_ALLOWEDTYPE);
3236 			*tl++ = txdr_unsigned(0x0);
3237 			acemask = NFSV4ACE_ALLFILESMASK;
3238 			if (nva.na_mode & S_IRUSR)
3239 			    acemask |= NFSV4ACE_READMASK;
3240 			if (nva.na_mode & S_IWUSR)
3241 			    acemask |= NFSV4ACE_WRITEMASK;
3242 			if (nva.na_mode & S_IXUSR)
3243 			    acemask |= NFSV4ACE_EXECUTEMASK;
3244 			*tl = txdr_unsigned(acemask);
3245 			(void) nfsm_strtom(nd, "OWNER@", 6);
3246 		}
3247 		*vpp = vp;
3248 	} else if (vp) {
3249 		vrele(vp);
3250 	}
3251 	if (dirp)
3252 		vrele(dirp);
3253 #ifdef NFS4_ACL_EXTATTR_NAME
3254 	acl_free(aclp);
3255 #endif
3256 	NFSEXITCODE2(0, nd);
3257 	return (0);
3258 nfsmout:
3259 	vrele(dp);
3260 #ifdef NFS4_ACL_EXTATTR_NAME
3261 	acl_free(aclp);
3262 #endif
3263 	if (stp)
3264 		free(stp, M_NFSDSTATE);
3265 	NFSEXITCODE2(error, nd);
3266 	return (error);
3267 }
3268 
3269 /*
3270  * nfsv4 close service
3271  */
3272 int
3273 nfsrvd_close(struct nfsrv_descript *nd, __unused int isdgram,
3274     vnode_t vp, __unused struct nfsexstuff *exp)
3275 {
3276 	u_int32_t *tl;
3277 	struct nfsstate st, *stp = &st;
3278 	int error = 0, writeacc;
3279 	nfsv4stateid_t stateid;
3280 	nfsquad_t clientid;
3281 	struct nfsvattr na;
3282 	struct thread *p = curthread;
3283 
3284 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID);
3285 	stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++);
3286 	stp->ls_ownerlen = 0;
3287 	stp->ls_op = nd->nd_rp;
3288 	stp->ls_uid = nd->nd_cred->cr_uid;
3289 	stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
3290 	NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
3291 	    NFSX_STATEIDOTHER);
3292 
3293 	/*
3294 	 * For the special stateid of other all 0s and seqid == 1, set the
3295 	 * stateid to the current stateid, if it is set.
3296 	 */
3297 	if ((nd->nd_flag & ND_NFSV41) != 0 && stp->ls_stateid.seqid == 1 &&
3298 	    stp->ls_stateid.other[0] == 0 && stp->ls_stateid.other[1] == 0 &&
3299 	    stp->ls_stateid.other[2] == 0) {
3300 		if ((nd->nd_flag & ND_CURSTATEID) != 0)
3301 			stp->ls_stateid = nd->nd_curstateid;
3302 		else {
3303 			nd->nd_repstat = NFSERR_BADSTATEID;
3304 			goto nfsmout;
3305 		}
3306 	}
3307 
3308 	stp->ls_flags = NFSLCK_CLOSE;
3309 	clientid.lval[0] = stp->ls_stateid.other[0];
3310 	clientid.lval[1] = stp->ls_stateid.other[1];
3311 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
3312 		if ((nd->nd_flag & ND_NFSV41) != 0)
3313 			clientid.qval = nd->nd_clientid.qval;
3314 		else if (nd->nd_clientid.qval != clientid.qval)
3315 			printf("EEK8 multiple clids\n");
3316 	} else {
3317 		if ((nd->nd_flag & ND_NFSV41) != 0)
3318 			printf("EEK! no clientid from session\n");
3319 		nd->nd_flag |= ND_IMPLIEDCLID;
3320 		nd->nd_clientid.qval = clientid.qval;
3321 	}
3322 	nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p,
3323 	    &writeacc);
3324 	/* For pNFS, update the attributes. */
3325 	if (writeacc != 0 || nfsrv_pnfsatime != 0)
3326 		nfsrv_updatemdsattr(vp, &na, p);
3327 	vput(vp);
3328 	if (!nd->nd_repstat) {
3329 		/*
3330 		 * If the stateid that has been closed is the current stateid,
3331 		 * unset it.
3332 		 */
3333 		if ((nd->nd_flag & ND_CURSTATEID) != 0 &&
3334 		    stateid.other[0] == nd->nd_curstateid.other[0] &&
3335 		    stateid.other[1] == nd->nd_curstateid.other[1] &&
3336 		    stateid.other[2] == nd->nd_curstateid.other[2])
3337 			nd->nd_flag &= ~ND_CURSTATEID;
3338 		NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
3339 		*tl++ = txdr_unsigned(stateid.seqid);
3340 		NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
3341 	}
3342 	NFSEXITCODE2(0, nd);
3343 	return (0);
3344 nfsmout:
3345 	vput(vp);
3346 	NFSEXITCODE2(error, nd);
3347 	return (error);
3348 }
3349 
3350 /*
3351  * nfsv4 delegpurge service
3352  */
3353 int
3354 nfsrvd_delegpurge(struct nfsrv_descript *nd, __unused int isdgram,
3355     __unused vnode_t vp, __unused struct nfsexstuff *exp)
3356 {
3357 	u_int32_t *tl;
3358 	int error = 0;
3359 	nfsquad_t clientid;
3360 	struct thread *p = curthread;
3361 
3362 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
3363 		goto nfsmout;
3364 	NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
3365 	clientid.lval[0] = *tl++;
3366 	clientid.lval[1] = *tl;
3367 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
3368 		if ((nd->nd_flag & ND_NFSV41) != 0)
3369 			clientid.qval = nd->nd_clientid.qval;
3370 		else if (nd->nd_clientid.qval != clientid.qval)
3371 			printf("EEK9 multiple clids\n");
3372 	} else {
3373 		if ((nd->nd_flag & ND_NFSV41) != 0)
3374 			printf("EEK! no clientid from session\n");
3375 		nd->nd_flag |= ND_IMPLIEDCLID;
3376 		nd->nd_clientid.qval = clientid.qval;
3377 	}
3378 	nd->nd_repstat = nfsrv_delegupdate(nd, clientid, NULL, NULL,
3379 	    NFSV4OP_DELEGPURGE, nd->nd_cred, p, NULL);
3380 nfsmout:
3381 	NFSEXITCODE2(error, nd);
3382 	return (error);
3383 }
3384 
3385 /*
3386  * nfsv4 delegreturn service
3387  */
3388 int
3389 nfsrvd_delegreturn(struct nfsrv_descript *nd, __unused int isdgram,
3390     vnode_t vp, __unused struct nfsexstuff *exp)
3391 {
3392 	u_int32_t *tl;
3393 	int error = 0, writeacc;
3394 	nfsv4stateid_t stateid;
3395 	nfsquad_t clientid;
3396 	struct nfsvattr na;
3397 	struct thread *p = curthread;
3398 
3399 	NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
3400 	stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
3401 	NFSBCOPY((caddr_t)tl, (caddr_t)stateid.other, NFSX_STATEIDOTHER);
3402 	clientid.lval[0] = stateid.other[0];
3403 	clientid.lval[1] = stateid.other[1];
3404 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
3405 		if ((nd->nd_flag & ND_NFSV41) != 0)
3406 			clientid.qval = nd->nd_clientid.qval;
3407 		else if (nd->nd_clientid.qval != clientid.qval)
3408 			printf("EEK10 multiple clids\n");
3409 	} else {
3410 		if ((nd->nd_flag & ND_NFSV41) != 0)
3411 			printf("EEK! no clientid from session\n");
3412 		nd->nd_flag |= ND_IMPLIEDCLID;
3413 		nd->nd_clientid.qval = clientid.qval;
3414 	}
3415 	nd->nd_repstat = nfsrv_delegupdate(nd, clientid, &stateid, vp,
3416 	    NFSV4OP_DELEGRETURN, nd->nd_cred, p, &writeacc);
3417 	/* For pNFS, update the attributes. */
3418 	if (writeacc != 0 || nfsrv_pnfsatime != 0)
3419 		nfsrv_updatemdsattr(vp, &na, p);
3420 nfsmout:
3421 	vput(vp);
3422 	NFSEXITCODE2(error, nd);
3423 	return (error);
3424 }
3425 
3426 /*
3427  * nfsv4 get file handle service
3428  */
3429 int
3430 nfsrvd_getfh(struct nfsrv_descript *nd, __unused int isdgram,
3431     vnode_t vp, __unused struct nfsexstuff *exp)
3432 {
3433 	fhandle_t fh;
3434 	struct thread *p = curthread;
3435 
3436 	nd->nd_repstat = nfsvno_getfh(vp, &fh, p);
3437 	vput(vp);
3438 	if (!nd->nd_repstat)
3439 		(void) nfsm_fhtom(nd, (u_int8_t *)&fh, 0, 0);
3440 	NFSEXITCODE2(0, nd);
3441 	return (0);
3442 }
3443 
3444 /*
3445  * nfsv4 open confirm service
3446  */
3447 int
3448 nfsrvd_openconfirm(struct nfsrv_descript *nd, __unused int isdgram,
3449     vnode_t vp, __unused struct nfsexstuff *exp)
3450 {
3451 	u_int32_t *tl;
3452 	struct nfsstate st, *stp = &st;
3453 	int error = 0;
3454 	nfsv4stateid_t stateid;
3455 	nfsquad_t clientid;
3456 	struct thread *p = curthread;
3457 
3458 	if ((nd->nd_flag & ND_NFSV41) != 0) {
3459 		nd->nd_repstat = NFSERR_NOTSUPP;
3460 		goto nfsmout;
3461 	}
3462 	NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + NFSX_UNSIGNED);
3463 	stp->ls_ownerlen = 0;
3464 	stp->ls_op = nd->nd_rp;
3465 	stp->ls_uid = nd->nd_cred->cr_uid;
3466 	stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
3467 	NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
3468 	    NFSX_STATEIDOTHER);
3469 	tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
3470 	stp->ls_seq = fxdr_unsigned(u_int32_t, *tl);
3471 	stp->ls_flags = NFSLCK_CONFIRM;
3472 	clientid.lval[0] = stp->ls_stateid.other[0];
3473 	clientid.lval[1] = stp->ls_stateid.other[1];
3474 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
3475 		if ((nd->nd_flag & ND_NFSV41) != 0)
3476 			clientid.qval = nd->nd_clientid.qval;
3477 		else if (nd->nd_clientid.qval != clientid.qval)
3478 			printf("EEK11 multiple clids\n");
3479 	} else {
3480 		if ((nd->nd_flag & ND_NFSV41) != 0)
3481 			printf("EEK! no clientid from session\n");
3482 		nd->nd_flag |= ND_IMPLIEDCLID;
3483 		nd->nd_clientid.qval = clientid.qval;
3484 	}
3485 	nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p,
3486 	    NULL);
3487 	if (!nd->nd_repstat) {
3488 		NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
3489 		*tl++ = txdr_unsigned(stateid.seqid);
3490 		NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
3491 	}
3492 nfsmout:
3493 	vput(vp);
3494 	NFSEXITCODE2(error, nd);
3495 	return (error);
3496 }
3497 
3498 /*
3499  * nfsv4 open downgrade service
3500  */
3501 int
3502 nfsrvd_opendowngrade(struct nfsrv_descript *nd, __unused int isdgram,
3503     vnode_t vp, __unused struct nfsexstuff *exp)
3504 {
3505 	u_int32_t *tl;
3506 	int i;
3507 	struct nfsstate st, *stp = &st;
3508 	int error = 0;
3509 	nfsv4stateid_t stateid;
3510 	nfsquad_t clientid;
3511 	struct thread *p = curthread;
3512 
3513 	/* opendowngrade can only work on a file object.*/
3514 	if (vp->v_type != VREG) {
3515 		error = NFSERR_INVAL;
3516 		goto nfsmout;
3517 	}
3518 	NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + 3 * NFSX_UNSIGNED);
3519 	stp->ls_ownerlen = 0;
3520 	stp->ls_op = nd->nd_rp;
3521 	stp->ls_uid = nd->nd_cred->cr_uid;
3522 	stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
3523 	NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
3524 	    NFSX_STATEIDOTHER);
3525 	tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
3526 
3527 	/*
3528 	 * For the special stateid of other all 0s and seqid == 1, set the
3529 	 * stateid to the current stateid, if it is set.
3530 	 */
3531 	if ((nd->nd_flag & ND_NFSV41) != 0 && stp->ls_stateid.seqid == 1 &&
3532 	    stp->ls_stateid.other[0] == 0 && stp->ls_stateid.other[1] == 0 &&
3533 	    stp->ls_stateid.other[2] == 0) {
3534 		if ((nd->nd_flag & ND_CURSTATEID) != 0)
3535 			stp->ls_stateid = nd->nd_curstateid;
3536 		else {
3537 			nd->nd_repstat = NFSERR_BADSTATEID;
3538 			goto nfsmout;
3539 		}
3540 	}
3541 
3542 	stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++);
3543 	i = fxdr_unsigned(int, *tl++);
3544 	if ((nd->nd_flag & ND_NFSV41) != 0)
3545 		i &= ~NFSV4OPEN_WANTDELEGMASK;
3546 	switch (i) {
3547 	case NFSV4OPEN_ACCESSREAD:
3548 		stp->ls_flags = (NFSLCK_READACCESS | NFSLCK_DOWNGRADE);
3549 		break;
3550 	case NFSV4OPEN_ACCESSWRITE:
3551 		stp->ls_flags = (NFSLCK_WRITEACCESS | NFSLCK_DOWNGRADE);
3552 		break;
3553 	case NFSV4OPEN_ACCESSBOTH:
3554 		stp->ls_flags = (NFSLCK_READACCESS | NFSLCK_WRITEACCESS |
3555 		    NFSLCK_DOWNGRADE);
3556 		break;
3557 	default:
3558 		nd->nd_repstat = NFSERR_INVAL;
3559 	}
3560 	i = fxdr_unsigned(int, *tl);
3561 	switch (i) {
3562 	case NFSV4OPEN_DENYNONE:
3563 		break;
3564 	case NFSV4OPEN_DENYREAD:
3565 		stp->ls_flags |= NFSLCK_READDENY;
3566 		break;
3567 	case NFSV4OPEN_DENYWRITE:
3568 		stp->ls_flags |= NFSLCK_WRITEDENY;
3569 		break;
3570 	case NFSV4OPEN_DENYBOTH:
3571 		stp->ls_flags |= (NFSLCK_READDENY | NFSLCK_WRITEDENY);
3572 		break;
3573 	default:
3574 		nd->nd_repstat = NFSERR_INVAL;
3575 	}
3576 
3577 	clientid.lval[0] = stp->ls_stateid.other[0];
3578 	clientid.lval[1] = stp->ls_stateid.other[1];
3579 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
3580 		if ((nd->nd_flag & ND_NFSV41) != 0)
3581 			clientid.qval = nd->nd_clientid.qval;
3582 		else if (nd->nd_clientid.qval != clientid.qval)
3583 			printf("EEK12 multiple clids\n");
3584 	} else {
3585 		if ((nd->nd_flag & ND_NFSV41) != 0)
3586 			printf("EEK! no clientid from session\n");
3587 		nd->nd_flag |= ND_IMPLIEDCLID;
3588 		nd->nd_clientid.qval = clientid.qval;
3589 	}
3590 	if (!nd->nd_repstat)
3591 		nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid,
3592 		    nd, p, NULL);
3593 	if (!nd->nd_repstat) {
3594 		/* For NFSv4.1, set the Current StateID. */
3595 		if ((nd->nd_flag & ND_NFSV41) != 0) {
3596 			nd->nd_curstateid = stateid;
3597 			nd->nd_flag |= ND_CURSTATEID;
3598 		}
3599 		NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
3600 		*tl++ = txdr_unsigned(stateid.seqid);
3601 		NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
3602 	}
3603 nfsmout:
3604 	vput(vp);
3605 	NFSEXITCODE2(error, nd);
3606 	return (error);
3607 }
3608 
3609 /*
3610  * nfsv4 renew lease service
3611  */
3612 int
3613 nfsrvd_renew(struct nfsrv_descript *nd, __unused int isdgram,
3614     __unused vnode_t vp, __unused struct nfsexstuff *exp)
3615 {
3616 	u_int32_t *tl;
3617 	int error = 0;
3618 	nfsquad_t clientid;
3619 	struct thread *p = curthread;
3620 
3621 	if ((nd->nd_flag & ND_NFSV41) != 0) {
3622 		nd->nd_repstat = NFSERR_NOTSUPP;
3623 		goto nfsmout;
3624 	}
3625 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
3626 		goto nfsmout;
3627 	NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
3628 	clientid.lval[0] = *tl++;
3629 	clientid.lval[1] = *tl;
3630 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
3631 		if ((nd->nd_flag & ND_NFSV41) != 0)
3632 			clientid.qval = nd->nd_clientid.qval;
3633 		else if (nd->nd_clientid.qval != clientid.qval)
3634 			printf("EEK13 multiple clids\n");
3635 	} else {
3636 		if ((nd->nd_flag & ND_NFSV41) != 0)
3637 			printf("EEK! no clientid from session\n");
3638 		nd->nd_flag |= ND_IMPLIEDCLID;
3639 		nd->nd_clientid.qval = clientid.qval;
3640 	}
3641 	nd->nd_repstat = nfsrv_getclient(clientid, (CLOPS_RENEWOP|CLOPS_RENEW),
3642 	    NULL, NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p);
3643 nfsmout:
3644 	NFSEXITCODE2(error, nd);
3645 	return (error);
3646 }
3647 
3648 /*
3649  * nfsv4 security info service
3650  */
3651 int
3652 nfsrvd_secinfo(struct nfsrv_descript *nd, int isdgram,
3653     vnode_t dp, struct nfsexstuff *exp)
3654 {
3655 	u_int32_t *tl;
3656 	int len;
3657 	struct nameidata named;
3658 	vnode_t dirp = NULL, vp;
3659 	struct nfsrvfh fh;
3660 	struct nfsexstuff retnes;
3661 	u_int32_t *sizp;
3662 	int error = 0, i;
3663 	uint64_t savflag;
3664 	char *bufp;
3665 	u_long *hashp;
3666 	struct thread *p = curthread;
3667 
3668 	/*
3669 	 * All this just to get the export flags for the name.
3670 	 */
3671 	NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP,
3672 	    LOCKLEAF | SAVESTART);
3673 	nfsvno_setpathbuf(&named, &bufp, &hashp);
3674 	error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
3675 	if (error) {
3676 		vput(dp);
3677 		nfsvno_relpathbuf(&named);
3678 		goto out;
3679 	}
3680 	if (!nd->nd_repstat) {
3681 		nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, p, &dirp);
3682 	} else {
3683 		vput(dp);
3684 		nfsvno_relpathbuf(&named);
3685 	}
3686 	if (dirp)
3687 		vrele(dirp);
3688 	if (nd->nd_repstat)
3689 		goto out;
3690 	vrele(named.ni_startdir);
3691 	nfsvno_relpathbuf(&named);
3692 	fh.nfsrvfh_len = NFSX_MYFH;
3693 	vp = named.ni_vp;
3694 	nd->nd_repstat = nfsvno_getfh(vp, (fhandle_t *)fh.nfsrvfh_data, p);
3695 	vput(vp);
3696 	savflag = nd->nd_flag;
3697 	if (!nd->nd_repstat) {
3698 		nfsd_fhtovp(nd, &fh, LK_SHARED, &vp, &retnes, NULL, 0);
3699 		if (vp)
3700 			vput(vp);
3701 	}
3702 	nd->nd_flag = savflag;
3703 	if (nd->nd_repstat)
3704 		goto out;
3705 
3706 	/*
3707 	 * Finally have the export flags for name, so we can create
3708 	 * the security info.
3709 	 */
3710 	len = 0;
3711 	NFSM_BUILD(sizp, u_int32_t *, NFSX_UNSIGNED);
3712 	for (i = 0; i < retnes.nes_numsecflavor; i++) {
3713 		if (retnes.nes_secflavors[i] == AUTH_SYS) {
3714 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3715 			*tl = txdr_unsigned(RPCAUTH_UNIX);
3716 			len++;
3717 		} else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5) {
3718 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3719 			*tl++ = txdr_unsigned(RPCAUTH_GSS);
3720 			(void) nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
3721 			    nfsgss_mechlist[KERBV_MECH].len);
3722 			NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
3723 			*tl++ = txdr_unsigned(GSS_KERBV_QOP);
3724 			*tl = txdr_unsigned(RPCAUTHGSS_SVCNONE);
3725 			len++;
3726 		} else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5I) {
3727 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3728 			*tl++ = txdr_unsigned(RPCAUTH_GSS);
3729 			(void) nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
3730 			    nfsgss_mechlist[KERBV_MECH].len);
3731 			NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
3732 			*tl++ = txdr_unsigned(GSS_KERBV_QOP);
3733 			*tl = txdr_unsigned(RPCAUTHGSS_SVCINTEGRITY);
3734 			len++;
3735 		} else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5P) {
3736 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3737 			*tl++ = txdr_unsigned(RPCAUTH_GSS);
3738 			(void) nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
3739 			    nfsgss_mechlist[KERBV_MECH].len);
3740 			NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
3741 			*tl++ = txdr_unsigned(GSS_KERBV_QOP);
3742 			*tl = txdr_unsigned(RPCAUTHGSS_SVCPRIVACY);
3743 			len++;
3744 		}
3745 	}
3746 	*sizp = txdr_unsigned(len);
3747 
3748 out:
3749 	NFSEXITCODE2(error, nd);
3750 	return (error);
3751 }
3752 
3753 /*
3754  * nfsv4 security info no name service
3755  */
3756 int
3757 nfsrvd_secinfononame(struct nfsrv_descript *nd, int isdgram,
3758     vnode_t dp, struct nfsexstuff *exp)
3759 {
3760 	uint32_t *tl, *sizp;
3761 	struct nameidata named;
3762 	vnode_t dirp = NULL, vp;
3763 	struct nfsrvfh fh;
3764 	struct nfsexstuff retnes;
3765 	int error = 0, fhstyle, i, len;
3766 	uint64_t savflag;
3767 	char *bufp;
3768 	u_long *hashp;
3769 	struct thread *p = curthread;
3770 
3771 	NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
3772 	fhstyle = fxdr_unsigned(int, *tl);
3773 	switch (fhstyle) {
3774 	case NFSSECINFONONAME_PARENT:
3775 		NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP,
3776 		    LOCKLEAF | SAVESTART);
3777 		nfsvno_setpathbuf(&named, &bufp, &hashp);
3778 		error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
3779 		if (error != 0) {
3780 			vput(dp);
3781 			nfsvno_relpathbuf(&named);
3782 			goto nfsmout;
3783 		}
3784 		if (nd->nd_repstat == 0)
3785 			nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, p, &dirp);
3786 		else
3787 			vput(dp);
3788 		if (dirp != NULL)
3789 			vrele(dirp);
3790 		vrele(named.ni_startdir);
3791 		nfsvno_relpathbuf(&named);
3792 		vp = named.ni_vp;
3793 		break;
3794 	case NFSSECINFONONAME_CURFH:
3795 		vp = dp;
3796 		break;
3797 	default:
3798 		nd->nd_repstat = NFSERR_INVAL;
3799 		vput(dp);
3800 	}
3801 	if (nd->nd_repstat != 0)
3802 		goto nfsmout;
3803 	fh.nfsrvfh_len = NFSX_MYFH;
3804 	nd->nd_repstat = nfsvno_getfh(vp, (fhandle_t *)fh.nfsrvfh_data, p);
3805 	vput(vp);
3806 	savflag = nd->nd_flag;
3807 	if (nd->nd_repstat == 0) {
3808 		nfsd_fhtovp(nd, &fh, LK_SHARED, &vp, &retnes, NULL, 0);
3809 		if (vp != NULL)
3810 			vput(vp);
3811 	}
3812 	nd->nd_flag = savflag;
3813 	if (nd->nd_repstat != 0)
3814 		goto nfsmout;
3815 
3816 	/*
3817 	 * Finally have the export flags for fh/parent, so we can create
3818 	 * the security info.
3819 	 */
3820 	len = 0;
3821 	NFSM_BUILD(sizp, uint32_t *, NFSX_UNSIGNED);
3822 	for (i = 0; i < retnes.nes_numsecflavor; i++) {
3823 		if (retnes.nes_secflavors[i] == AUTH_SYS) {
3824 			NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
3825 			*tl = txdr_unsigned(RPCAUTH_UNIX);
3826 			len++;
3827 		} else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5) {
3828 			NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
3829 			*tl = txdr_unsigned(RPCAUTH_GSS);
3830 			nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
3831 			    nfsgss_mechlist[KERBV_MECH].len);
3832 			NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
3833 			*tl++ = txdr_unsigned(GSS_KERBV_QOP);
3834 			*tl = txdr_unsigned(RPCAUTHGSS_SVCNONE);
3835 			len++;
3836 		} else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5I) {
3837 			NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
3838 			*tl = txdr_unsigned(RPCAUTH_GSS);
3839 			nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
3840 			    nfsgss_mechlist[KERBV_MECH].len);
3841 			NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
3842 			*tl++ = txdr_unsigned(GSS_KERBV_QOP);
3843 			*tl = txdr_unsigned(RPCAUTHGSS_SVCINTEGRITY);
3844 			len++;
3845 		} else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5P) {
3846 			NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
3847 			*tl = txdr_unsigned(RPCAUTH_GSS);
3848 			nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
3849 			    nfsgss_mechlist[KERBV_MECH].len);
3850 			NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
3851 			*tl++ = txdr_unsigned(GSS_KERBV_QOP);
3852 			*tl = txdr_unsigned(RPCAUTHGSS_SVCPRIVACY);
3853 			len++;
3854 		}
3855 	}
3856 	*sizp = txdr_unsigned(len);
3857 
3858 nfsmout:
3859 	NFSEXITCODE2(error, nd);
3860 	return (error);
3861 }
3862 
3863 /*
3864  * nfsv4 set client id service
3865  */
3866 int
3867 nfsrvd_setclientid(struct nfsrv_descript *nd, __unused int isdgram,
3868     __unused vnode_t vp, __unused struct nfsexstuff *exp)
3869 {
3870 	u_int32_t *tl;
3871 	int i;
3872 	int error = 0, idlen;
3873 	struct nfsclient *clp = NULL;
3874 #ifdef INET
3875 	struct sockaddr_in *rin;
3876 #endif
3877 #ifdef INET6
3878 	struct sockaddr_in6 *rin6;
3879 #endif
3880 #if defined(INET) || defined(INET6)
3881 	u_char *ucp, *ucp2;
3882 #endif
3883 	u_char *verf, *addrbuf;
3884 	nfsquad_t clientid, confirm;
3885 	struct thread *p = curthread;
3886 
3887 	if ((nd->nd_flag & ND_NFSV41) != 0) {
3888 		nd->nd_repstat = NFSERR_NOTSUPP;
3889 		goto nfsmout;
3890 	}
3891 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
3892 		goto out;
3893 	NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF + NFSX_UNSIGNED);
3894 	verf = (u_char *)tl;
3895 	tl += (NFSX_VERF / NFSX_UNSIGNED);
3896 	i = fxdr_unsigned(int, *tl);
3897 	if (i > NFSV4_OPAQUELIMIT || i <= 0) {
3898 		nd->nd_repstat = NFSERR_BADXDR;
3899 		goto nfsmout;
3900 	}
3901 	idlen = i;
3902 	if (nd->nd_flag & ND_GSS)
3903 		i += nd->nd_princlen;
3904 	clp = malloc(sizeof(struct nfsclient) + i, M_NFSDCLIENT, M_WAITOK |
3905 	    M_ZERO);
3906 	clp->lc_stateid = malloc(sizeof(struct nfsstatehead) *
3907 	    nfsrv_statehashsize, M_NFSDCLIENT, M_WAITOK);
3908 	NFSINITSOCKMUTEX(&clp->lc_req.nr_mtx);
3909 	/* Allocated large enough for an AF_INET or AF_INET6 socket. */
3910 	clp->lc_req.nr_nam = malloc(sizeof(struct sockaddr_in6), M_SONAME,
3911 	    M_WAITOK | M_ZERO);
3912 	clp->lc_req.nr_cred = NULL;
3913 	NFSBCOPY(verf, clp->lc_verf, NFSX_VERF);
3914 	clp->lc_idlen = idlen;
3915 	error = nfsrv_mtostr(nd, clp->lc_id, idlen);
3916 	if (error)
3917 		goto nfsmout;
3918 	if (nd->nd_flag & ND_GSS) {
3919 		clp->lc_flags = LCL_GSS;
3920 		if (nd->nd_flag & ND_GSSINTEGRITY)
3921 			clp->lc_flags |= LCL_GSSINTEGRITY;
3922 		else if (nd->nd_flag & ND_GSSPRIVACY)
3923 			clp->lc_flags |= LCL_GSSPRIVACY;
3924 	} else {
3925 		clp->lc_flags = 0;
3926 	}
3927 	if ((nd->nd_flag & ND_GSS) && nd->nd_princlen > 0) {
3928 		clp->lc_flags |= LCL_NAME;
3929 		clp->lc_namelen = nd->nd_princlen;
3930 		clp->lc_name = &clp->lc_id[idlen];
3931 		NFSBCOPY(nd->nd_principal, clp->lc_name, clp->lc_namelen);
3932 	} else {
3933 		clp->lc_uid = nd->nd_cred->cr_uid;
3934 		clp->lc_gid = nd->nd_cred->cr_gid;
3935 	}
3936 
3937 	/* If the client is using TLS, do so for the callback connection. */
3938 	if (nd->nd_flag & ND_TLS)
3939 		clp->lc_flags |= LCL_TLSCB;
3940 
3941 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
3942 	clp->lc_program = fxdr_unsigned(u_int32_t, *tl);
3943 	error = nfsrv_getclientipaddr(nd, clp);
3944 	if (error)
3945 		goto nfsmout;
3946 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
3947 	clp->lc_callback = fxdr_unsigned(u_int32_t, *tl);
3948 
3949 	/*
3950 	 * nfsrv_setclient() does the actual work of adding it to the
3951 	 * client list. If there is no error, the structure has been
3952 	 * linked into the client list and clp should no longer be used
3953 	 * here. When an error is returned, it has not been linked in,
3954 	 * so it should be free'd.
3955 	 */
3956 	nd->nd_repstat = nfsrv_setclient(nd, &clp, &clientid, &confirm, p);
3957 	if (nd->nd_repstat == NFSERR_CLIDINUSE) {
3958 		/*
3959 		 * 8 is the maximum length of the port# string.
3960 		 */
3961 		addrbuf = malloc(INET6_ADDRSTRLEN + 8, M_TEMP, M_WAITOK);
3962 		switch (clp->lc_req.nr_nam->sa_family) {
3963 #ifdef INET
3964 		case AF_INET:
3965 			if (clp->lc_flags & LCL_TCPCALLBACK)
3966 				(void) nfsm_strtom(nd, "tcp", 3);
3967 			else
3968 				(void) nfsm_strtom(nd, "udp", 3);
3969 			rin = (struct sockaddr_in *)clp->lc_req.nr_nam;
3970 			ucp = (u_char *)&rin->sin_addr.s_addr;
3971 			ucp2 = (u_char *)&rin->sin_port;
3972 			sprintf(addrbuf, "%d.%d.%d.%d.%d.%d", ucp[0] & 0xff,
3973 			    ucp[1] & 0xff, ucp[2] & 0xff, ucp[3] & 0xff,
3974 			    ucp2[0] & 0xff, ucp2[1] & 0xff);
3975 			break;
3976 #endif
3977 #ifdef INET6
3978 		case AF_INET6:
3979 			if (clp->lc_flags & LCL_TCPCALLBACK)
3980 				(void) nfsm_strtom(nd, "tcp6", 4);
3981 			else
3982 				(void) nfsm_strtom(nd, "udp6", 4);
3983 			rin6 = (struct sockaddr_in6 *)clp->lc_req.nr_nam;
3984 			ucp = inet_ntop(AF_INET6, &rin6->sin6_addr, addrbuf,
3985 			    INET6_ADDRSTRLEN);
3986 			if (ucp != NULL)
3987 				i = strlen(ucp);
3988 			else
3989 				i = 0;
3990 			ucp2 = (u_char *)&rin6->sin6_port;
3991 			sprintf(&addrbuf[i], ".%d.%d", ucp2[0] & 0xff,
3992 			    ucp2[1] & 0xff);
3993 			break;
3994 #endif
3995 		}
3996 		(void) nfsm_strtom(nd, addrbuf, strlen(addrbuf));
3997 		free(addrbuf, M_TEMP);
3998 	}
3999 	if (clp) {
4000 		free(clp->lc_req.nr_nam, M_SONAME);
4001 		NFSFREEMUTEX(&clp->lc_req.nr_mtx);
4002 		free(clp->lc_stateid, M_NFSDCLIENT);
4003 		free(clp, M_NFSDCLIENT);
4004 	}
4005 	if (!nd->nd_repstat) {
4006 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_HYPER);
4007 		*tl++ = clientid.lval[0];
4008 		*tl++ = clientid.lval[1];
4009 		*tl++ = confirm.lval[0];
4010 		*tl = confirm.lval[1];
4011 	}
4012 
4013 out:
4014 	NFSEXITCODE2(0, nd);
4015 	return (0);
4016 nfsmout:
4017 	if (clp) {
4018 		free(clp->lc_req.nr_nam, M_SONAME);
4019 		NFSFREEMUTEX(&clp->lc_req.nr_mtx);
4020 		free(clp->lc_stateid, M_NFSDCLIENT);
4021 		free(clp, M_NFSDCLIENT);
4022 	}
4023 	NFSEXITCODE2(error, nd);
4024 	return (error);
4025 }
4026 
4027 /*
4028  * nfsv4 set client id confirm service
4029  */
4030 int
4031 nfsrvd_setclientidcfrm(struct nfsrv_descript *nd,
4032     __unused int isdgram, __unused vnode_t vp,
4033     __unused struct nfsexstuff *exp)
4034 {
4035 	u_int32_t *tl;
4036 	int error = 0;
4037 	nfsquad_t clientid, confirm;
4038 	struct thread *p = curthread;
4039 
4040 	if ((nd->nd_flag & ND_NFSV41) != 0) {
4041 		nd->nd_repstat = NFSERR_NOTSUPP;
4042 		goto nfsmout;
4043 	}
4044 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
4045 		goto nfsmout;
4046 	NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_HYPER);
4047 	clientid.lval[0] = *tl++;
4048 	clientid.lval[1] = *tl++;
4049 	confirm.lval[0] = *tl++;
4050 	confirm.lval[1] = *tl;
4051 
4052 	/*
4053 	 * nfsrv_getclient() searches the client list for a match and
4054 	 * returns the appropriate NFSERR status.
4055 	 */
4056 	nd->nd_repstat = nfsrv_getclient(clientid, (CLOPS_CONFIRM|CLOPS_RENEW),
4057 	    NULL, NULL, confirm, 0, nd, p);
4058 nfsmout:
4059 	NFSEXITCODE2(error, nd);
4060 	return (error);
4061 }
4062 
4063 /*
4064  * nfsv4 verify service
4065  */
4066 int
4067 nfsrvd_verify(struct nfsrv_descript *nd, int isdgram,
4068     vnode_t vp, __unused struct nfsexstuff *exp)
4069 {
4070 	int error = 0, ret, fhsize = NFSX_MYFH;
4071 	struct nfsvattr nva;
4072 	struct statfs *sf;
4073 	struct nfsfsinfo fs;
4074 	fhandle_t fh;
4075 	struct thread *p = curthread;
4076 
4077 	sf = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
4078 	nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
4079 	if (!nd->nd_repstat)
4080 		nd->nd_repstat = nfsvno_statfs(vp, sf);
4081 	if (!nd->nd_repstat)
4082 		nd->nd_repstat = nfsvno_getfh(vp, &fh, p);
4083 	if (!nd->nd_repstat) {
4084 		nfsvno_getfs(&fs, isdgram);
4085 		error = nfsv4_loadattr(nd, vp, &nva, NULL, &fh, fhsize, NULL,
4086 		    sf, NULL, &fs, NULL, 1, &ret, NULL, NULL, p, nd->nd_cred);
4087 		if (!error) {
4088 			if (nd->nd_procnum == NFSV4OP_NVERIFY) {
4089 				if (ret == 0)
4090 					nd->nd_repstat = NFSERR_SAME;
4091 				else if (ret != NFSERR_NOTSAME)
4092 					nd->nd_repstat = ret;
4093 			} else if (ret)
4094 				nd->nd_repstat = ret;
4095 		}
4096 	}
4097 	vput(vp);
4098 	free(sf, M_STATFS);
4099 	NFSEXITCODE2(error, nd);
4100 	return (error);
4101 }
4102 
4103 /*
4104  * nfs openattr rpc
4105  */
4106 int
4107 nfsrvd_openattr(struct nfsrv_descript *nd, __unused int isdgram,
4108     vnode_t dp, __unused vnode_t *vpp, __unused fhandle_t *fhp,
4109     __unused struct nfsexstuff *exp)
4110 {
4111 	u_int32_t *tl;
4112 	int error = 0, createdir __unused;
4113 
4114 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
4115 	createdir = fxdr_unsigned(int, *tl);
4116 	nd->nd_repstat = NFSERR_NOTSUPP;
4117 nfsmout:
4118 	vrele(dp);
4119 	NFSEXITCODE2(error, nd);
4120 	return (error);
4121 }
4122 
4123 /*
4124  * nfsv4 release lock owner service
4125  */
4126 int
4127 nfsrvd_releaselckown(struct nfsrv_descript *nd, __unused int isdgram,
4128     __unused vnode_t vp, __unused struct nfsexstuff *exp)
4129 {
4130 	u_int32_t *tl;
4131 	struct nfsstate *stp = NULL;
4132 	int error = 0, len;
4133 	nfsquad_t clientid;
4134 	struct thread *p = curthread;
4135 
4136 	if ((nd->nd_flag & ND_NFSV41) != 0) {
4137 		nd->nd_repstat = NFSERR_NOTSUPP;
4138 		goto nfsmout;
4139 	}
4140 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
4141 		goto nfsmout;
4142 	NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
4143 	len = fxdr_unsigned(int, *(tl + 2));
4144 	if (len <= 0 || len > NFSV4_OPAQUELIMIT) {
4145 		nd->nd_repstat = NFSERR_BADXDR;
4146 		goto nfsmout;
4147 	}
4148 	stp = malloc(sizeof (struct nfsstate) + len,
4149 	    M_NFSDSTATE, M_WAITOK);
4150 	stp->ls_ownerlen = len;
4151 	stp->ls_op = NULL;
4152 	stp->ls_flags = NFSLCK_RELEASE;
4153 	stp->ls_uid = nd->nd_cred->cr_uid;
4154 	clientid.lval[0] = *tl++;
4155 	clientid.lval[1] = *tl;
4156 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
4157 		if ((nd->nd_flag & ND_NFSV41) != 0)
4158 			clientid.qval = nd->nd_clientid.qval;
4159 		else if (nd->nd_clientid.qval != clientid.qval)
4160 			printf("EEK14 multiple clids\n");
4161 	} else {
4162 		if ((nd->nd_flag & ND_NFSV41) != 0)
4163 			printf("EEK! no clientid from session\n");
4164 		nd->nd_flag |= ND_IMPLIEDCLID;
4165 		nd->nd_clientid.qval = clientid.qval;
4166 	}
4167 	error = nfsrv_mtostr(nd, stp->ls_owner, len);
4168 	if (error)
4169 		goto nfsmout;
4170 	nd->nd_repstat = nfsrv_releaselckown(stp, clientid, p);
4171 	free(stp, M_NFSDSTATE);
4172 
4173 	NFSEXITCODE2(0, nd);
4174 	return (0);
4175 nfsmout:
4176 	if (stp)
4177 		free(stp, M_NFSDSTATE);
4178 	NFSEXITCODE2(error, nd);
4179 	return (error);
4180 }
4181 
4182 /*
4183  * nfsv4 exchange_id service
4184  */
4185 int
4186 nfsrvd_exchangeid(struct nfsrv_descript *nd, __unused int isdgram,
4187     __unused vnode_t vp, __unused struct nfsexstuff *exp)
4188 {
4189 	uint32_t *tl;
4190 	int error = 0, i, idlen;
4191 	struct nfsclient *clp = NULL;
4192 	nfsquad_t clientid, confirm;
4193 	uint8_t *verf;
4194 	uint32_t sp4type, v41flags;
4195 	uint64_t owner_minor;
4196 	struct timespec verstime;
4197 #ifdef INET
4198 	struct sockaddr_in *sin, *rin;
4199 #endif
4200 #ifdef INET6
4201 	struct sockaddr_in6 *sin6, *rin6;
4202 #endif
4203 	struct thread *p = curthread;
4204 
4205 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
4206 		goto nfsmout;
4207 	NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF + NFSX_UNSIGNED);
4208 	verf = (uint8_t *)tl;
4209 	tl += (NFSX_VERF / NFSX_UNSIGNED);
4210 	i = fxdr_unsigned(int, *tl);
4211 	if (i > NFSV4_OPAQUELIMIT || i <= 0) {
4212 		nd->nd_repstat = NFSERR_BADXDR;
4213 		goto nfsmout;
4214 	}
4215 	idlen = i;
4216 	if (nd->nd_flag & ND_GSS)
4217 		i += nd->nd_princlen;
4218 	clp = malloc(sizeof(struct nfsclient) + i, M_NFSDCLIENT, M_WAITOK |
4219 	    M_ZERO);
4220 	clp->lc_stateid = malloc(sizeof(struct nfsstatehead) *
4221 	    nfsrv_statehashsize, M_NFSDCLIENT, M_WAITOK);
4222 	NFSINITSOCKMUTEX(&clp->lc_req.nr_mtx);
4223 	/* Allocated large enough for an AF_INET or AF_INET6 socket. */
4224 	clp->lc_req.nr_nam = malloc(sizeof(struct sockaddr_in6), M_SONAME,
4225 	    M_WAITOK | M_ZERO);
4226 	switch (nd->nd_nam->sa_family) {
4227 #ifdef INET
4228 	case AF_INET:
4229 		rin = (struct sockaddr_in *)clp->lc_req.nr_nam;
4230 		sin = (struct sockaddr_in *)nd->nd_nam;
4231 		rin->sin_family = AF_INET;
4232 		rin->sin_len = sizeof(struct sockaddr_in);
4233 		rin->sin_port = 0;
4234 		rin->sin_addr.s_addr = sin->sin_addr.s_addr;
4235 		break;
4236 #endif
4237 #ifdef INET6
4238 	case AF_INET6:
4239 		rin6 = (struct sockaddr_in6 *)clp->lc_req.nr_nam;
4240 		sin6 = (struct sockaddr_in6 *)nd->nd_nam;
4241 		rin6->sin6_family = AF_INET6;
4242 		rin6->sin6_len = sizeof(struct sockaddr_in6);
4243 		rin6->sin6_port = 0;
4244 		rin6->sin6_addr = sin6->sin6_addr;
4245 		break;
4246 #endif
4247 	}
4248 	clp->lc_req.nr_cred = NULL;
4249 	NFSBCOPY(verf, clp->lc_verf, NFSX_VERF);
4250 	clp->lc_idlen = idlen;
4251 	error = nfsrv_mtostr(nd, clp->lc_id, idlen);
4252 	if (error != 0)
4253 		goto nfsmout;
4254 	if ((nd->nd_flag & ND_GSS) != 0) {
4255 		clp->lc_flags = LCL_GSS | LCL_NFSV41;
4256 		if ((nd->nd_flag & ND_GSSINTEGRITY) != 0)
4257 			clp->lc_flags |= LCL_GSSINTEGRITY;
4258 		else if ((nd->nd_flag & ND_GSSPRIVACY) != 0)
4259 			clp->lc_flags |= LCL_GSSPRIVACY;
4260 	} else
4261 		clp->lc_flags = LCL_NFSV41;
4262 	if ((nd->nd_flag & ND_NFSV42) != 0)
4263 		clp->lc_flags |= LCL_NFSV42;
4264 	if ((nd->nd_flag & ND_GSS) != 0 && nd->nd_princlen > 0) {
4265 		clp->lc_flags |= LCL_NAME;
4266 		clp->lc_namelen = nd->nd_princlen;
4267 		clp->lc_name = &clp->lc_id[idlen];
4268 		NFSBCOPY(nd->nd_principal, clp->lc_name, clp->lc_namelen);
4269 	} else {
4270 		clp->lc_uid = nd->nd_cred->cr_uid;
4271 		clp->lc_gid = nd->nd_cred->cr_gid;
4272 	}
4273 	NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
4274 	v41flags = fxdr_unsigned(uint32_t, *tl++);
4275 	if ((v41flags & ~(NFSV4EXCH_SUPPMOVEDREFER | NFSV4EXCH_SUPPMOVEDMIGR |
4276 	    NFSV4EXCH_BINDPRINCSTATEID | NFSV4EXCH_MASKPNFS |
4277 	    NFSV4EXCH_UPDCONFIRMEDRECA)) != 0) {
4278 		nd->nd_repstat = NFSERR_INVAL;
4279 		goto nfsmout;
4280 	}
4281 	if ((v41flags & NFSV4EXCH_UPDCONFIRMEDRECA) != 0)
4282 		confirm.lval[1] = 1;
4283 	else
4284 		confirm.lval[1] = 0;
4285 	if (nfsrv_devidcnt == 0)
4286 		v41flags = NFSV4EXCH_USENONPNFS | NFSV4EXCH_USEPNFSDS;
4287  	else
4288  		v41flags = NFSV4EXCH_USEPNFSMDS;
4289 	sp4type = fxdr_unsigned(uint32_t, *tl);
4290 	if (sp4type != NFSV4EXCH_SP4NONE) {
4291 		nd->nd_repstat = NFSERR_NOTSUPP;
4292 		goto nfsmout;
4293 	}
4294 
4295 	/*
4296 	 * nfsrv_setclient() does the actual work of adding it to the
4297 	 * client list. If there is no error, the structure has been
4298 	 * linked into the client list and clp should no longer be used
4299 	 * here. When an error is returned, it has not been linked in,
4300 	 * so it should be free'd.
4301 	 */
4302 	nd->nd_repstat = nfsrv_setclient(nd, &clp, &clientid, &confirm, p);
4303 	if (clp != NULL) {
4304 		free(clp->lc_req.nr_nam, M_SONAME);
4305 		NFSFREEMUTEX(&clp->lc_req.nr_mtx);
4306 		free(clp->lc_stateid, M_NFSDCLIENT);
4307 		free(clp, M_NFSDCLIENT);
4308 	}
4309 	if (nd->nd_repstat == 0) {
4310 		if (confirm.lval[1] != 0)
4311 			v41flags |= NFSV4EXCH_CONFIRMEDR;
4312 		NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER + 3 * NFSX_UNSIGNED);
4313 		*tl++ = clientid.lval[0];			/* ClientID */
4314 		*tl++ = clientid.lval[1];
4315 		*tl++ = txdr_unsigned(confirm.lval[0]);		/* SequenceID */
4316 		*tl++ = txdr_unsigned(v41flags);		/* Exch flags */
4317 		*tl++ = txdr_unsigned(NFSV4EXCH_SP4NONE);	/* No SSV */
4318 		owner_minor = 0;				/* Owner */
4319 		txdr_hyper(owner_minor, tl);			/* Minor */
4320 		(void)nfsm_strtom(nd, nd->nd_cred->cr_prison->pr_hostuuid,
4321 		    strlen(nd->nd_cred->cr_prison->pr_hostuuid)); /* Major */
4322 		(void)nfsm_strtom(nd, nd->nd_cred->cr_prison->pr_hostuuid,
4323 		    strlen(nd->nd_cred->cr_prison->pr_hostuuid)); /* Scope */
4324 		NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
4325 		*tl = txdr_unsigned(1);
4326 		(void)nfsm_strtom(nd, "freebsd.org", strlen("freebsd.org"));
4327 		(void)nfsm_strtom(nd, version, strlen(version));
4328 		NFSM_BUILD(tl, uint32_t *, NFSX_V4TIME);
4329 		verstime.tv_sec = 1293840000;		/* Jan 1, 2011 */
4330 		verstime.tv_nsec = 0;
4331 		txdr_nfsv4time(&verstime, tl);
4332 	}
4333 	NFSEXITCODE2(0, nd);
4334 	return (0);
4335 nfsmout:
4336 	if (clp != NULL) {
4337 		free(clp->lc_req.nr_nam, M_SONAME);
4338 		NFSFREEMUTEX(&clp->lc_req.nr_mtx);
4339 		free(clp->lc_stateid, M_NFSDCLIENT);
4340 		free(clp, M_NFSDCLIENT);
4341 	}
4342 	NFSEXITCODE2(error, nd);
4343 	return (error);
4344 }
4345 
4346 /*
4347  * nfsv4 create session service
4348  */
4349 int
4350 nfsrvd_createsession(struct nfsrv_descript *nd, __unused int isdgram,
4351     __unused vnode_t vp, __unused struct nfsexstuff *exp)
4352 {
4353 	uint32_t *tl;
4354 	int error = 0;
4355 	nfsquad_t clientid, confirm;
4356 	struct nfsdsession *sep = NULL;
4357 	uint32_t rdmacnt;
4358 	struct thread *p = curthread;
4359 
4360 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
4361 		goto nfsmout;
4362 	sep = (struct nfsdsession *)malloc(sizeof(struct nfsdsession),
4363 	    M_NFSDSESSION, M_WAITOK | M_ZERO);
4364 	sep->sess_refcnt = 1;
4365 	mtx_init(&sep->sess_cbsess.nfsess_mtx, "nfscbsession", NULL, MTX_DEF);
4366 	NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + 2 * NFSX_UNSIGNED);
4367 	clientid.lval[0] = *tl++;
4368 	clientid.lval[1] = *tl++;
4369 	confirm.lval[0] = fxdr_unsigned(uint32_t, *tl++);
4370 	sep->sess_crflags = fxdr_unsigned(uint32_t, *tl);
4371 	/* Persistent sessions and RDMA are not supported. */
4372 	sep->sess_crflags &= NFSV4CRSESS_CONNBACKCHAN;
4373 
4374 	/* Fore channel attributes. */
4375 	NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED);
4376 	tl++;					/* Header pad always 0. */
4377 	sep->sess_maxreq = fxdr_unsigned(uint32_t, *tl++);
4378 	if (sep->sess_maxreq > sb_max_adj - NFS_MAXXDR) {
4379 		sep->sess_maxreq = sb_max_adj - NFS_MAXXDR;
4380 		printf("Consider increasing kern.ipc.maxsockbuf\n");
4381 	}
4382 	sep->sess_maxresp = fxdr_unsigned(uint32_t, *tl++);
4383 	if (sep->sess_maxresp > sb_max_adj - NFS_MAXXDR) {
4384 		sep->sess_maxresp = sb_max_adj - NFS_MAXXDR;
4385 		printf("Consider increasing kern.ipc.maxsockbuf\n");
4386 	}
4387 	sep->sess_maxrespcached = fxdr_unsigned(uint32_t, *tl++);
4388 	sep->sess_maxops = fxdr_unsigned(uint32_t, *tl++);
4389 	sep->sess_maxslots = fxdr_unsigned(uint32_t, *tl++);
4390 	if (sep->sess_maxslots > NFSV4_SLOTS)
4391 		sep->sess_maxslots = NFSV4_SLOTS;
4392 	rdmacnt = fxdr_unsigned(uint32_t, *tl);
4393 	if (rdmacnt > 1) {
4394 		nd->nd_repstat = NFSERR_BADXDR;
4395 		goto nfsmout;
4396 	} else if (rdmacnt == 1)
4397 		NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
4398 
4399 	/* Back channel attributes. */
4400 	NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED);
4401 	tl++;					/* Header pad always 0. */
4402 	sep->sess_cbmaxreq = fxdr_unsigned(uint32_t, *tl++);
4403 	sep->sess_cbmaxresp = fxdr_unsigned(uint32_t, *tl++);
4404 	sep->sess_cbmaxrespcached = fxdr_unsigned(uint32_t, *tl++);
4405 	sep->sess_cbmaxops = fxdr_unsigned(uint32_t, *tl++);
4406 	sep->sess_cbsess.nfsess_foreslots = fxdr_unsigned(uint32_t, *tl++);
4407 	rdmacnt = fxdr_unsigned(uint32_t, *tl);
4408 	if (rdmacnt > 1) {
4409 		nd->nd_repstat = NFSERR_BADXDR;
4410 		goto nfsmout;
4411 	} else if (rdmacnt == 1)
4412 		NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
4413 
4414 	NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
4415 	sep->sess_cbprogram = fxdr_unsigned(uint32_t, *tl);
4416 
4417 	/*
4418 	 * nfsrv_getclient() searches the client list for a match and
4419 	 * returns the appropriate NFSERR status.
4420 	 */
4421 	nd->nd_repstat = nfsrv_getclient(clientid, CLOPS_CONFIRM | CLOPS_RENEW,
4422 	    NULL, sep, confirm, sep->sess_cbprogram, nd, p);
4423 	if (nd->nd_repstat == 0) {
4424 		NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID);
4425 		NFSBCOPY(sep->sess_sessionid, tl, NFSX_V4SESSIONID);
4426 		NFSM_BUILD(tl, uint32_t *, 18 * NFSX_UNSIGNED);
4427 		*tl++ = txdr_unsigned(confirm.lval[0]);	/* sequenceid */
4428 		*tl++ = txdr_unsigned(sep->sess_crflags);
4429 
4430 		/* Fore channel attributes. */
4431 		*tl++ = 0;
4432 		*tl++ = txdr_unsigned(sep->sess_maxreq);
4433 		*tl++ = txdr_unsigned(sep->sess_maxresp);
4434 		*tl++ = txdr_unsigned(sep->sess_maxrespcached);
4435 		*tl++ = txdr_unsigned(sep->sess_maxops);
4436 		*tl++ = txdr_unsigned(sep->sess_maxslots);
4437 		*tl++ = txdr_unsigned(1);
4438 		*tl++ = txdr_unsigned(0);			/* No RDMA. */
4439 
4440 		/* Back channel attributes. */
4441 		*tl++ = 0;
4442 		*tl++ = txdr_unsigned(sep->sess_cbmaxreq);
4443 		*tl++ = txdr_unsigned(sep->sess_cbmaxresp);
4444 		*tl++ = txdr_unsigned(sep->sess_cbmaxrespcached);
4445 		*tl++ = txdr_unsigned(sep->sess_cbmaxops);
4446 		*tl++ = txdr_unsigned(sep->sess_cbsess.nfsess_foreslots);
4447 		*tl++ = txdr_unsigned(1);
4448 		*tl = txdr_unsigned(0);			/* No RDMA. */
4449 	}
4450 nfsmout:
4451 	if (nd->nd_repstat != 0 && sep != NULL)
4452 		free(sep, M_NFSDSESSION);
4453 	NFSEXITCODE2(error, nd);
4454 	return (error);
4455 }
4456 
4457 /*
4458  * nfsv4 sequence service
4459  */
4460 int
4461 nfsrvd_sequence(struct nfsrv_descript *nd, __unused int isdgram,
4462     __unused vnode_t vp, __unused struct nfsexstuff *exp)
4463 {
4464 	uint32_t *tl;
4465 	uint32_t highest_slotid, sequenceid, sflags, target_highest_slotid;
4466 	int cache_this, error = 0;
4467 	struct thread *p = curthread;
4468 
4469 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
4470 		goto nfsmout;
4471 	NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID);
4472 	NFSBCOPY(tl, nd->nd_sessionid, NFSX_V4SESSIONID);
4473 	NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED);
4474 	sequenceid = fxdr_unsigned(uint32_t, *tl++);
4475 	nd->nd_slotid = fxdr_unsigned(uint32_t, *tl++);
4476 	highest_slotid = fxdr_unsigned(uint32_t, *tl++);
4477 	if (*tl == newnfs_true)
4478 		cache_this = 1;
4479 	else
4480 		cache_this = 0;
4481 	nd->nd_flag |= ND_HASSEQUENCE;
4482 	nd->nd_repstat = nfsrv_checksequence(nd, sequenceid, &highest_slotid,
4483 	    &target_highest_slotid, cache_this, &sflags, p);
4484 	if (nd->nd_repstat == 0) {
4485 		NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID);
4486 		NFSBCOPY(nd->nd_sessionid, tl, NFSX_V4SESSIONID);
4487 		NFSM_BUILD(tl, uint32_t *, 5 * NFSX_UNSIGNED);
4488 		*tl++ = txdr_unsigned(sequenceid);
4489 		*tl++ = txdr_unsigned(nd->nd_slotid);
4490 		*tl++ = txdr_unsigned(highest_slotid);
4491 		*tl++ = txdr_unsigned(target_highest_slotid);
4492 		*tl = txdr_unsigned(sflags);
4493 	}
4494 nfsmout:
4495 	NFSEXITCODE2(error, nd);
4496 	return (error);
4497 }
4498 
4499 /*
4500  * nfsv4 reclaim complete service
4501  */
4502 int
4503 nfsrvd_reclaimcomplete(struct nfsrv_descript *nd, __unused int isdgram,
4504     __unused vnode_t vp, __unused struct nfsexstuff *exp)
4505 {
4506 	uint32_t *tl;
4507 	int error = 0, onefs;
4508 
4509 	NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
4510 	/*
4511 	 * I believe that a ReclaimComplete with rca_one_fs == TRUE is only
4512 	 * to be used after a file system has been transferred to a different
4513 	 * file server.  However, RFC5661 is somewhat vague w.r.t. this and
4514 	 * the ESXi 6.7 client does both a ReclaimComplete with rca_one_fs
4515 	 * == TRUE and one with ReclaimComplete with rca_one_fs == FALSE.
4516 	 * Therefore, just ignore the rca_one_fs == TRUE operation and return
4517 	 * NFS_OK without doing anything.
4518 	 */
4519 	onefs = 0;
4520 	if (*tl == newnfs_true)
4521 		onefs = 1;
4522 	nd->nd_repstat = nfsrv_checkreclaimcomplete(nd, onefs);
4523 nfsmout:
4524 	NFSEXITCODE2(error, nd);
4525 	return (error);
4526 }
4527 
4528 /*
4529  * nfsv4 destroy clientid service
4530  */
4531 int
4532 nfsrvd_destroyclientid(struct nfsrv_descript *nd, __unused int isdgram,
4533     __unused vnode_t vp, __unused struct nfsexstuff *exp)
4534 {
4535 	uint32_t *tl;
4536 	nfsquad_t clientid;
4537 	int error = 0;
4538 	struct thread *p = curthread;
4539 
4540 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
4541 		goto nfsmout;
4542 	NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
4543 	clientid.lval[0] = *tl++;
4544 	clientid.lval[1] = *tl;
4545 	nd->nd_repstat = nfsrv_destroyclient(clientid, p);
4546 nfsmout:
4547 	NFSEXITCODE2(error, nd);
4548 	return (error);
4549 }
4550 
4551 /*
4552  * nfsv4 bind connection to session service
4553  */
4554 int
4555 nfsrvd_bindconnsess(struct nfsrv_descript *nd, __unused int isdgram,
4556     __unused vnode_t vp, __unused struct nfsexstuff *exp)
4557 {
4558 	uint32_t *tl;
4559 	uint8_t sessid[NFSX_V4SESSIONID];
4560 	int error = 0, foreaft;
4561 
4562 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
4563 		goto nfsmout;
4564 	NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID + 2 * NFSX_UNSIGNED);
4565 	NFSBCOPY(tl, sessid, NFSX_V4SESSIONID);
4566 	tl += (NFSX_V4SESSIONID / NFSX_UNSIGNED);
4567 	foreaft = fxdr_unsigned(int, *tl++);
4568 	if (*tl == newnfs_true) {
4569 		/* RDMA is not supported. */
4570 		nd->nd_repstat = NFSERR_NOTSUPP;
4571 		goto nfsmout;
4572 	}
4573 
4574 	nd->nd_repstat = nfsrv_bindconnsess(nd, sessid, &foreaft);
4575 	if (nd->nd_repstat == 0) {
4576 		NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 2 *
4577 		    NFSX_UNSIGNED);
4578 		NFSBCOPY(sessid, tl, NFSX_V4SESSIONID);
4579 		tl += (NFSX_V4SESSIONID / NFSX_UNSIGNED);
4580 		*tl++ = txdr_unsigned(foreaft);
4581 		*tl = newnfs_false;
4582 	}
4583 nfsmout:
4584 	NFSEXITCODE2(error, nd);
4585 	return (error);
4586 }
4587 
4588 /*
4589  * nfsv4 destroy session service
4590  */
4591 int
4592 nfsrvd_destroysession(struct nfsrv_descript *nd, __unused int isdgram,
4593     __unused vnode_t vp, __unused struct nfsexstuff *exp)
4594 {
4595 	uint8_t *cp, sessid[NFSX_V4SESSIONID];
4596 	int error = 0;
4597 
4598 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
4599 		goto nfsmout;
4600 	NFSM_DISSECT(cp, uint8_t *, NFSX_V4SESSIONID);
4601 	NFSBCOPY(cp, sessid, NFSX_V4SESSIONID);
4602 	nd->nd_repstat = nfsrv_destroysession(nd, sessid);
4603 nfsmout:
4604 	NFSEXITCODE2(error, nd);
4605 	return (error);
4606 }
4607 
4608 /*
4609  * nfsv4 free stateid service
4610  */
4611 int
4612 nfsrvd_freestateid(struct nfsrv_descript *nd, __unused int isdgram,
4613     __unused vnode_t vp, __unused struct nfsexstuff *exp)
4614 {
4615 	uint32_t *tl;
4616 	nfsv4stateid_t stateid;
4617 	int error = 0;
4618 	struct thread *p = curthread;
4619 
4620 	NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID);
4621 	stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
4622 	NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
4623 
4624 	/*
4625 	 * For the special stateid of other all 0s and seqid == 1, set the
4626 	 * stateid to the current stateid, if it is set.
4627 	 */
4628 	if (stateid.seqid == 1 && stateid.other[0] == 0 &&
4629 	    stateid.other[1] == 0 && stateid.other[2] == 0) {
4630 		if ((nd->nd_flag & ND_CURSTATEID) != 0) {
4631 			stateid = nd->nd_curstateid;
4632 			stateid.seqid = 0;
4633 		} else {
4634 			nd->nd_repstat = NFSERR_BADSTATEID;
4635 			goto nfsmout;
4636 		}
4637 	}
4638 
4639 	nd->nd_repstat = nfsrv_freestateid(nd, &stateid, p);
4640 
4641 	/* If the current stateid has been free'd, unset it. */
4642 	if (nd->nd_repstat == 0 && (nd->nd_flag & ND_CURSTATEID) != 0 &&
4643 	    stateid.other[0] == nd->nd_curstateid.other[0] &&
4644 	    stateid.other[1] == nd->nd_curstateid.other[1] &&
4645 	    stateid.other[2] == nd->nd_curstateid.other[2])
4646 		nd->nd_flag &= ~ND_CURSTATEID;
4647 nfsmout:
4648 	NFSEXITCODE2(error, nd);
4649 	return (error);
4650 }
4651 
4652 /*
4653  * nfsv4 layoutget service
4654  */
4655 int
4656 nfsrvd_layoutget(struct nfsrv_descript *nd, __unused int isdgram,
4657     vnode_t vp, struct nfsexstuff *exp)
4658 {
4659 	uint32_t *tl;
4660 	nfsv4stateid_t stateid;
4661 	int error = 0, layoutlen, layouttype, iomode, maxcnt, retonclose;
4662 	uint64_t offset, len, minlen;
4663 	char *layp;
4664 	struct thread *p = curthread;
4665 
4666 	NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED + 3 * NFSX_HYPER +
4667 	    NFSX_STATEID);
4668 	tl++;		/* Signal layout available. Ignore for now. */
4669 	layouttype = fxdr_unsigned(int, *tl++);
4670 	iomode = fxdr_unsigned(int, *tl++);
4671 	offset = fxdr_hyper(tl); tl += 2;
4672 	len = fxdr_hyper(tl); tl += 2;
4673 	minlen = fxdr_hyper(tl); tl += 2;
4674 	stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
4675 	NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
4676 	tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
4677 	maxcnt = fxdr_unsigned(int, *tl);
4678 	NFSD_DEBUG(4, "layoutget ltyp=%d iom=%d off=%ju len=%ju mlen=%ju\n",
4679 	    layouttype, iomode, (uintmax_t)offset, (uintmax_t)len,
4680 	    (uintmax_t)minlen);
4681 	if (len < minlen ||
4682 	    (minlen != UINT64_MAX && offset + minlen < offset) ||
4683 	    (len != UINT64_MAX && offset + len < offset)) {
4684 		nd->nd_repstat = NFSERR_INVAL;
4685 		goto nfsmout;
4686 	}
4687 
4688 	/*
4689 	 * For the special stateid of other all 0s and seqid == 1, set the
4690 	 * stateid to the current stateid, if it is set.
4691 	 */
4692 	if (stateid.seqid == 1 && stateid.other[0] == 0 &&
4693 	    stateid.other[1] == 0 && stateid.other[2] == 0) {
4694 		if ((nd->nd_flag & ND_CURSTATEID) != 0) {
4695 			stateid = nd->nd_curstateid;
4696 			stateid.seqid = 0;
4697 		} else {
4698 			nd->nd_repstat = NFSERR_BADSTATEID;
4699 			goto nfsmout;
4700 		}
4701 	}
4702 
4703 	layp = NULL;
4704 	if (layouttype == NFSLAYOUT_NFSV4_1_FILES && nfsrv_maxpnfsmirror == 1)
4705 		layp = malloc(NFSX_V4FILELAYOUT, M_TEMP, M_WAITOK);
4706 	else if (layouttype == NFSLAYOUT_FLEXFILE)
4707 		layp = malloc(NFSX_V4FLEXLAYOUT(nfsrv_maxpnfsmirror), M_TEMP,
4708 		    M_WAITOK);
4709 	else
4710 		nd->nd_repstat = NFSERR_UNKNLAYOUTTYPE;
4711 	if (layp != NULL)
4712 		nd->nd_repstat = nfsrv_layoutget(nd, vp, exp, layouttype,
4713 		    &iomode, &offset, &len, minlen, &stateid, maxcnt,
4714 		    &retonclose, &layoutlen, layp, nd->nd_cred, p);
4715 	NFSD_DEBUG(4, "nfsrv_layoutget stat=%u layoutlen=%d\n", nd->nd_repstat,
4716 	    layoutlen);
4717 	if (nd->nd_repstat == 0) {
4718 		/* For NFSv4.1, set the Current StateID. */
4719 		if ((nd->nd_flag & ND_NFSV41) != 0) {
4720 			nd->nd_curstateid = stateid;
4721 			nd->nd_flag |= ND_CURSTATEID;
4722 		}
4723 		NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED + NFSX_STATEID +
4724 		    2 * NFSX_HYPER);
4725 		*tl++ = txdr_unsigned(retonclose);
4726 		*tl++ = txdr_unsigned(stateid.seqid);
4727 		NFSBCOPY(stateid.other, tl, NFSX_STATEIDOTHER);
4728 		tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
4729 		*tl++ = txdr_unsigned(1);	/* Only returns one layout. */
4730 		txdr_hyper(offset, tl); tl += 2;
4731 		txdr_hyper(len, tl); tl += 2;
4732 		*tl++ = txdr_unsigned(iomode);
4733 		*tl = txdr_unsigned(layouttype);
4734 		nfsm_strtom(nd, layp, layoutlen);
4735 	} else if (nd->nd_repstat == NFSERR_LAYOUTTRYLATER) {
4736 		NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
4737 		*tl = newnfs_false;
4738 	}
4739 	free(layp, M_TEMP);
4740 nfsmout:
4741 	vput(vp);
4742 	NFSEXITCODE2(error, nd);
4743 	return (error);
4744 }
4745 
4746 /*
4747  * nfsv4 layoutcommit service
4748  */
4749 int
4750 nfsrvd_layoutcommit(struct nfsrv_descript *nd, __unused int isdgram,
4751     vnode_t vp, struct nfsexstuff *exp)
4752 {
4753 	uint32_t *tl;
4754 	nfsv4stateid_t stateid;
4755 	int error = 0, hasnewoff, hasnewmtime, layouttype, maxcnt, reclaim;
4756 	int hasnewsize;
4757 	uint64_t offset, len, newoff = 0, newsize;
4758 	struct timespec newmtime;
4759 	char *layp;
4760 	struct thread *p = curthread;
4761 
4762 	layp = NULL;
4763 	NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED + 2 * NFSX_HYPER +
4764 	    NFSX_STATEID);
4765 	offset = fxdr_hyper(tl); tl += 2;
4766 	len = fxdr_hyper(tl); tl += 2;
4767 	reclaim = fxdr_unsigned(int, *tl++);
4768 	stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
4769 	NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
4770 	tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
4771 	/*
4772 	 * For the special stateid of other all 0s and seqid == 1, set the
4773 	 * stateid to the current stateid, if it is set.
4774 	 */
4775 	if (stateid.seqid == 1 && stateid.other[0] == 0 &&
4776 	    stateid.other[1] == 0 && stateid.other[2] == 0) {
4777 		if ((nd->nd_flag & ND_CURSTATEID) != 0) {
4778 			stateid = nd->nd_curstateid;
4779 			stateid.seqid = 0;
4780 		} else {
4781 			nd->nd_repstat = NFSERR_BADSTATEID;
4782 			goto nfsmout;
4783 		}
4784 	}
4785 
4786 	hasnewoff = fxdr_unsigned(int, *tl);
4787 	if (hasnewoff != 0) {
4788 		NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + NFSX_UNSIGNED);
4789 		newoff = fxdr_hyper(tl); tl += 2;
4790 	} else
4791 		NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
4792 	hasnewmtime = fxdr_unsigned(int, *tl);
4793 	if (hasnewmtime != 0) {
4794 		NFSM_DISSECT(tl, uint32_t *, NFSX_V4TIME + 2 * NFSX_UNSIGNED);
4795 		fxdr_nfsv4time(tl, &newmtime);
4796 		tl += (NFSX_V4TIME / NFSX_UNSIGNED);
4797 	} else
4798 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
4799 	layouttype = fxdr_unsigned(int, *tl++);
4800 	maxcnt = fxdr_unsigned(int, *tl);
4801 	if (maxcnt > 0) {
4802 		layp = malloc(maxcnt + 1, M_TEMP, M_WAITOK);
4803 		error = nfsrv_mtostr(nd, layp, maxcnt);
4804 		if (error != 0)
4805 			goto nfsmout;
4806 	}
4807 	nd->nd_repstat = nfsrv_layoutcommit(nd, vp, layouttype, hasnewoff,
4808 	    newoff, offset, len, hasnewmtime, &newmtime, reclaim, &stateid,
4809 	    maxcnt, layp, &hasnewsize, &newsize, nd->nd_cred, p);
4810 	NFSD_DEBUG(4, "nfsrv_layoutcommit stat=%u\n", nd->nd_repstat);
4811 	if (nd->nd_repstat == 0) {
4812 		if (hasnewsize != 0) {
4813 			NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED + NFSX_HYPER);
4814 			*tl++ = newnfs_true;
4815 			txdr_hyper(newsize, tl);
4816 		} else {
4817 			NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
4818 			*tl = newnfs_false;
4819 		}
4820 	}
4821 nfsmout:
4822 	free(layp, M_TEMP);
4823 	vput(vp);
4824 	NFSEXITCODE2(error, nd);
4825 	return (error);
4826 }
4827 
4828 /*
4829  * nfsv4 layoutreturn service
4830  */
4831 int
4832 nfsrvd_layoutreturn(struct nfsrv_descript *nd, __unused int isdgram,
4833     vnode_t vp, struct nfsexstuff *exp)
4834 {
4835 	uint32_t *tl, *layp;
4836 	nfsv4stateid_t stateid;
4837 	int error = 0, fnd, kind, layouttype, iomode, maxcnt, reclaim;
4838 	uint64_t offset, len;
4839 	struct thread *p = curthread;
4840 
4841 	layp = NULL;
4842 	NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED);
4843 	reclaim = *tl++;
4844 	layouttype = fxdr_unsigned(int, *tl++);
4845 	iomode = fxdr_unsigned(int, *tl++);
4846 	kind = fxdr_unsigned(int, *tl);
4847 	NFSD_DEBUG(4, "layoutreturn recl=%d ltyp=%d iom=%d kind=%d\n", reclaim,
4848 	    layouttype, iomode, kind);
4849 	if (kind == NFSV4LAYOUTRET_FILE) {
4850 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_STATEID +
4851 		    NFSX_UNSIGNED);
4852 		offset = fxdr_hyper(tl); tl += 2;
4853 		len = fxdr_hyper(tl); tl += 2;
4854 		stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
4855 		NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
4856 		tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
4857 
4858 		/*
4859 		 * For the special stateid of other all 0s and seqid == 1, set
4860 		 * the stateid to the current stateid, if it is set.
4861 		 */
4862 		if (stateid.seqid == 1 && stateid.other[0] == 0 &&
4863 		    stateid.other[1] == 0 && stateid.other[2] == 0) {
4864 			if ((nd->nd_flag & ND_CURSTATEID) != 0) {
4865 				stateid = nd->nd_curstateid;
4866 				stateid.seqid = 0;
4867 			} else {
4868 				nd->nd_repstat = NFSERR_BADSTATEID;
4869 				goto nfsmout;
4870 			}
4871 		}
4872 
4873 		maxcnt = fxdr_unsigned(int, *tl);
4874 		if (maxcnt > 0) {
4875 			layp = malloc(maxcnt + 1, M_TEMP, M_WAITOK);
4876 			error = nfsrv_mtostr(nd, (char *)layp, maxcnt);
4877 			if (error != 0)
4878 				goto nfsmout;
4879 		}
4880 	} else {
4881 		if (reclaim == newnfs_true) {
4882 			nd->nd_repstat = NFSERR_INVAL;
4883 			goto nfsmout;
4884 		}
4885 		offset = len = 0;
4886 		maxcnt = 0;
4887 	}
4888 	nd->nd_repstat = nfsrv_layoutreturn(nd, vp, layouttype, iomode,
4889 	    offset, len, reclaim, kind, &stateid, maxcnt, layp, &fnd,
4890 	    nd->nd_cred, p);
4891 	NFSD_DEBUG(4, "nfsrv_layoutreturn stat=%u fnd=%d\n", nd->nd_repstat,
4892 	    fnd);
4893 	if (nd->nd_repstat == 0) {
4894 		NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
4895 		if (fnd != 0) {
4896 			*tl = newnfs_true;
4897 			NFSM_BUILD(tl, uint32_t *, NFSX_STATEID);
4898 			*tl++ = txdr_unsigned(stateid.seqid);
4899 			NFSBCOPY(stateid.other, tl, NFSX_STATEIDOTHER);
4900 		} else
4901 			*tl = newnfs_false;
4902 	}
4903 nfsmout:
4904 	free(layp, M_TEMP);
4905 	vput(vp);
4906 	NFSEXITCODE2(error, nd);
4907 	return (error);
4908 }
4909 
4910 /*
4911  * nfsv4 layout error service
4912  */
4913 int
4914 nfsrvd_layouterror(struct nfsrv_descript *nd, __unused int isdgram,
4915     vnode_t vp, struct nfsexstuff *exp)
4916 {
4917 	uint32_t *tl;
4918 	nfsv4stateid_t stateid;
4919 	int cnt, error = 0, i, stat;
4920 	int opnum __unused;
4921 	char devid[NFSX_V4DEVICEID];
4922 	uint64_t offset, len;
4923 
4924 	NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_STATEID +
4925 	    NFSX_UNSIGNED);
4926 	offset = fxdr_hyper(tl); tl += 2;
4927 	len = fxdr_hyper(tl); tl += 2;
4928 	stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
4929 	NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
4930 	tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
4931 	cnt = fxdr_unsigned(int, *tl);
4932 	NFSD_DEBUG(4, "layouterror off=%ju len=%ju cnt=%d\n", (uintmax_t)offset,
4933 	    (uintmax_t)len, cnt);
4934 	/*
4935 	 * For the special stateid of other all 0s and seqid == 1, set
4936 	 * the stateid to the current stateid, if it is set.
4937 	 */
4938 	if (stateid.seqid == 1 && stateid.other[0] == 0 &&
4939 	    stateid.other[1] == 0 && stateid.other[2] == 0) {
4940 		if ((nd->nd_flag & ND_CURSTATEID) != 0) {
4941 			stateid = nd->nd_curstateid;
4942 			stateid.seqid = 0;
4943 		} else {
4944 			nd->nd_repstat = NFSERR_BADSTATEID;
4945 			goto nfsmout;
4946 		}
4947 	}
4948 
4949 	/*
4950 	 * Ignore offset, len and stateid for now.
4951 	 */
4952 	for (i = 0; i < cnt; i++) {
4953 		NFSM_DISSECT(tl, uint32_t *, NFSX_V4DEVICEID + 2 *
4954 		    NFSX_UNSIGNED);
4955 		NFSBCOPY(tl, devid, NFSX_V4DEVICEID);
4956 		tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
4957 		stat = fxdr_unsigned(int, *tl++);
4958 		opnum = fxdr_unsigned(int, *tl);
4959 		NFSD_DEBUG(4, "nfsrvd_layouterr op=%d stat=%d\n", opnum, stat);
4960 		/*
4961 		 * Except for NFSERR_ACCES and NFSERR_STALE errors,
4962 		 * disable the mirror.
4963 		 */
4964 		if (stat != NFSERR_ACCES && stat != NFSERR_STALE)
4965 			nfsrv_delds(devid, curthread);
4966 	}
4967 nfsmout:
4968 	vput(vp);
4969 	NFSEXITCODE2(error, nd);
4970 	return (error);
4971 }
4972 
4973 /*
4974  * nfsv4 layout stats service
4975  */
4976 int
4977 nfsrvd_layoutstats(struct nfsrv_descript *nd, __unused int isdgram,
4978     vnode_t vp, struct nfsexstuff *exp)
4979 {
4980 	uint32_t *tl;
4981 	nfsv4stateid_t stateid;
4982 	int cnt, error = 0;
4983 	int layouttype __unused;
4984 	char devid[NFSX_V4DEVICEID] __unused;
4985 	uint64_t offset, len, readcount, readbytes, writecount, writebytes
4986 	    __unused;
4987 
4988 	NFSM_DISSECT(tl, uint32_t *, 6 * NFSX_HYPER + NFSX_STATEID +
4989 	    NFSX_V4DEVICEID + 2 * NFSX_UNSIGNED);
4990 	offset = fxdr_hyper(tl); tl += 2;
4991 	len = fxdr_hyper(tl); tl += 2;
4992 	stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
4993 	NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
4994 	tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
4995 	readcount = fxdr_hyper(tl); tl += 2;
4996 	readbytes = fxdr_hyper(tl); tl += 2;
4997 	writecount = fxdr_hyper(tl); tl += 2;
4998 	writebytes = fxdr_hyper(tl); tl += 2;
4999 	NFSBCOPY(tl, devid, NFSX_V4DEVICEID);
5000 	tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
5001 	layouttype = fxdr_unsigned(int, *tl++);
5002 	cnt = fxdr_unsigned(int, *tl);
5003 	error = nfsm_advance(nd, NFSM_RNDUP(cnt), -1);
5004 	if (error != 0)
5005 		goto nfsmout;
5006 	NFSD_DEBUG(4, "layoutstats cnt=%d\n", cnt);
5007 	/*
5008 	 * For the special stateid of other all 0s and seqid == 1, set
5009 	 * the stateid to the current stateid, if it is set.
5010 	 */
5011 	if (stateid.seqid == 1 && stateid.other[0] == 0 &&
5012 	    stateid.other[1] == 0 && stateid.other[2] == 0) {
5013 		if ((nd->nd_flag & ND_CURSTATEID) != 0) {
5014 			stateid = nd->nd_curstateid;
5015 			stateid.seqid = 0;
5016 		} else {
5017 			nd->nd_repstat = NFSERR_BADSTATEID;
5018 			goto nfsmout;
5019 		}
5020 	}
5021 
5022 	/*
5023 	 * No use for the stats for now.
5024 	 */
5025 nfsmout:
5026 	vput(vp);
5027 	NFSEXITCODE2(error, nd);
5028 	return (error);
5029 }
5030 
5031 /*
5032  * nfsv4 io_advise service
5033  */
5034 int
5035 nfsrvd_ioadvise(struct nfsrv_descript *nd, __unused int isdgram,
5036     vnode_t vp, struct nfsexstuff *exp)
5037 {
5038 	uint32_t *tl;
5039 	nfsv4stateid_t stateid;
5040 	nfsattrbit_t hints;
5041 	int error = 0, ret;
5042 	off_t offset, len;
5043 
5044 	NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID + 2 * NFSX_HYPER);
5045 	stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
5046 	NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
5047 	tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
5048 	offset = fxdr_hyper(tl); tl += 2;
5049 	len = fxdr_hyper(tl);
5050 	error = nfsrv_getattrbits(nd, &hints, NULL, NULL);
5051 	if (error != 0)
5052 		goto nfsmout;
5053 	/*
5054 	 * For the special stateid of other all 0s and seqid == 1, set
5055 	 * the stateid to the current stateid, if it is set.
5056 	 */
5057 	if (stateid.seqid == 1 && stateid.other[0] == 0 &&
5058 	    stateid.other[1] == 0 && stateid.other[2] == 0) {
5059 		if ((nd->nd_flag & ND_CURSTATEID) != 0) {
5060 			stateid = nd->nd_curstateid;
5061 			stateid.seqid = 0;
5062 		} else {
5063 			nd->nd_repstat = NFSERR_BADSTATEID;
5064 			goto nfsmout;
5065 		}
5066 	}
5067 
5068 	if (offset < 0) {
5069 		nd->nd_repstat = NFSERR_INVAL;
5070 		goto nfsmout;
5071 	}
5072 	if (len < 0)
5073 		len = 0;
5074 	if (vp->v_type != VREG) {
5075 		if (vp->v_type == VDIR)
5076 			nd->nd_repstat = NFSERR_ISDIR;
5077 		else
5078 			nd->nd_repstat = NFSERR_WRONGTYPE;
5079 		goto nfsmout;
5080 	}
5081 
5082 	/*
5083 	 * For now, we can only handle WILLNEED and DONTNEED and don't use
5084 	 * the stateid.
5085 	 */
5086 	if ((NFSISSET_ATTRBIT(&hints, NFSV4IOHINT_WILLNEED) &&
5087 	    !NFSISSET_ATTRBIT(&hints, NFSV4IOHINT_DONTNEED)) ||
5088 	    (NFSISSET_ATTRBIT(&hints, NFSV4IOHINT_DONTNEED) &&
5089 	    !NFSISSET_ATTRBIT(&hints, NFSV4IOHINT_WILLNEED))) {
5090 		NFSVOPUNLOCK(vp);
5091 		if (NFSISSET_ATTRBIT(&hints, NFSV4IOHINT_WILLNEED)) {
5092 			ret = VOP_ADVISE(vp, offset, len, POSIX_FADV_WILLNEED);
5093 			NFSZERO_ATTRBIT(&hints);
5094 			if (ret == 0)
5095 				NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_WILLNEED);
5096 			else
5097 				NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_NORMAL);
5098 		} else {
5099 			ret = VOP_ADVISE(vp, offset, len, POSIX_FADV_DONTNEED);
5100 			NFSZERO_ATTRBIT(&hints);
5101 			if (ret == 0)
5102 				NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_DONTNEED);
5103 			else
5104 				NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_NORMAL);
5105 		}
5106 		vrele(vp);
5107 	} else {
5108 		NFSZERO_ATTRBIT(&hints);
5109 		NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_NORMAL);
5110 		vput(vp);
5111 	}
5112 	nfsrv_putattrbit(nd, &hints);
5113 	NFSEXITCODE2(error, nd);
5114 	return (error);
5115 nfsmout:
5116 	vput(vp);
5117 	NFSEXITCODE2(error, nd);
5118 	return (error);
5119 }
5120 
5121 /*
5122  * nfsv4 getdeviceinfo service
5123  */
5124 int
5125 nfsrvd_getdevinfo(struct nfsrv_descript *nd, __unused int isdgram,
5126     __unused vnode_t vp, __unused struct nfsexstuff *exp)
5127 {
5128 	uint32_t *tl, maxcnt, notify[NFSV4_NOTIFYBITMAP];
5129 	int cnt, devaddrlen, error = 0, i, layouttype;
5130 	char devid[NFSX_V4DEVICEID], *devaddr;
5131 	time_t dev_time;
5132 
5133 	NFSM_DISSECT(tl, uint32_t *, 3 * NFSX_UNSIGNED + NFSX_V4DEVICEID);
5134 	NFSBCOPY(tl, devid, NFSX_V4DEVICEID);
5135 	tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
5136 	layouttype = fxdr_unsigned(int, *tl++);
5137 	maxcnt = fxdr_unsigned(uint32_t, *tl++);
5138 	cnt = fxdr_unsigned(int, *tl);
5139 	NFSD_DEBUG(4, "getdevinfo ltyp=%d maxcnt=%u bitcnt=%d\n", layouttype,
5140 	    maxcnt, cnt);
5141 	if (cnt > NFSV4_NOTIFYBITMAP || cnt < 0) {
5142 		nd->nd_repstat = NFSERR_INVAL;
5143 		goto nfsmout;
5144 	}
5145 	if (cnt > 0) {
5146 		NFSM_DISSECT(tl, uint32_t *, cnt * NFSX_UNSIGNED);
5147 		for (i = 0; i < cnt; i++)
5148 			notify[i] = fxdr_unsigned(uint32_t, *tl++);
5149 	}
5150 	for (i = cnt; i < NFSV4_NOTIFYBITMAP; i++)
5151 		notify[i] = 0;
5152 
5153 	/*
5154 	 * Check that the device id is not stale.  Device ids are recreated
5155 	 * each time the nfsd threads are restarted.
5156 	 */
5157 	NFSBCOPY(devid, &dev_time, sizeof(dev_time));
5158 	if (dev_time != nfsdev_time) {
5159 		nd->nd_repstat = NFSERR_NOENT;
5160 		goto nfsmout;
5161 	}
5162 
5163 	/* Look for the device id. */
5164 	nd->nd_repstat = nfsrv_getdevinfo(devid, layouttype, &maxcnt,
5165 	    notify, &devaddrlen, &devaddr);
5166 	NFSD_DEBUG(4, "nfsrv_getdevinfo stat=%u\n", nd->nd_repstat);
5167 	if (nd->nd_repstat == 0) {
5168 		NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
5169 		*tl = txdr_unsigned(layouttype);
5170 		nfsm_strtom(nd, devaddr, devaddrlen);
5171 		cnt = 0;
5172 		for (i = 0; i < NFSV4_NOTIFYBITMAP; i++) {
5173 			if (notify[i] != 0)
5174 				cnt = i + 1;
5175 		}
5176 		NFSM_BUILD(tl, uint32_t *, (cnt + 1) * NFSX_UNSIGNED);
5177 		*tl++ = txdr_unsigned(cnt);
5178 		for (i = 0; i < cnt; i++)
5179 			*tl++ = txdr_unsigned(notify[i]);
5180 	} else if (nd->nd_repstat == NFSERR_TOOSMALL) {
5181 		NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
5182 		*tl = txdr_unsigned(maxcnt);
5183 	}
5184 nfsmout:
5185 	NFSEXITCODE2(error, nd);
5186 	return (error);
5187 }
5188 
5189 /*
5190  * nfsv4 test stateid service
5191  */
5192 int
5193 nfsrvd_teststateid(struct nfsrv_descript *nd, __unused int isdgram,
5194     __unused vnode_t vp, __unused struct nfsexstuff *exp)
5195 {
5196 	uint32_t *tl;
5197 	nfsv4stateid_t *stateidp = NULL, *tstateidp;
5198 	int cnt, error = 0, i, ret;
5199 	struct thread *p = curthread;
5200 
5201 	NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
5202 	cnt = fxdr_unsigned(int, *tl);
5203 	if (cnt <= 0 || cnt > 1024) {
5204 		nd->nd_repstat = NFSERR_BADXDR;
5205 		goto nfsmout;
5206 	}
5207 	stateidp = mallocarray(cnt, sizeof(nfsv4stateid_t), M_TEMP, M_WAITOK);
5208 	tstateidp = stateidp;
5209 	for (i = 0; i < cnt; i++) {
5210 		NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID);
5211 		tstateidp->seqid = fxdr_unsigned(uint32_t, *tl++);
5212 		NFSBCOPY(tl, tstateidp->other, NFSX_STATEIDOTHER);
5213 		tstateidp++;
5214 	}
5215 	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
5216 	*tl = txdr_unsigned(cnt);
5217 	tstateidp = stateidp;
5218 	for (i = 0; i < cnt; i++) {
5219 		ret = nfsrv_teststateid(nd, tstateidp, p);
5220 		NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
5221 		*tl = txdr_unsigned(ret);
5222 		tstateidp++;
5223 	}
5224 nfsmout:
5225 	free(stateidp, M_TEMP);
5226 	NFSEXITCODE2(error, nd);
5227 	return (error);
5228 }
5229 
5230 /*
5231  * nfs allocate service
5232  */
5233 int
5234 nfsrvd_allocate(struct nfsrv_descript *nd, __unused int isdgram,
5235     vnode_t vp, struct nfsexstuff *exp)
5236 {
5237 	uint32_t *tl;
5238 	struct nfsvattr forat;
5239 	int error = 0, forat_ret = 1, gotproxystateid;
5240 	off_t off, len;
5241 	struct nfsstate st, *stp = &st;
5242 	struct nfslock lo, *lop = &lo;
5243 	nfsv4stateid_t stateid;
5244 	nfsquad_t clientid;
5245 	nfsattrbit_t attrbits;
5246 
5247 	gotproxystateid = 0;
5248 	NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID + 2 * NFSX_HYPER);
5249 	stp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS);
5250 	lop->lo_flags = NFSLCK_WRITE;
5251 	stp->ls_ownerlen = 0;
5252 	stp->ls_op = NULL;
5253 	stp->ls_uid = nd->nd_cred->cr_uid;
5254 	stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
5255 	clientid.lval[0] = stp->ls_stateid.other[0] = *tl++;
5256 	clientid.lval[1] = stp->ls_stateid.other[1] = *tl++;
5257 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
5258 		if ((nd->nd_flag & ND_NFSV41) != 0)
5259 			clientid.qval = nd->nd_clientid.qval;
5260 		else if (nd->nd_clientid.qval != clientid.qval)
5261 			printf("EEK2 multiple clids\n");
5262 	} else {
5263 		if ((nd->nd_flag & ND_NFSV41) != 0)
5264 			printf("EEK! no clientid from session\n");
5265 		nd->nd_flag |= ND_IMPLIEDCLID;
5266 		nd->nd_clientid.qval = clientid.qval;
5267 	}
5268 	stp->ls_stateid.other[2] = *tl++;
5269 	/*
5270 	 * Don't allow this to be done for a DS.
5271 	 */
5272 	if ((nd->nd_flag & ND_DSSERVER) != 0)
5273 		nd->nd_repstat = NFSERR_NOTSUPP;
5274 	/* However, allow the proxy stateid. */
5275 	if (stp->ls_stateid.seqid == 0xffffffff &&
5276 	    stp->ls_stateid.other[0] == 0x55555555 &&
5277 	    stp->ls_stateid.other[1] == 0x55555555 &&
5278 	    stp->ls_stateid.other[2] == 0x55555555)
5279 		gotproxystateid = 1;
5280 	off = fxdr_hyper(tl); tl += 2;
5281 	lop->lo_first = off;
5282 	len = fxdr_hyper(tl);
5283 	lop->lo_end = off + len;
5284 	/*
5285 	 * Paranoia, just in case it wraps around, which shouldn't
5286 	 * ever happen anyhow.
5287 	 */
5288 	if (nd->nd_repstat == 0 && (lop->lo_end < lop->lo_first || len <= 0))
5289 		nd->nd_repstat = NFSERR_INVAL;
5290 
5291 	if (nd->nd_repstat == 0 && vnode_vtype(vp) != VREG)
5292 		nd->nd_repstat = NFSERR_WRONGTYPE;
5293 	NFSZERO_ATTRBIT(&attrbits);
5294 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNER);
5295 	forat_ret = nfsvno_getattr(vp, &forat, nd, curthread, 1, &attrbits);
5296 	if (nd->nd_repstat == 0)
5297 		nd->nd_repstat = forat_ret;
5298 	if (nd->nd_repstat == 0 && (forat.na_uid != nd->nd_cred->cr_uid ||
5299 	     NFSVNO_EXSTRICTACCESS(exp)))
5300 		nd->nd_repstat = nfsvno_accchk(vp, VWRITE, nd->nd_cred, exp,
5301 		    curthread, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED,
5302 		    NULL);
5303 	if (nd->nd_repstat == 0 && gotproxystateid == 0)
5304 		nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid,
5305 		    &stateid, exp, nd, curthread);
5306 
5307 	if (nd->nd_repstat == 0)
5308 		nd->nd_repstat = nfsvno_allocate(vp, off, len, nd->nd_cred,
5309 		    curthread);
5310 	vput(vp);
5311 	NFSEXITCODE2(0, nd);
5312 	return (0);
5313 nfsmout:
5314 	vput(vp);
5315 	NFSEXITCODE2(error, nd);
5316 	return (error);
5317 }
5318 
5319 /*
5320  * nfs copy service
5321  */
5322 int
5323 nfsrvd_copy_file_range(struct nfsrv_descript *nd, __unused int isdgram,
5324     vnode_t vp, vnode_t tovp, struct nfsexstuff *exp, struct nfsexstuff *toexp)
5325 {
5326 	uint32_t *tl;
5327 	struct nfsvattr at;
5328 	int cnt, error = 0, ret;
5329 	off_t inoff, outoff;
5330 	uint64_t len;
5331 	size_t xfer;
5332 	struct nfsstate inst, outst, *instp = &inst, *outstp = &outst;
5333 	struct nfslock inlo, outlo, *inlop = &inlo, *outlop = &outlo;
5334 	nfsquad_t clientid;
5335 	nfsv4stateid_t stateid;
5336 	nfsattrbit_t attrbits;
5337 	void *rl_rcookie, *rl_wcookie;
5338 
5339 	rl_rcookie = rl_wcookie = NULL;
5340 	if (nfsrv_devidcnt > 0) {
5341 		/*
5342 		 * For a pNFS server, reply NFSERR_NOTSUPP so that the client
5343 		 * will do the copy via I/O on the DS(s).
5344 		 */
5345 		nd->nd_repstat = NFSERR_NOTSUPP;
5346 		goto nfsmout;
5347 	}
5348 	if (vp == tovp) {
5349 		/* Copying a byte range within the same file is not allowed. */
5350 		nd->nd_repstat = NFSERR_INVAL;
5351 		goto nfsmout;
5352 	}
5353 	NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_STATEID + 3 * NFSX_HYPER +
5354 	    3 * NFSX_UNSIGNED);
5355 	instp->ls_flags = (NFSLCK_CHECK | NFSLCK_READACCESS);
5356 	inlop->lo_flags = NFSLCK_READ;
5357 	instp->ls_ownerlen = 0;
5358 	instp->ls_op = NULL;
5359 	instp->ls_uid = nd->nd_cred->cr_uid;
5360 	instp->ls_stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
5361 	clientid.lval[0] = instp->ls_stateid.other[0] = *tl++;
5362 	clientid.lval[1] = instp->ls_stateid.other[1] = *tl++;
5363 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0)
5364 		clientid.qval = nd->nd_clientid.qval;
5365 	instp->ls_stateid.other[2] = *tl++;
5366 	outstp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS);
5367 	outlop->lo_flags = NFSLCK_WRITE;
5368 	outstp->ls_ownerlen = 0;
5369 	outstp->ls_op = NULL;
5370 	outstp->ls_uid = nd->nd_cred->cr_uid;
5371 	outstp->ls_stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
5372 	outstp->ls_stateid.other[0] = *tl++;
5373 	outstp->ls_stateid.other[1] = *tl++;
5374 	outstp->ls_stateid.other[2] = *tl++;
5375 	inoff = fxdr_hyper(tl); tl += 2;
5376 	inlop->lo_first = inoff;
5377 	outoff = fxdr_hyper(tl); tl += 2;
5378 	outlop->lo_first = outoff;
5379 	len = fxdr_hyper(tl); tl += 2;
5380 	if (len == 0) {
5381 		/* len == 0 means to EOF. */
5382 		inlop->lo_end = OFF_MAX;
5383 		outlop->lo_end = OFF_MAX;
5384 	} else {
5385 		inlop->lo_end = inlop->lo_first + len;
5386 		outlop->lo_end = outlop->lo_first + len;
5387 	}
5388 
5389 	/*
5390 	 * At this time only consecutive, synchronous copy is supported,
5391 	 * so ca_consecutive and ca_synchronous can be ignored.
5392 	 */
5393 	tl += 2;
5394 
5395 	cnt = fxdr_unsigned(int, *tl);
5396 	if ((nd->nd_flag & ND_DSSERVER) != 0 || cnt != 0)
5397 		nd->nd_repstat = NFSERR_NOTSUPP;
5398 	if (nd->nd_repstat == 0 && (inoff > OFF_MAX || outoff > OFF_MAX ||
5399 	    inlop->lo_end > OFF_MAX || outlop->lo_end > OFF_MAX ||
5400 	    inlop->lo_end < inlop->lo_first || outlop->lo_end <
5401 	    outlop->lo_first))
5402 		nd->nd_repstat = NFSERR_INVAL;
5403 
5404 	if (nd->nd_repstat == 0 && vnode_vtype(vp) != VREG)
5405 		nd->nd_repstat = NFSERR_WRONGTYPE;
5406 
5407 	/* Check permissions for the input file. */
5408 	NFSZERO_ATTRBIT(&attrbits);
5409 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNER);
5410 	ret = nfsvno_getattr(vp, &at, nd, curthread, 1, &attrbits);
5411 	if (nd->nd_repstat == 0)
5412 		nd->nd_repstat = ret;
5413 	if (nd->nd_repstat == 0 && (at.na_uid != nd->nd_cred->cr_uid ||
5414 	     NFSVNO_EXSTRICTACCESS(exp)))
5415 		nd->nd_repstat = nfsvno_accchk(vp, VREAD, nd->nd_cred, exp,
5416 		    curthread, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED,
5417 		    NULL);
5418 	if (nd->nd_repstat == 0)
5419 		nd->nd_repstat = nfsrv_lockctrl(vp, &instp, &inlop, NULL,
5420 		    clientid, &stateid, exp, nd, curthread);
5421 	NFSVOPUNLOCK(vp);
5422 	if (nd->nd_repstat != 0)
5423 		goto out;
5424 
5425 	error = NFSVOPLOCK(tovp, LK_SHARED);
5426 	if (error != 0)
5427 		goto out;
5428 	if (vnode_vtype(tovp) != VREG)
5429 		nd->nd_repstat = NFSERR_WRONGTYPE;
5430 
5431 	/* For the output file, we only need the Owner attribute. */
5432 	ret = nfsvno_getattr(tovp, &at, nd, curthread, 1, &attrbits);
5433 	if (nd->nd_repstat == 0)
5434 		nd->nd_repstat = ret;
5435 	if (nd->nd_repstat == 0 && (at.na_uid != nd->nd_cred->cr_uid ||
5436 	     NFSVNO_EXSTRICTACCESS(exp)))
5437 		nd->nd_repstat = nfsvno_accchk(tovp, VWRITE, nd->nd_cred, toexp,
5438 		    curthread, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED,
5439 		    NULL);
5440 	if (nd->nd_repstat == 0)
5441 		nd->nd_repstat = nfsrv_lockctrl(tovp, &outstp, &outlop, NULL,
5442 		    clientid, &stateid, toexp, nd, curthread);
5443 	NFSVOPUNLOCK(tovp);
5444 
5445 	/* Range lock the byte ranges for both invp and outvp. */
5446 	if (nd->nd_repstat == 0) {
5447 		for (;;) {
5448 			if (len == 0) {
5449 				rl_wcookie = vn_rangelock_wlock(tovp, outoff,
5450 				    OFF_MAX);
5451 				rl_rcookie = vn_rangelock_tryrlock(vp, inoff,
5452 				    OFF_MAX);
5453 			} else {
5454 				rl_wcookie = vn_rangelock_wlock(tovp, outoff,
5455 				    outoff + len);
5456 				rl_rcookie = vn_rangelock_tryrlock(vp, inoff,
5457 				    inoff + len);
5458 			}
5459 			if (rl_rcookie != NULL)
5460 				break;
5461 			vn_rangelock_unlock(tovp, rl_wcookie);
5462 			if (len == 0)
5463 				rl_rcookie = vn_rangelock_rlock(vp, inoff,
5464 				    OFF_MAX);
5465 			else
5466 				rl_rcookie = vn_rangelock_rlock(vp, inoff,
5467 				    inoff + len);
5468 			vn_rangelock_unlock(vp, rl_rcookie);
5469 		}
5470 
5471 		error = NFSVOPLOCK(vp, LK_SHARED);
5472 		if (error == 0) {
5473 			ret = nfsvno_getattr(vp, &at, nd, curthread, 1, NULL);
5474 			if (ret == 0) {
5475 				/*
5476 				 * Since invp is range locked, na_size should
5477 				 * not change.
5478 				 */
5479 				if (len == 0 && at.na_size > inoff) {
5480 					/*
5481 					 * If len == 0, set it based on invp's
5482 					 * size. If offset is past EOF, just
5483 					 * leave len == 0.
5484 					 */
5485 					len = at.na_size - inoff;
5486 				} else if (nfsrv_linux42server == 0 &&
5487 				    inoff + len > at.na_size) {
5488 					/*
5489 					 * RFC-7862 says that NFSERR_INVAL must
5490 					 * be returned when inoff + len exceeds
5491 					 * the file size, however the NFSv4.2
5492 					 * Linux client likes to do this, so
5493 					 * only check if nfsrv_linux42server
5494 					 * is not set.
5495 					 */
5496 					nd->nd_repstat = NFSERR_INVAL;
5497 				}
5498 			}
5499 			NFSVOPUNLOCK(vp);
5500 			if (ret != 0 && nd->nd_repstat == 0)
5501 				nd->nd_repstat = ret;
5502 		} else if (nd->nd_repstat == 0)
5503 			nd->nd_repstat = error;
5504 	}
5505 
5506 	/*
5507 	 * Do the actual copy to an upper limit of vfs.nfs.maxcopyrange.
5508 	 * This limit is applied to ensure that the RPC replies in a
5509 	 * reasonable time.
5510 	 */
5511 	if (len > nfs_maxcopyrange)
5512 		xfer = nfs_maxcopyrange;
5513 	else
5514 		xfer = len;
5515 	if (nd->nd_repstat == 0) {
5516 		nd->nd_repstat = vn_copy_file_range(vp, &inoff, tovp, &outoff,
5517 		    &xfer, 0, nd->nd_cred, nd->nd_cred, NULL);
5518 		if (nd->nd_repstat == 0)
5519 			len = xfer;
5520 	}
5521 
5522 	/* Unlock the ranges. */
5523 	if (rl_rcookie != NULL)
5524 		vn_rangelock_unlock(vp, rl_rcookie);
5525 	if (rl_wcookie != NULL)
5526 		vn_rangelock_unlock(tovp, rl_wcookie);
5527 
5528 	if (nd->nd_repstat == 0) {
5529 		NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED + NFSX_HYPER +
5530 		    NFSX_VERF);
5531 		*tl++ = txdr_unsigned(0);	/* No callback ids. */
5532 		txdr_hyper(len, tl); tl += 2;
5533 		*tl++ = txdr_unsigned(NFSWRITE_UNSTABLE);
5534 		*tl++ = txdr_unsigned(nfsboottime.tv_sec);
5535 		*tl++ = txdr_unsigned(nfsboottime.tv_usec);
5536 		*tl++ = newnfs_true;
5537 		*tl = newnfs_true;
5538 	}
5539 out:
5540 	vrele(vp);
5541 	vrele(tovp);
5542 	NFSEXITCODE2(error, nd);
5543 	return (error);
5544 nfsmout:
5545 	vput(vp);
5546 	vrele(tovp);
5547 	NFSEXITCODE2(error, nd);
5548 	return (error);
5549 }
5550 
5551 /*
5552  * nfs seek service
5553  */
5554 int
5555 nfsrvd_seek(struct nfsrv_descript *nd, __unused int isdgram,
5556     vnode_t vp, struct nfsexstuff *exp)
5557 {
5558 	uint32_t *tl;
5559 	struct nfsvattr at;
5560 	int content, error = 0;
5561 	off_t off;
5562 	u_long cmd;
5563 	nfsattrbit_t attrbits;
5564 	bool eof;
5565 
5566 	NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID + NFSX_HYPER + NFSX_UNSIGNED);
5567 	/* Ignore the stateid for now. */
5568 	tl += (NFSX_STATEID / NFSX_UNSIGNED);
5569 	off = fxdr_hyper(tl); tl += 2;
5570 	content = fxdr_unsigned(int, *tl);
5571 	if (content == NFSV4CONTENT_DATA)
5572 		cmd = FIOSEEKDATA;
5573 	else if (content == NFSV4CONTENT_HOLE)
5574 		cmd = FIOSEEKHOLE;
5575 	else
5576 		nd->nd_repstat = NFSERR_BADXDR;
5577 	if (nd->nd_repstat == 0 && vnode_vtype(vp) == VDIR)
5578 		nd->nd_repstat = NFSERR_ISDIR;
5579 	if (nd->nd_repstat == 0 && vnode_vtype(vp) != VREG)
5580 		nd->nd_repstat = NFSERR_WRONGTYPE;
5581 	if (nd->nd_repstat == 0 && off < 0)
5582 		nd->nd_repstat = NFSERR_NXIO;
5583 	if (nd->nd_repstat == 0) {
5584 		/* Check permissions for the input file. */
5585 		NFSZERO_ATTRBIT(&attrbits);
5586 		NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNER);
5587 		nd->nd_repstat = nfsvno_getattr(vp, &at, nd, curthread, 1,
5588 		    &attrbits);
5589 	}
5590 	if (nd->nd_repstat == 0 && (at.na_uid != nd->nd_cred->cr_uid ||
5591 	     NFSVNO_EXSTRICTACCESS(exp)))
5592 		nd->nd_repstat = nfsvno_accchk(vp, VREAD, nd->nd_cred, exp,
5593 		    curthread, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED,
5594 		    NULL);
5595 	if (nd->nd_repstat != 0)
5596 		goto nfsmout;
5597 
5598 	/* nfsvno_seek() unlocks and vrele()s the vp. */
5599 	nd->nd_repstat = nfsvno_seek(nd, vp, cmd, &off, content, &eof,
5600 	    nd->nd_cred, curthread);
5601 	if (nd->nd_repstat == 0 && eof && content == NFSV4CONTENT_DATA &&
5602 	    nfsrv_linux42server != 0)
5603 		nd->nd_repstat = NFSERR_NXIO;
5604 	if (nd->nd_repstat == 0) {
5605 		NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED + NFSX_HYPER);
5606 		if (eof)
5607 			*tl++ = newnfs_true;
5608 		else
5609 			*tl++ = newnfs_false;
5610 		txdr_hyper(off, tl);
5611 	}
5612 	NFSEXITCODE2(error, nd);
5613 	return (error);
5614 nfsmout:
5615 	vput(vp);
5616 	NFSEXITCODE2(error, nd);
5617 	return (error);
5618 }
5619 
5620 /*
5621  * nfs get extended attribute service
5622  */
5623 int
5624 nfsrvd_getxattr(struct nfsrv_descript *nd, __unused int isdgram,
5625     vnode_t vp, __unused struct nfsexstuff *exp)
5626 {
5627 	uint32_t *tl;
5628 	struct mbuf *mp = NULL, *mpend = NULL;
5629 	int error, len;
5630 	char *name;
5631 	struct thread *p = curthread;
5632 	uint16_t off;
5633 
5634 	error = 0;
5635 	NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
5636 	len = fxdr_unsigned(int, *tl);
5637 	if (len <= 0) {
5638 		nd->nd_repstat = NFSERR_BADXDR;
5639 		goto nfsmout;
5640 	}
5641 	if (len > EXTATTR_MAXNAMELEN) {
5642 		nd->nd_repstat = NFSERR_NOXATTR;
5643 		goto nfsmout;
5644 	}
5645 	name = malloc(len + 1, M_TEMP, M_WAITOK);
5646 	nd->nd_repstat = nfsrv_mtostr(nd, name, len);
5647 	if (nd->nd_repstat == 0)
5648 		nd->nd_repstat = nfsvno_getxattr(vp, name,
5649 		    nd->nd_maxresp, nd->nd_cred, nd->nd_flag,
5650 		    nd->nd_maxextsiz, p, &mp, &mpend, &len);
5651 	if (nd->nd_repstat == ENOATTR)
5652 		nd->nd_repstat = NFSERR_NOXATTR;
5653 	else if (nd->nd_repstat == EOPNOTSUPP)
5654 		nd->nd_repstat = NFSERR_NOTSUPP;
5655 	if (nd->nd_repstat == 0) {
5656 		NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
5657 		*tl = txdr_unsigned(len);
5658 		if (len > 0) {
5659 			nd->nd_mb->m_next = mp;
5660 			nd->nd_mb = mpend;
5661 			if ((mpend->m_flags & M_EXTPG) != 0) {
5662 				nd->nd_flag |= ND_EXTPG;
5663 				nd->nd_bextpg = mpend->m_epg_npgs - 1;
5664 				nd->nd_bpos = (char *)(void *)
5665 				   PHYS_TO_DMAP(mpend->m_epg_pa[nd->nd_bextpg]);
5666 				off = (nd->nd_bextpg == 0) ?
5667 				    mpend->m_epg_1st_off : 0;
5668 				nd->nd_bpos += off + mpend->m_epg_last_len;
5669 				nd->nd_bextpgsiz = PAGE_SIZE -
5670 				    mpend->m_epg_last_len - off;
5671 			} else
5672 				nd->nd_bpos = mtod(mpend, char *) +
5673 				    mpend->m_len;
5674 		}
5675 	}
5676 	free(name, M_TEMP);
5677 
5678 nfsmout:
5679 	if (nd->nd_repstat == 0)
5680 		nd->nd_repstat = error;
5681 	vput(vp);
5682 	NFSEXITCODE2(0, nd);
5683 	return (0);
5684 }
5685 
5686 /*
5687  * nfs set extended attribute service
5688  */
5689 int
5690 nfsrvd_setxattr(struct nfsrv_descript *nd, __unused int isdgram,
5691     vnode_t vp, __unused struct nfsexstuff *exp)
5692 {
5693 	uint32_t *tl;
5694 	struct nfsvattr ova, nva;
5695 	nfsattrbit_t attrbits;
5696 	int error, len, opt;
5697 	char *name;
5698 	size_t siz;
5699 	struct thread *p = curthread;
5700 
5701 	error = 0;
5702 	name = NULL;
5703 	NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
5704 	opt = fxdr_unsigned(int, *tl++);
5705 	len = fxdr_unsigned(int, *tl);
5706 	if (len <= 0) {
5707 		nd->nd_repstat = NFSERR_BADXDR;
5708 		goto nfsmout;
5709 	}
5710 	if (len > EXTATTR_MAXNAMELEN) {
5711 		nd->nd_repstat = NFSERR_NOXATTR;
5712 		goto nfsmout;
5713 	}
5714 	name = malloc(len + 1, M_TEMP, M_WAITOK);
5715 	error = nfsrv_mtostr(nd, name, len);
5716 	if (error != 0)
5717 		goto nfsmout;
5718 	NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
5719 	len = fxdr_unsigned(int, *tl);
5720 	if (len < 0 || len > IOSIZE_MAX) {
5721 		nd->nd_repstat = NFSERR_XATTR2BIG;
5722 		goto nfsmout;
5723 	}
5724 	switch (opt) {
5725 	case NFSV4SXATTR_CREATE:
5726 		error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, NULL,
5727 		    &siz, nd->nd_cred, p);
5728 		if (error != ENOATTR)
5729 			nd->nd_repstat = NFSERR_EXIST;
5730 		error = 0;
5731 		break;
5732 	case NFSV4SXATTR_REPLACE:
5733 		error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, NULL,
5734 		    &siz, nd->nd_cred, p);
5735 		if (error != 0)
5736 			nd->nd_repstat = NFSERR_NOXATTR;
5737 		break;
5738 	case NFSV4SXATTR_EITHER:
5739 		break;
5740 	default:
5741 		nd->nd_repstat = NFSERR_BADXDR;
5742 	}
5743 	if (nd->nd_repstat != 0)
5744 		goto nfsmout;
5745 
5746 	/* Now, do the Set Extended attribute, with Change before and after. */
5747 	NFSZERO_ATTRBIT(&attrbits);
5748 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE);
5749 	nd->nd_repstat = nfsvno_getattr(vp, &ova, nd, p, 1, &attrbits);
5750 	if (nd->nd_repstat == 0) {
5751 		nd->nd_repstat = nfsvno_setxattr(vp, name, len, nd->nd_md,
5752 		    nd->nd_dpos, nd->nd_cred, p);
5753 		if (nd->nd_repstat == ENXIO)
5754 			nd->nd_repstat = NFSERR_XATTR2BIG;
5755 	}
5756 	if (nd->nd_repstat == 0 && len > 0)
5757 		nd->nd_repstat = nfsm_advance(nd, NFSM_RNDUP(len), -1);
5758 	if (nd->nd_repstat == 0)
5759 		nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, &attrbits);
5760 	if (nd->nd_repstat == 0) {
5761 		NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_UNSIGNED);
5762 		*tl++ = newnfs_true;
5763 		txdr_hyper(ova.na_filerev, tl); tl += 2;
5764 		txdr_hyper(nva.na_filerev, tl);
5765 	}
5766 
5767 nfsmout:
5768 	free(name, M_TEMP);
5769 	if (nd->nd_repstat == 0)
5770 		nd->nd_repstat = error;
5771 	vput(vp);
5772 	NFSEXITCODE2(0, nd);
5773 	return (0);
5774 }
5775 
5776 /*
5777  * nfs remove extended attribute service
5778  */
5779 int
5780 nfsrvd_rmxattr(struct nfsrv_descript *nd, __unused int isdgram,
5781     vnode_t vp, __unused struct nfsexstuff *exp)
5782 {
5783 	uint32_t *tl;
5784 	struct nfsvattr ova, nva;
5785 	nfsattrbit_t attrbits;
5786 	int error, len;
5787 	char *name;
5788 	struct thread *p = curthread;
5789 
5790 	error = 0;
5791 	name = NULL;
5792 	NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
5793 	len = fxdr_unsigned(int, *tl);
5794 	if (len <= 0) {
5795 		nd->nd_repstat = NFSERR_BADXDR;
5796 		goto nfsmout;
5797 	}
5798 	if (len > EXTATTR_MAXNAMELEN) {
5799 		nd->nd_repstat = NFSERR_NOXATTR;
5800 		goto nfsmout;
5801 	}
5802 	name = malloc(len + 1, M_TEMP, M_WAITOK);
5803 	error = nfsrv_mtostr(nd, name, len);
5804 	if (error != 0)
5805 		goto nfsmout;
5806 
5807 	if ((nd->nd_flag & ND_IMPLIEDCLID) == 0) {
5808 		printf("EEK! nfsrvd_rmxattr: no implied clientid\n");
5809 		error = NFSERR_NOXATTR;
5810 		goto nfsmout;
5811 	}
5812 	/*
5813 	 * Now, do the Remove Extended attribute, with Change before and
5814 	 * after.
5815 	*/
5816 	NFSZERO_ATTRBIT(&attrbits);
5817 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE);
5818 	nd->nd_repstat = nfsvno_getattr(vp, &ova, nd, p, 1, &attrbits);
5819 	if (nd->nd_repstat == 0) {
5820 		nd->nd_repstat = nfsvno_rmxattr(nd, vp, name, nd->nd_cred, p);
5821 		if (nd->nd_repstat == ENOATTR)
5822 			nd->nd_repstat = NFSERR_NOXATTR;
5823 	}
5824 	if (nd->nd_repstat == 0)
5825 		nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, &attrbits);
5826 	if (nd->nd_repstat == 0) {
5827 		NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_UNSIGNED);
5828 		*tl++ = newnfs_true;
5829 		txdr_hyper(ova.na_filerev, tl); tl += 2;
5830 		txdr_hyper(nva.na_filerev, tl);
5831 	}
5832 
5833 nfsmout:
5834 	free(name, M_TEMP);
5835 	if (nd->nd_repstat == 0)
5836 		nd->nd_repstat = error;
5837 	vput(vp);
5838 	NFSEXITCODE2(0, nd);
5839 	return (0);
5840 }
5841 
5842 /*
5843  * nfs list extended attribute service
5844  */
5845 int
5846 nfsrvd_listxattr(struct nfsrv_descript *nd, __unused int isdgram,
5847     vnode_t vp, __unused struct nfsexstuff *exp)
5848 {
5849 	uint32_t cnt, *tl, len, len2, i, pos, retlen;
5850 	int error;
5851 	uint64_t cookie, cookie2;
5852 	u_char *buf;
5853 	bool eof;
5854 	struct thread *p = curthread;
5855 
5856 	error = 0;
5857 	buf = NULL;
5858 	NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + NFSX_UNSIGNED);
5859 	/*
5860 	 * The cookie doesn't need to be in net byte order, but FreeBSD
5861 	 * does so to make it more readable in packet traces.
5862 	 */
5863 	cookie = fxdr_hyper(tl); tl += 2;
5864 	len = fxdr_unsigned(uint32_t, *tl);
5865 	if (len == 0 || cookie >= IOSIZE_MAX) {
5866 		nd->nd_repstat = NFSERR_BADXDR;
5867 		goto nfsmout;
5868 	}
5869 	if (len > nd->nd_maxresp - NFS_MAXXDR)
5870 		len = nd->nd_maxresp - NFS_MAXXDR;
5871 	len2 = len;
5872 	nd->nd_repstat = nfsvno_listxattr(vp, cookie, nd->nd_cred, p, &buf,
5873 	    &len, &eof);
5874 	if (nd->nd_repstat == EOPNOTSUPP)
5875 		nd->nd_repstat = NFSERR_NOTSUPP;
5876 	if (nd->nd_repstat == 0) {
5877 		cookie2 = cookie + len;
5878 		if (cookie2 < cookie)
5879 			nd->nd_repstat = NFSERR_BADXDR;
5880 	}
5881 	if (nd->nd_repstat == 0) {
5882 		/* Now copy the entries out. */
5883 		retlen = NFSX_HYPER + 2 * NFSX_UNSIGNED;
5884 		if (len == 0 && retlen <= len2) {
5885 			/* The cookie was at eof. */
5886 			NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + 2 *
5887 			    NFSX_UNSIGNED);
5888 			txdr_hyper(cookie2, tl); tl += 2;
5889 			*tl++ = txdr_unsigned(0);
5890 			*tl = newnfs_true;
5891 			goto nfsmout;
5892 		}
5893 
5894 		/* Sanity check the cookie. */
5895 		for (pos = 0; pos < len; pos += (i + 1)) {
5896 			if (pos == cookie)
5897 				break;
5898 			i = buf[pos];
5899 		}
5900 		if (pos != cookie) {
5901 			nd->nd_repstat = NFSERR_INVAL;
5902 			goto nfsmout;
5903 		}
5904 
5905 		/* Loop around copying the entrie(s) out. */
5906 		cnt = 0;
5907 		len -= cookie;
5908 		i = buf[pos];
5909 		while (i < len && len2 >= retlen + NFSM_RNDUP(i) +
5910 		    NFSX_UNSIGNED) {
5911 			if (cnt == 0) {
5912 				NFSM_BUILD(tl, uint32_t *, NFSX_HYPER +
5913 				    NFSX_UNSIGNED);
5914 				txdr_hyper(cookie2, tl); tl += 2;
5915 			}
5916 			retlen += nfsm_strtom(nd, &buf[pos + 1], i);
5917 			len -= (i + 1);
5918 			pos += (i + 1);
5919 			i = buf[pos];
5920 			cnt++;
5921 		}
5922 		/*
5923 		 * eof is set true/false by nfsvno_listxattr(), but if we
5924 		 * can't copy all entries returned by nfsvno_listxattr(),
5925 		 * we are not at eof.
5926 		 */
5927 		if (len > 0)
5928 			eof = false;
5929 		if (cnt > 0) {
5930 			/* *tl is set above. */
5931 			*tl = txdr_unsigned(cnt);
5932 			NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
5933 			if (eof)
5934 				*tl = newnfs_true;
5935 			else
5936 				*tl = newnfs_false;
5937 		} else
5938 			nd->nd_repstat = NFSERR_TOOSMALL;
5939 	}
5940 
5941 nfsmout:
5942 	free(buf, M_TEMP);
5943 	if (nd->nd_repstat == 0)
5944 		nd->nd_repstat = error;
5945 	vput(vp);
5946 	NFSEXITCODE2(0, nd);
5947 	return (0);
5948 }
5949 
5950 /*
5951  * nfsv4 service not supported
5952  */
5953 int
5954 nfsrvd_notsupp(struct nfsrv_descript *nd, __unused int isdgram,
5955     __unused vnode_t vp, __unused struct nfsexstuff *exp)
5956 {
5957 
5958 	nd->nd_repstat = NFSERR_NOTSUPP;
5959 	NFSEXITCODE2(0, nd);
5960 	return (0);
5961 }
5962