xref: /freebsd/sys/fs/nfsserver/nfs_nfsdserv.c (revision 8c2dd68caa963f1900a8228b0732b04f5d530ffa)
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, -1);	/* 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,
1804 			    0, -1);
1805 			if (dp)
1806 				NFSVOPUNLOCK(dp);
1807 		}
1808 	}
1809 	NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
1810 	    LOCKPARENT | SAVENAME | NOCACHE);
1811 	if (!nd->nd_repstat) {
1812 		nfsvno_setpathbuf(&named, &bufp, &hashp);
1813 		error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
1814 		if (error) {
1815 			vrele(vp);
1816 			if (dp)
1817 				vrele(dp);
1818 			nfsvno_relpathbuf(&named);
1819 			goto out;
1820 		}
1821 		if (!nd->nd_repstat) {
1822 			nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, &tnes,
1823 			    p, &dirp);
1824 		} else {
1825 			if (dp)
1826 				vrele(dp);
1827 			nfsvno_relpathbuf(&named);
1828 		}
1829 	}
1830 	if (dirp) {
1831 		if (nd->nd_flag & ND_NFSV2) {
1832 			vrele(dirp);
1833 			dirp = NULL;
1834 		} else {
1835 			dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0,
1836 			    NULL);
1837 		}
1838 	}
1839 	if (!nd->nd_repstat)
1840 		nd->nd_repstat = nfsvno_link(&named, vp, nd->nd_cred, p, exp);
1841 	if (nd->nd_flag & ND_NFSV3)
1842 		getret = nfsvno_getattr(vp, &at, nd, p, 0, NULL);
1843 	if (dirp) {
1844 		diraft_ret = nfsvno_getattr(dirp, &diraft, nd, p, 0, NULL);
1845 		vrele(dirp);
1846 	}
1847 	vrele(vp);
1848 	if (nd->nd_flag & ND_NFSV3) {
1849 		nfsrv_postopattr(nd, getret, &at);
1850 		nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1851 	} else if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) {
1852 		NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1853 		*tl++ = newnfs_false;
1854 		txdr_hyper(dirfor.na_filerev, tl);
1855 		tl += 2;
1856 		txdr_hyper(diraft.na_filerev, tl);
1857 	}
1858 
1859 out:
1860 	NFSEXITCODE2(error, nd);
1861 	return (error);
1862 }
1863 
1864 /*
1865  * nfs symbolic link service
1866  */
1867 int
1868 nfsrvd_symlink(struct nfsrv_descript *nd, __unused int isdgram,
1869     vnode_t dp, vnode_t *vpp, fhandle_t *fhp, struct nfsexstuff *exp)
1870 {
1871 	struct nfsvattr nva, dirfor, diraft;
1872 	struct nameidata named;
1873 	int error = 0, dirfor_ret = 1, diraft_ret = 1, pathlen;
1874 	vnode_t dirp = NULL;
1875 	char *bufp, *pathcp = NULL;
1876 	u_long *hashp;
1877 	struct thread *p = curthread;
1878 
1879 	if (nd->nd_repstat) {
1880 		nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1881 		goto out;
1882 	}
1883 	if (vpp)
1884 		*vpp = NULL;
1885 	NFSVNO_ATTRINIT(&nva);
1886 	NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
1887 	    LOCKPARENT | SAVESTART | NOCACHE);
1888 	nfsvno_setpathbuf(&named, &bufp, &hashp);
1889 	error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
1890 	if (!error && !nd->nd_repstat)
1891 		error = nfsvno_getsymlink(nd, &nva, p, &pathcp, &pathlen);
1892 	if (error) {
1893 		vrele(dp);
1894 		nfsvno_relpathbuf(&named);
1895 		goto out;
1896 	}
1897 	if (!nd->nd_repstat) {
1898 		nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp);
1899 	} else {
1900 		vrele(dp);
1901 		nfsvno_relpathbuf(&named);
1902 	}
1903 	if (dirp != NULL && !(nd->nd_flag & ND_NFSV3)) {
1904 		vrele(dirp);
1905 		dirp = NULL;
1906 	}
1907 
1908 	/*
1909 	 * And call nfsrvd_symlinksub() to do the common code. It will
1910 	 * return EBADRPC upon a parsing error, 0 otherwise.
1911 	 */
1912 	if (!nd->nd_repstat) {
1913 		if (dirp != NULL)
1914 			dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0,
1915 			    NULL);
1916 		nfsrvd_symlinksub(nd, &named, &nva, fhp, vpp, dirp,
1917 		    &dirfor, &diraft, &diraft_ret, NULL, NULL, p, exp,
1918 		    pathcp, pathlen);
1919 	} else if (dirp != NULL) {
1920 		dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0, NULL);
1921 		vrele(dirp);
1922 	}
1923 	if (pathcp)
1924 		free(pathcp, M_TEMP);
1925 
1926 	if (nd->nd_flag & ND_NFSV3) {
1927 		if (!nd->nd_repstat) {
1928 			(void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 1);
1929 			nfsrv_postopattr(nd, 0, &nva);
1930 		}
1931 		nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
1932 	}
1933 
1934 out:
1935 	NFSEXITCODE2(error, nd);
1936 	return (error);
1937 }
1938 
1939 /*
1940  * Common code for creating a symbolic link.
1941  */
1942 static void
1943 nfsrvd_symlinksub(struct nfsrv_descript *nd, struct nameidata *ndp,
1944     struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp,
1945     vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp,
1946     int *diraft_retp, nfsattrbit_t *attrbitp,
1947     NFSACL_T *aclp, NFSPROC_T *p, struct nfsexstuff *exp, char *pathcp,
1948     int pathlen)
1949 {
1950 	u_int32_t *tl;
1951 
1952 	nd->nd_repstat = nfsvno_symlink(ndp, nvap, pathcp, pathlen,
1953 	    !(nd->nd_flag & ND_NFSV2), nd->nd_saveduid, nd->nd_cred, p, exp);
1954 	if (!nd->nd_repstat && !(nd->nd_flag & ND_NFSV2)) {
1955 		nfsrv_fixattr(nd, ndp->ni_vp, nvap, aclp, p, attrbitp, exp);
1956 		if (nd->nd_flag & ND_NFSV3) {
1957 			nd->nd_repstat = nfsvno_getfh(ndp->ni_vp, fhp, p);
1958 			if (!nd->nd_repstat)
1959 				nd->nd_repstat = nfsvno_getattr(ndp->ni_vp,
1960 				    nvap, nd, p, 1, NULL);
1961 		}
1962 		if (vpp != NULL && nd->nd_repstat == 0) {
1963 			NFSVOPUNLOCK(ndp->ni_vp);
1964 			*vpp = ndp->ni_vp;
1965 		} else
1966 			vput(ndp->ni_vp);
1967 	}
1968 	if (dirp) {
1969 		*diraft_retp = nfsvno_getattr(dirp, diraftp, nd, p, 0, NULL);
1970 		vrele(dirp);
1971 	}
1972 	if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) {
1973 		NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1974 		*tl++ = newnfs_false;
1975 		txdr_hyper(dirforp->na_filerev, tl);
1976 		tl += 2;
1977 		txdr_hyper(diraftp->na_filerev, tl);
1978 		(void) nfsrv_putattrbit(nd, attrbitp);
1979 	}
1980 
1981 	NFSEXITCODE2(0, nd);
1982 }
1983 
1984 /*
1985  * nfs mkdir service
1986  */
1987 int
1988 nfsrvd_mkdir(struct nfsrv_descript *nd, __unused int isdgram,
1989     vnode_t dp, vnode_t *vpp, fhandle_t *fhp, struct nfsexstuff *exp)
1990 {
1991 	struct nfsvattr nva, dirfor, diraft;
1992 	struct nameidata named;
1993 	u_int32_t *tl;
1994 	int error = 0, dirfor_ret = 1, diraft_ret = 1;
1995 	vnode_t dirp = NULL;
1996 	char *bufp;
1997 	u_long *hashp;
1998 	struct thread *p = curthread;
1999 
2000 	if (nd->nd_repstat) {
2001 		nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
2002 		goto out;
2003 	}
2004 	NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
2005 	    LOCKPARENT | SAVENAME | NOCACHE);
2006 	nfsvno_setpathbuf(&named, &bufp, &hashp);
2007 	error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
2008 	if (error)
2009 		goto nfsmout;
2010 	if (!nd->nd_repstat) {
2011 		NFSVNO_ATTRINIT(&nva);
2012 		if (nd->nd_flag & ND_NFSV3) {
2013 			error = nfsrv_sattr(nd, NULL, &nva, NULL, NULL, p);
2014 			if (error)
2015 				goto nfsmout;
2016 		} else {
2017 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2018 			nva.na_mode = nfstov_mode(*tl++);
2019 		}
2020 	}
2021 	if (!nd->nd_repstat) {
2022 		nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp);
2023 	} else {
2024 		vrele(dp);
2025 		nfsvno_relpathbuf(&named);
2026 	}
2027 	if (dirp != NULL && !(nd->nd_flag & ND_NFSV3)) {
2028 		vrele(dirp);
2029 		dirp = NULL;
2030 	}
2031 	if (nd->nd_repstat) {
2032 		if (dirp != NULL) {
2033 			dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0,
2034 			    NULL);
2035 			vrele(dirp);
2036 		}
2037 		if (nd->nd_flag & ND_NFSV3)
2038 			nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
2039 			    &diraft);
2040 		goto out;
2041 	}
2042 	if (dirp != NULL)
2043 		dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0, NULL);
2044 
2045 	/*
2046 	 * Call nfsrvd_mkdirsub() for the code common to V4 as well.
2047 	 */
2048 	nfsrvd_mkdirsub(nd, &named, &nva, fhp, vpp, dirp, &dirfor, &diraft,
2049 	    &diraft_ret, NULL, NULL, p, exp);
2050 
2051 	if (nd->nd_flag & ND_NFSV3) {
2052 		if (!nd->nd_repstat) {
2053 			(void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 1);
2054 			nfsrv_postopattr(nd, 0, &nva);
2055 		}
2056 		nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
2057 	} else if (!nd->nd_repstat) {
2058 		(void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 0);
2059 		nfsrv_fillattr(nd, &nva);
2060 	}
2061 
2062 out:
2063 	NFSEXITCODE2(0, nd);
2064 	return (0);
2065 nfsmout:
2066 	vrele(dp);
2067 	nfsvno_relpathbuf(&named);
2068 	NFSEXITCODE2(error, nd);
2069 	return (error);
2070 }
2071 
2072 /*
2073  * Code common to mkdir for V2,3 and 4.
2074  */
2075 static void
2076 nfsrvd_mkdirsub(struct nfsrv_descript *nd, struct nameidata *ndp,
2077     struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp,
2078     vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp,
2079     int *diraft_retp, nfsattrbit_t *attrbitp, NFSACL_T *aclp,
2080     NFSPROC_T *p, struct nfsexstuff *exp)
2081 {
2082 	vnode_t vp;
2083 	u_int32_t *tl;
2084 
2085 	NFSVNO_SETATTRVAL(nvap, type, VDIR);
2086 	nd->nd_repstat = nfsvno_mkdir(ndp, nvap, nd->nd_saveduid,
2087 	    nd->nd_cred, p, exp);
2088 	if (!nd->nd_repstat) {
2089 		vp = ndp->ni_vp;
2090 		nfsrv_fixattr(nd, vp, nvap, aclp, p, attrbitp, exp);
2091 		nd->nd_repstat = nfsvno_getfh(vp, fhp, p);
2092 		if (!(nd->nd_flag & ND_NFSV4) && !nd->nd_repstat)
2093 			nd->nd_repstat = nfsvno_getattr(vp, nvap, nd, p, 1,
2094 			    NULL);
2095 		if (vpp && !nd->nd_repstat) {
2096 			NFSVOPUNLOCK(vp);
2097 			*vpp = vp;
2098 		} else {
2099 			vput(vp);
2100 		}
2101 	}
2102 	if (dirp) {
2103 		*diraft_retp = nfsvno_getattr(dirp, diraftp, nd, p, 0, NULL);
2104 		vrele(dirp);
2105 	}
2106 	if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) {
2107 		NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
2108 		*tl++ = newnfs_false;
2109 		txdr_hyper(dirforp->na_filerev, tl);
2110 		tl += 2;
2111 		txdr_hyper(diraftp->na_filerev, tl);
2112 		(void) nfsrv_putattrbit(nd, attrbitp);
2113 	}
2114 
2115 	NFSEXITCODE2(0, nd);
2116 }
2117 
2118 /*
2119  * nfs commit service
2120  */
2121 int
2122 nfsrvd_commit(struct nfsrv_descript *nd, __unused int isdgram,
2123     vnode_t vp, __unused struct nfsexstuff *exp)
2124 {
2125 	struct nfsvattr bfor, aft;
2126 	u_int32_t *tl;
2127 	int error = 0, for_ret = 1, aft_ret = 1, cnt;
2128 	u_int64_t off;
2129 	struct thread *p = curthread;
2130 
2131        if (nd->nd_repstat) {
2132 		nfsrv_wcc(nd, for_ret, &bfor, aft_ret, &aft);
2133 		goto out;
2134 	}
2135 
2136 	/* Return NFSERR_ISDIR in NFSv4 when commit on a directory. */
2137 	if (vp->v_type != VREG) {
2138 		if (nd->nd_flag & ND_NFSV3)
2139 			error = NFSERR_NOTSUPP;
2140 		else
2141 			error = (vp->v_type == VDIR) ? NFSERR_ISDIR : NFSERR_INVAL;
2142 		goto nfsmout;
2143 	}
2144 	NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2145 
2146 	/*
2147 	 * XXX At this time VOP_FSYNC() does not accept offset and byte
2148 	 * count parameters, so these arguments are useless (someday maybe).
2149 	 */
2150 	off = fxdr_hyper(tl);
2151 	tl += 2;
2152 	cnt = fxdr_unsigned(int, *tl);
2153 	if (nd->nd_flag & ND_NFSV3)
2154 		for_ret = nfsvno_getattr(vp, &bfor, nd, p, 1, NULL);
2155 	nd->nd_repstat = nfsvno_fsync(vp, off, cnt, nd->nd_cred, p);
2156 	if (nd->nd_flag & ND_NFSV3) {
2157 		aft_ret = nfsvno_getattr(vp, &aft, nd, p, 1, NULL);
2158 		nfsrv_wcc(nd, for_ret, &bfor, aft_ret, &aft);
2159 	}
2160 	vput(vp);
2161 	if (!nd->nd_repstat) {
2162 		NFSM_BUILD(tl, u_int32_t *, NFSX_VERF);
2163 		*tl++ = txdr_unsigned(nfsboottime.tv_sec);
2164 		*tl = txdr_unsigned(nfsboottime.tv_usec);
2165 	}
2166 
2167 out:
2168 	NFSEXITCODE2(0, nd);
2169 	return (0);
2170 nfsmout:
2171 	vput(vp);
2172 	NFSEXITCODE2(error, nd);
2173 	return (error);
2174 }
2175 
2176 /*
2177  * nfs statfs service
2178  */
2179 int
2180 nfsrvd_statfs(struct nfsrv_descript *nd, __unused int isdgram,
2181     vnode_t vp, __unused struct nfsexstuff *exp)
2182 {
2183 	struct statfs *sf;
2184 	u_int32_t *tl;
2185 	int getret = 1;
2186 	struct nfsvattr at;
2187 	u_quad_t tval;
2188 	struct thread *p = curthread;
2189 
2190 	sf = NULL;
2191 	if (nd->nd_repstat) {
2192 		nfsrv_postopattr(nd, getret, &at);
2193 		goto out;
2194 	}
2195 	sf = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
2196 	nd->nd_repstat = nfsvno_statfs(vp, sf);
2197 	getret = nfsvno_getattr(vp, &at, nd, p, 1, NULL);
2198 	vput(vp);
2199 	if (nd->nd_flag & ND_NFSV3)
2200 		nfsrv_postopattr(nd, getret, &at);
2201 	if (nd->nd_repstat)
2202 		goto out;
2203 	if (nd->nd_flag & ND_NFSV2) {
2204 		NFSM_BUILD(tl, u_int32_t *, NFSX_V2STATFS);
2205 		*tl++ = txdr_unsigned(NFS_V2MAXDATA);
2206 		*tl++ = txdr_unsigned(sf->f_bsize);
2207 		*tl++ = txdr_unsigned(sf->f_blocks);
2208 		*tl++ = txdr_unsigned(sf->f_bfree);
2209 		*tl = txdr_unsigned(sf->f_bavail);
2210 	} else {
2211 		NFSM_BUILD(tl, u_int32_t *, NFSX_V3STATFS);
2212 		tval = (u_quad_t)sf->f_blocks;
2213 		tval *= (u_quad_t)sf->f_bsize;
2214 		txdr_hyper(tval, tl); tl += 2;
2215 		tval = (u_quad_t)sf->f_bfree;
2216 		tval *= (u_quad_t)sf->f_bsize;
2217 		txdr_hyper(tval, tl); tl += 2;
2218 		tval = (u_quad_t)sf->f_bavail;
2219 		tval *= (u_quad_t)sf->f_bsize;
2220 		txdr_hyper(tval, tl); tl += 2;
2221 		tval = (u_quad_t)sf->f_files;
2222 		txdr_hyper(tval, tl); tl += 2;
2223 		tval = (u_quad_t)sf->f_ffree;
2224 		txdr_hyper(tval, tl); tl += 2;
2225 		tval = (u_quad_t)sf->f_ffree;
2226 		txdr_hyper(tval, tl); tl += 2;
2227 		*tl = 0;
2228 	}
2229 
2230 out:
2231 	free(sf, M_STATFS);
2232 	NFSEXITCODE2(0, nd);
2233 	return (0);
2234 }
2235 
2236 /*
2237  * nfs fsinfo service
2238  */
2239 int
2240 nfsrvd_fsinfo(struct nfsrv_descript *nd, int isdgram,
2241     vnode_t vp, __unused struct nfsexstuff *exp)
2242 {
2243 	u_int32_t *tl;
2244 	struct nfsfsinfo fs;
2245 	int getret = 1;
2246 	struct nfsvattr at;
2247 	struct thread *p = curthread;
2248 
2249 	if (nd->nd_repstat) {
2250 		nfsrv_postopattr(nd, getret, &at);
2251 		goto out;
2252 	}
2253 	getret = nfsvno_getattr(vp, &at, nd, p, 1, NULL);
2254 	nfsvno_getfs(&fs, isdgram);
2255 	vput(vp);
2256 	nfsrv_postopattr(nd, getret, &at);
2257 	NFSM_BUILD(tl, u_int32_t *, NFSX_V3FSINFO);
2258 	*tl++ = txdr_unsigned(fs.fs_rtmax);
2259 	*tl++ = txdr_unsigned(fs.fs_rtpref);
2260 	*tl++ = txdr_unsigned(fs.fs_rtmult);
2261 	*tl++ = txdr_unsigned(fs.fs_wtmax);
2262 	*tl++ = txdr_unsigned(fs.fs_wtpref);
2263 	*tl++ = txdr_unsigned(fs.fs_wtmult);
2264 	*tl++ = txdr_unsigned(fs.fs_dtpref);
2265 	txdr_hyper(fs.fs_maxfilesize, tl);
2266 	tl += 2;
2267 	txdr_nfsv3time(&fs.fs_timedelta, tl);
2268 	tl += 2;
2269 	*tl = txdr_unsigned(fs.fs_properties);
2270 
2271 out:
2272 	NFSEXITCODE2(0, nd);
2273 	return (0);
2274 }
2275 
2276 /*
2277  * nfs pathconf service
2278  */
2279 int
2280 nfsrvd_pathconf(struct nfsrv_descript *nd, __unused int isdgram,
2281     vnode_t vp, __unused struct nfsexstuff *exp)
2282 {
2283 	struct nfsv3_pathconf *pc;
2284 	int getret = 1;
2285 	long linkmax, namemax, chownres, notrunc;
2286 	struct nfsvattr at;
2287 	struct thread *p = curthread;
2288 
2289 	if (nd->nd_repstat) {
2290 		nfsrv_postopattr(nd, getret, &at);
2291 		goto out;
2292 	}
2293 	nd->nd_repstat = nfsvno_pathconf(vp, _PC_LINK_MAX, &linkmax,
2294 	    nd->nd_cred, p);
2295 	if (!nd->nd_repstat)
2296 		nd->nd_repstat = nfsvno_pathconf(vp, _PC_NAME_MAX, &namemax,
2297 		    nd->nd_cred, p);
2298 	if (!nd->nd_repstat)
2299 		nd->nd_repstat=nfsvno_pathconf(vp, _PC_CHOWN_RESTRICTED,
2300 		    &chownres, nd->nd_cred, p);
2301 	if (!nd->nd_repstat)
2302 		nd->nd_repstat = nfsvno_pathconf(vp, _PC_NO_TRUNC, &notrunc,
2303 		    nd->nd_cred, p);
2304 	getret = nfsvno_getattr(vp, &at, nd, p, 1, NULL);
2305 	vput(vp);
2306 	nfsrv_postopattr(nd, getret, &at);
2307 	if (!nd->nd_repstat) {
2308 		NFSM_BUILD(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF);
2309 		pc->pc_linkmax = txdr_unsigned(linkmax);
2310 		pc->pc_namemax = txdr_unsigned(namemax);
2311 		pc->pc_notrunc = txdr_unsigned(notrunc);
2312 		pc->pc_chownrestricted = txdr_unsigned(chownres);
2313 
2314 		/*
2315 		 * These should probably be supported by VOP_PATHCONF(), but
2316 		 * until msdosfs is exportable (why would you want to?), the
2317 		 * Unix defaults should be ok.
2318 		 */
2319 		pc->pc_caseinsensitive = newnfs_false;
2320 		pc->pc_casepreserving = newnfs_true;
2321 	}
2322 
2323 out:
2324 	NFSEXITCODE2(0, nd);
2325 	return (0);
2326 }
2327 
2328 /*
2329  * nfsv4 lock service
2330  */
2331 int
2332 nfsrvd_lock(struct nfsrv_descript *nd, __unused int isdgram,
2333     vnode_t vp, struct nfsexstuff *exp)
2334 {
2335 	u_int32_t *tl;
2336 	int i;
2337 	struct nfsstate *stp = NULL;
2338 	struct nfslock *lop;
2339 	struct nfslockconflict cf;
2340 	int error = 0;
2341 	u_short flags = NFSLCK_LOCK, lflags;
2342 	u_int64_t offset, len;
2343 	nfsv4stateid_t stateid;
2344 	nfsquad_t clientid;
2345 	struct thread *p = curthread;
2346 
2347 	NFSM_DISSECT(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
2348 	i = fxdr_unsigned(int, *tl++);
2349 	switch (i) {
2350 	case NFSV4LOCKT_READW:
2351 		flags |= NFSLCK_BLOCKING;
2352 	case NFSV4LOCKT_READ:
2353 		lflags = NFSLCK_READ;
2354 		break;
2355 	case NFSV4LOCKT_WRITEW:
2356 		flags |= NFSLCK_BLOCKING;
2357 	case NFSV4LOCKT_WRITE:
2358 		lflags = NFSLCK_WRITE;
2359 		break;
2360 	default:
2361 		nd->nd_repstat = NFSERR_BADXDR;
2362 		goto nfsmout;
2363 	}
2364 	if (*tl++ == newnfs_true)
2365 		flags |= NFSLCK_RECLAIM;
2366 	offset = fxdr_hyper(tl);
2367 	tl += 2;
2368 	len = fxdr_hyper(tl);
2369 	tl += 2;
2370 	if (*tl == newnfs_true)
2371 		flags |= NFSLCK_OPENTOLOCK;
2372 	if (flags & NFSLCK_OPENTOLOCK) {
2373 		NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED + NFSX_STATEID);
2374 		i = fxdr_unsigned(int, *(tl+4+(NFSX_STATEID / NFSX_UNSIGNED)));
2375 		if (i <= 0 || i > NFSV4_OPAQUELIMIT) {
2376 			nd->nd_repstat = NFSERR_BADXDR;
2377 			goto nfsmout;
2378 		}
2379 		stp = malloc(sizeof (struct nfsstate) + i,
2380 			M_NFSDSTATE, M_WAITOK);
2381 		stp->ls_ownerlen = i;
2382 		stp->ls_op = nd->nd_rp;
2383 		stp->ls_seq = fxdr_unsigned(int, *tl++);
2384 		stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
2385 		NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
2386 			NFSX_STATEIDOTHER);
2387 		tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
2388 
2389 		/*
2390 		 * For the special stateid of other all 0s and seqid == 1, set
2391 		 * the stateid to the current stateid, if it is set.
2392 		 */
2393 		if ((nd->nd_flag & ND_NFSV41) != 0 &&
2394 		    stp->ls_stateid.seqid == 1 &&
2395 		    stp->ls_stateid.other[0] == 0 &&
2396 		    stp->ls_stateid.other[1] == 0 &&
2397 		    stp->ls_stateid.other[2] == 0) {
2398 			if ((nd->nd_flag & ND_CURSTATEID) != 0) {
2399 				stp->ls_stateid = nd->nd_curstateid;
2400 				stp->ls_stateid.seqid = 0;
2401 			} else {
2402 				nd->nd_repstat = NFSERR_BADSTATEID;
2403 				goto nfsmout;
2404 			}
2405 		}
2406 
2407 		stp->ls_opentolockseq = fxdr_unsigned(int, *tl++);
2408 		clientid.lval[0] = *tl++;
2409 		clientid.lval[1] = *tl++;
2410 		if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
2411 			if ((nd->nd_flag & ND_NFSV41) != 0)
2412 				clientid.qval = nd->nd_clientid.qval;
2413 			else if (nd->nd_clientid.qval != clientid.qval)
2414 				printf("EEK3 multiple clids\n");
2415 		} else {
2416 			if ((nd->nd_flag & ND_NFSV41) != 0)
2417 				printf("EEK! no clientid from session\n");
2418 			nd->nd_flag |= ND_IMPLIEDCLID;
2419 			nd->nd_clientid.qval = clientid.qval;
2420 		}
2421 		error = nfsrv_mtostr(nd, stp->ls_owner, stp->ls_ownerlen);
2422 		if (error)
2423 			goto nfsmout;
2424 	} else {
2425 		NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + NFSX_UNSIGNED);
2426 		stp = malloc(sizeof (struct nfsstate),
2427 			M_NFSDSTATE, M_WAITOK);
2428 		stp->ls_ownerlen = 0;
2429 		stp->ls_op = nd->nd_rp;
2430 		stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
2431 		NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
2432 			NFSX_STATEIDOTHER);
2433 		tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
2434 
2435 		/*
2436 		 * For the special stateid of other all 0s and seqid == 1, set
2437 		 * the stateid to the current stateid, if it is set.
2438 		 */
2439 		if ((nd->nd_flag & ND_NFSV41) != 0 &&
2440 		    stp->ls_stateid.seqid == 1 &&
2441 		    stp->ls_stateid.other[0] == 0 &&
2442 		    stp->ls_stateid.other[1] == 0 &&
2443 		    stp->ls_stateid.other[2] == 0) {
2444 			if ((nd->nd_flag & ND_CURSTATEID) != 0) {
2445 				stp->ls_stateid = nd->nd_curstateid;
2446 				stp->ls_stateid.seqid = 0;
2447 			} else {
2448 				nd->nd_repstat = NFSERR_BADSTATEID;
2449 				goto nfsmout;
2450 			}
2451 		}
2452 
2453 		stp->ls_seq = fxdr_unsigned(int, *tl);
2454 		clientid.lval[0] = stp->ls_stateid.other[0];
2455 		clientid.lval[1] = stp->ls_stateid.other[1];
2456 		if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
2457 			if ((nd->nd_flag & ND_NFSV41) != 0)
2458 				clientid.qval = nd->nd_clientid.qval;
2459 			else if (nd->nd_clientid.qval != clientid.qval)
2460 				printf("EEK4 multiple clids\n");
2461 		} else {
2462 			if ((nd->nd_flag & ND_NFSV41) != 0)
2463 				printf("EEK! no clientid from session\n");
2464 			nd->nd_flag |= ND_IMPLIEDCLID;
2465 			nd->nd_clientid.qval = clientid.qval;
2466 		}
2467 	}
2468 	lop = malloc(sizeof (struct nfslock),
2469 		M_NFSDLOCK, M_WAITOK);
2470 	lop->lo_first = offset;
2471 	if (len == NFS64BITSSET) {
2472 		lop->lo_end = NFS64BITSSET;
2473 	} else {
2474 		lop->lo_end = offset + len;
2475 		if (lop->lo_end <= lop->lo_first)
2476 			nd->nd_repstat = NFSERR_INVAL;
2477 	}
2478 	lop->lo_flags = lflags;
2479 	stp->ls_flags = flags;
2480 	stp->ls_uid = nd->nd_cred->cr_uid;
2481 
2482 	/*
2483 	 * Do basic access checking.
2484 	 */
2485 	if (!nd->nd_repstat && vnode_vtype(vp) != VREG) {
2486 	    if (vnode_vtype(vp) == VDIR)
2487 		nd->nd_repstat = NFSERR_ISDIR;
2488 	    else
2489 		nd->nd_repstat = NFSERR_INVAL;
2490 	}
2491 	if (!nd->nd_repstat) {
2492 	    if (lflags & NFSLCK_WRITE) {
2493 		nd->nd_repstat = nfsvno_accchk(vp, VWRITE,
2494 		    nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER,
2495 		    NFSACCCHK_VPISLOCKED, NULL);
2496 	    } else {
2497 		nd->nd_repstat = nfsvno_accchk(vp, VREAD,
2498 		    nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER,
2499 		    NFSACCCHK_VPISLOCKED, NULL);
2500 		if (nd->nd_repstat)
2501 		    nd->nd_repstat = nfsvno_accchk(vp, VEXEC,
2502 			nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER,
2503 			NFSACCCHK_VPISLOCKED, NULL);
2504 	    }
2505 	}
2506 
2507 	/*
2508 	 * We call nfsrv_lockctrl() even if nd_repstat set, so that the
2509 	 * seqid# gets updated. nfsrv_lockctrl() will return the value
2510 	 * of nd_repstat, if it gets that far.
2511 	 */
2512 	nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, &cf, clientid,
2513 		&stateid, exp, nd, p);
2514 	if (lop)
2515 		free(lop, M_NFSDLOCK);
2516 	if (stp)
2517 		free(stp, M_NFSDSTATE);
2518 	if (!nd->nd_repstat) {
2519 		/* For NFSv4.1, set the Current StateID. */
2520 		if ((nd->nd_flag & ND_NFSV41) != 0) {
2521 			nd->nd_curstateid = stateid;
2522 			nd->nd_flag |= ND_CURSTATEID;
2523 		}
2524 		NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
2525 		*tl++ = txdr_unsigned(stateid.seqid);
2526 		NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
2527 	} else if (nd->nd_repstat == NFSERR_DENIED) {
2528 		NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
2529 		txdr_hyper(cf.cl_first, tl);
2530 		tl += 2;
2531 		if (cf.cl_end == NFS64BITSSET)
2532 			len = NFS64BITSSET;
2533 		else
2534 			len = cf.cl_end - cf.cl_first;
2535 		txdr_hyper(len, tl);
2536 		tl += 2;
2537 		if (cf.cl_flags == NFSLCK_WRITE)
2538 			*tl++ = txdr_unsigned(NFSV4LOCKT_WRITE);
2539 		else
2540 			*tl++ = txdr_unsigned(NFSV4LOCKT_READ);
2541 		*tl++ = stateid.other[0];
2542 		*tl = stateid.other[1];
2543 		(void) nfsm_strtom(nd, cf.cl_owner, cf.cl_ownerlen);
2544 	}
2545 	vput(vp);
2546 	NFSEXITCODE2(0, nd);
2547 	return (0);
2548 nfsmout:
2549 	vput(vp);
2550 	if (stp)
2551 		free(stp, M_NFSDSTATE);
2552 	NFSEXITCODE2(error, nd);
2553 	return (error);
2554 }
2555 
2556 /*
2557  * nfsv4 lock test service
2558  */
2559 int
2560 nfsrvd_lockt(struct nfsrv_descript *nd, __unused int isdgram,
2561     vnode_t vp, struct nfsexstuff *exp)
2562 {
2563 	u_int32_t *tl;
2564 	int i;
2565 	struct nfsstate *stp = NULL;
2566 	struct nfslock lo, *lop = &lo;
2567 	struct nfslockconflict cf;
2568 	int error = 0;
2569 	nfsv4stateid_t stateid;
2570 	nfsquad_t clientid;
2571 	u_int64_t len;
2572 	struct thread *p = curthread;
2573 
2574 	NFSM_DISSECT(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
2575 	i = fxdr_unsigned(int, *(tl + 7));
2576 	if (i <= 0 || i > NFSV4_OPAQUELIMIT) {
2577 		nd->nd_repstat = NFSERR_BADXDR;
2578 		goto nfsmout;
2579 	}
2580 	stp = malloc(sizeof (struct nfsstate) + i,
2581 	    M_NFSDSTATE, M_WAITOK);
2582 	stp->ls_ownerlen = i;
2583 	stp->ls_op = NULL;
2584 	stp->ls_flags = NFSLCK_TEST;
2585 	stp->ls_uid = nd->nd_cred->cr_uid;
2586 	i = fxdr_unsigned(int, *tl++);
2587 	switch (i) {
2588 	case NFSV4LOCKT_READW:
2589 		stp->ls_flags |= NFSLCK_BLOCKING;
2590 	case NFSV4LOCKT_READ:
2591 		lo.lo_flags = NFSLCK_READ;
2592 		break;
2593 	case NFSV4LOCKT_WRITEW:
2594 		stp->ls_flags |= NFSLCK_BLOCKING;
2595 	case NFSV4LOCKT_WRITE:
2596 		lo.lo_flags = NFSLCK_WRITE;
2597 		break;
2598 	default:
2599 		nd->nd_repstat = NFSERR_BADXDR;
2600 		goto nfsmout;
2601 	}
2602 	lo.lo_first = fxdr_hyper(tl);
2603 	tl += 2;
2604 	len = fxdr_hyper(tl);
2605 	if (len == NFS64BITSSET) {
2606 		lo.lo_end = NFS64BITSSET;
2607 	} else {
2608 		lo.lo_end = lo.lo_first + len;
2609 		if (lo.lo_end <= lo.lo_first)
2610 			nd->nd_repstat = NFSERR_INVAL;
2611 	}
2612 	tl += 2;
2613 	clientid.lval[0] = *tl++;
2614 	clientid.lval[1] = *tl;
2615 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
2616 		if ((nd->nd_flag & ND_NFSV41) != 0)
2617 			clientid.qval = nd->nd_clientid.qval;
2618 		else if (nd->nd_clientid.qval != clientid.qval)
2619 			printf("EEK5 multiple clids\n");
2620 	} else {
2621 		if ((nd->nd_flag & ND_NFSV41) != 0)
2622 			printf("EEK! no clientid from session\n");
2623 		nd->nd_flag |= ND_IMPLIEDCLID;
2624 		nd->nd_clientid.qval = clientid.qval;
2625 	}
2626 	error = nfsrv_mtostr(nd, stp->ls_owner, stp->ls_ownerlen);
2627 	if (error)
2628 		goto nfsmout;
2629 	if (!nd->nd_repstat && vnode_vtype(vp) != VREG) {
2630 	    if (vnode_vtype(vp) == VDIR)
2631 		nd->nd_repstat = NFSERR_ISDIR;
2632 	    else
2633 		nd->nd_repstat = NFSERR_INVAL;
2634 	}
2635 	if (!nd->nd_repstat)
2636 	  nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, &cf, clientid,
2637 	    &stateid, exp, nd, p);
2638 	if (nd->nd_repstat) {
2639 	    if (nd->nd_repstat == NFSERR_DENIED) {
2640 		NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
2641 		txdr_hyper(cf.cl_first, tl);
2642 		tl += 2;
2643 		if (cf.cl_end == NFS64BITSSET)
2644 			len = NFS64BITSSET;
2645 		else
2646 			len = cf.cl_end - cf.cl_first;
2647 		txdr_hyper(len, tl);
2648 		tl += 2;
2649 		if (cf.cl_flags == NFSLCK_WRITE)
2650 			*tl++ = txdr_unsigned(NFSV4LOCKT_WRITE);
2651 		else
2652 			*tl++ = txdr_unsigned(NFSV4LOCKT_READ);
2653 		*tl++ = stp->ls_stateid.other[0];
2654 		*tl = stp->ls_stateid.other[1];
2655 		(void) nfsm_strtom(nd, cf.cl_owner, cf.cl_ownerlen);
2656 	    }
2657 	}
2658 	vput(vp);
2659 	if (stp)
2660 		free(stp, M_NFSDSTATE);
2661 	NFSEXITCODE2(0, nd);
2662 	return (0);
2663 nfsmout:
2664 	vput(vp);
2665 	if (stp)
2666 		free(stp, M_NFSDSTATE);
2667 	NFSEXITCODE2(error, nd);
2668 	return (error);
2669 }
2670 
2671 /*
2672  * nfsv4 unlock service
2673  */
2674 int
2675 nfsrvd_locku(struct nfsrv_descript *nd, __unused int isdgram,
2676     vnode_t vp, struct nfsexstuff *exp)
2677 {
2678 	u_int32_t *tl;
2679 	int i;
2680 	struct nfsstate *stp;
2681 	struct nfslock *lop;
2682 	int error = 0;
2683 	nfsv4stateid_t stateid;
2684 	nfsquad_t clientid;
2685 	u_int64_t len;
2686 	struct thread *p = curthread;
2687 
2688 	NFSM_DISSECT(tl, u_int32_t *, 6 * NFSX_UNSIGNED + NFSX_STATEID);
2689 	stp = malloc(sizeof (struct nfsstate),
2690 	    M_NFSDSTATE, M_WAITOK);
2691 	lop = malloc(sizeof (struct nfslock),
2692 	    M_NFSDLOCK, M_WAITOK);
2693 	stp->ls_flags = NFSLCK_UNLOCK;
2694 	lop->lo_flags = NFSLCK_UNLOCK;
2695 	stp->ls_op = nd->nd_rp;
2696 	i = fxdr_unsigned(int, *tl++);
2697 	switch (i) {
2698 	case NFSV4LOCKT_READW:
2699 		stp->ls_flags |= NFSLCK_BLOCKING;
2700 	case NFSV4LOCKT_READ:
2701 		break;
2702 	case NFSV4LOCKT_WRITEW:
2703 		stp->ls_flags |= NFSLCK_BLOCKING;
2704 	case NFSV4LOCKT_WRITE:
2705 		break;
2706 	default:
2707 		nd->nd_repstat = NFSERR_BADXDR;
2708 		free(stp, M_NFSDSTATE);
2709 		free(lop, M_NFSDLOCK);
2710 		goto nfsmout;
2711 	}
2712 	stp->ls_ownerlen = 0;
2713 	stp->ls_uid = nd->nd_cred->cr_uid;
2714 	stp->ls_seq = fxdr_unsigned(int, *tl++);
2715 	stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
2716 	NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
2717 	    NFSX_STATEIDOTHER);
2718 	tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
2719 
2720 	/*
2721 	 * For the special stateid of other all 0s and seqid == 1, set the
2722 	 * stateid to the current stateid, if it is set.
2723 	 */
2724 	if ((nd->nd_flag & ND_NFSV41) != 0 && stp->ls_stateid.seqid == 1 &&
2725 	    stp->ls_stateid.other[0] == 0 && stp->ls_stateid.other[1] == 0 &&
2726 	    stp->ls_stateid.other[2] == 0) {
2727 		if ((nd->nd_flag & ND_CURSTATEID) != 0) {
2728 			stp->ls_stateid = nd->nd_curstateid;
2729 			stp->ls_stateid.seqid = 0;
2730 		} else {
2731 			nd->nd_repstat = NFSERR_BADSTATEID;
2732 			free(stp, M_NFSDSTATE);
2733 			free(lop, M_NFSDLOCK);
2734 			goto nfsmout;
2735 		}
2736 	}
2737 
2738 	lop->lo_first = fxdr_hyper(tl);
2739 	tl += 2;
2740 	len = fxdr_hyper(tl);
2741 	if (len == NFS64BITSSET) {
2742 		lop->lo_end = NFS64BITSSET;
2743 	} else {
2744 		lop->lo_end = lop->lo_first + len;
2745 		if (lop->lo_end <= lop->lo_first)
2746 			nd->nd_repstat = NFSERR_INVAL;
2747 	}
2748 	clientid.lval[0] = stp->ls_stateid.other[0];
2749 	clientid.lval[1] = stp->ls_stateid.other[1];
2750 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
2751 		if ((nd->nd_flag & ND_NFSV41) != 0)
2752 			clientid.qval = nd->nd_clientid.qval;
2753 		else if (nd->nd_clientid.qval != clientid.qval)
2754 			printf("EEK6 multiple clids\n");
2755 	} else {
2756 		if ((nd->nd_flag & ND_NFSV41) != 0)
2757 			printf("EEK! no clientid from session\n");
2758 		nd->nd_flag |= ND_IMPLIEDCLID;
2759 		nd->nd_clientid.qval = clientid.qval;
2760 	}
2761 	if (!nd->nd_repstat && vnode_vtype(vp) != VREG) {
2762 	    if (vnode_vtype(vp) == VDIR)
2763 		nd->nd_repstat = NFSERR_ISDIR;
2764 	    else
2765 		nd->nd_repstat = NFSERR_INVAL;
2766 	}
2767 	/*
2768 	 * Call nfsrv_lockctrl() even if nd_repstat is set, so that the
2769 	 * seqid# gets incremented. nfsrv_lockctrl() will return the
2770 	 * value of nd_repstat, if it gets that far.
2771 	 */
2772 	nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid,
2773 	    &stateid, exp, nd, p);
2774 	if (stp)
2775 		free(stp, M_NFSDSTATE);
2776 	if (lop)
2777 		free(lop, M_NFSDLOCK);
2778 	if (!nd->nd_repstat) {
2779 		NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
2780 		*tl++ = txdr_unsigned(stateid.seqid);
2781 		NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
2782 	}
2783 nfsmout:
2784 	vput(vp);
2785 	NFSEXITCODE2(error, nd);
2786 	return (error);
2787 }
2788 
2789 /*
2790  * nfsv4 open service
2791  */
2792 int
2793 nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
2794     vnode_t dp, vnode_t *vpp, __unused fhandle_t *fhp, struct nfsexstuff *exp)
2795 {
2796 	u_int32_t *tl;
2797 	int i, retext;
2798 	struct nfsstate *stp = NULL;
2799 	int error = 0, create, claim, exclusive_flag = 0, override;
2800 	u_int32_t rflags = NFSV4OPEN_LOCKTYPEPOSIX, acemask;
2801 	int how = NFSCREATE_UNCHECKED;
2802 	int32_t cverf[2], tverf[2] = { 0, 0 };
2803 	vnode_t vp = NULL, dirp = NULL;
2804 	struct nfsvattr nva, dirfor, diraft;
2805 	struct nameidata named;
2806 	nfsv4stateid_t stateid, delegstateid;
2807 	nfsattrbit_t attrbits;
2808 	nfsquad_t clientid;
2809 	char *bufp = NULL;
2810 	u_long *hashp;
2811 	NFSACL_T *aclp = NULL;
2812 	struct thread *p = curthread;
2813 
2814 #ifdef NFS4_ACL_EXTATTR_NAME
2815 	aclp = acl_alloc(M_WAITOK);
2816 	aclp->acl_cnt = 0;
2817 #endif
2818 	NFSZERO_ATTRBIT(&attrbits);
2819 	named.ni_startdir = NULL;
2820 	named.ni_cnd.cn_nameiop = 0;
2821 	NFSM_DISSECT(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
2822 	i = fxdr_unsigned(int, *(tl + 5));
2823 	if (i <= 0 || i > NFSV4_OPAQUELIMIT) {
2824 		nd->nd_repstat = NFSERR_BADXDR;
2825 		goto nfsmout;
2826 	}
2827 	stp = malloc(sizeof (struct nfsstate) + i,
2828 	    M_NFSDSTATE, M_WAITOK);
2829 	stp->ls_ownerlen = i;
2830 	stp->ls_op = nd->nd_rp;
2831 	stp->ls_flags = NFSLCK_OPEN;
2832 	stp->ls_uid = nd->nd_cred->cr_uid;
2833 	stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++);
2834 	i = fxdr_unsigned(int, *tl++);
2835 	retext = 0;
2836 	if ((i & (NFSV4OPEN_WANTDELEGMASK | NFSV4OPEN_WANTSIGNALDELEG |
2837 	    NFSV4OPEN_WANTPUSHDELEG)) != 0 && (nd->nd_flag & ND_NFSV41) != 0) {
2838 		retext = 1;
2839 		/* For now, ignore these. */
2840 		i &= ~(NFSV4OPEN_WANTPUSHDELEG | NFSV4OPEN_WANTSIGNALDELEG);
2841 		switch (i & NFSV4OPEN_WANTDELEGMASK) {
2842 		case NFSV4OPEN_WANTANYDELEG:
2843 			stp->ls_flags |= (NFSLCK_WANTRDELEG |
2844 			    NFSLCK_WANTWDELEG);
2845 			i &= ~NFSV4OPEN_WANTDELEGMASK;
2846 			break;
2847 		case NFSV4OPEN_WANTREADDELEG:
2848 			stp->ls_flags |= NFSLCK_WANTRDELEG;
2849 			i &= ~NFSV4OPEN_WANTDELEGMASK;
2850 			break;
2851 		case NFSV4OPEN_WANTWRITEDELEG:
2852 			stp->ls_flags |= NFSLCK_WANTWDELEG;
2853 			i &= ~NFSV4OPEN_WANTDELEGMASK;
2854 			break;
2855 		case NFSV4OPEN_WANTNODELEG:
2856 			stp->ls_flags |= NFSLCK_WANTNODELEG;
2857 			i &= ~NFSV4OPEN_WANTDELEGMASK;
2858 			break;
2859 		case NFSV4OPEN_WANTCANCEL:
2860 			printf("NFSv4: ignore Open WantCancel\n");
2861 			i &= ~NFSV4OPEN_WANTDELEGMASK;
2862 			break;
2863 		default:
2864 			/* nd_repstat will be set to NFSERR_INVAL below. */
2865 			break;
2866 		}
2867 	}
2868 	switch (i) {
2869 	case NFSV4OPEN_ACCESSREAD:
2870 		stp->ls_flags |= NFSLCK_READACCESS;
2871 		break;
2872 	case NFSV4OPEN_ACCESSWRITE:
2873 		stp->ls_flags |= NFSLCK_WRITEACCESS;
2874 		break;
2875 	case NFSV4OPEN_ACCESSBOTH:
2876 		stp->ls_flags |= (NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
2877 		break;
2878 	default:
2879 		nd->nd_repstat = NFSERR_INVAL;
2880 	}
2881 	i = fxdr_unsigned(int, *tl++);
2882 	switch (i) {
2883 	case NFSV4OPEN_DENYNONE:
2884 		break;
2885 	case NFSV4OPEN_DENYREAD:
2886 		stp->ls_flags |= NFSLCK_READDENY;
2887 		break;
2888 	case NFSV4OPEN_DENYWRITE:
2889 		stp->ls_flags |= NFSLCK_WRITEDENY;
2890 		break;
2891 	case NFSV4OPEN_DENYBOTH:
2892 		stp->ls_flags |= (NFSLCK_READDENY | NFSLCK_WRITEDENY);
2893 		break;
2894 	default:
2895 		nd->nd_repstat = NFSERR_INVAL;
2896 	}
2897 	clientid.lval[0] = *tl++;
2898 	clientid.lval[1] = *tl;
2899 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
2900 		if ((nd->nd_flag & ND_NFSV41) != 0)
2901 			clientid.qval = nd->nd_clientid.qval;
2902 		else if (nd->nd_clientid.qval != clientid.qval)
2903 			printf("EEK7 multiple clids\n");
2904 	} else {
2905 		if ((nd->nd_flag & ND_NFSV41) != 0)
2906 			printf("EEK! no clientid from session\n");
2907 		nd->nd_flag |= ND_IMPLIEDCLID;
2908 		nd->nd_clientid.qval = clientid.qval;
2909 	}
2910 	error = nfsrv_mtostr(nd, stp->ls_owner, stp->ls_ownerlen);
2911 	if (error)
2912 		goto nfsmout;
2913 	NFSVNO_ATTRINIT(&nva);
2914 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2915 	create = fxdr_unsigned(int, *tl);
2916 	if (!nd->nd_repstat)
2917 		nd->nd_repstat = nfsvno_getattr(dp, &dirfor, nd, p, 0, NULL);
2918 	if (create == NFSV4OPEN_CREATE) {
2919 		nva.na_type = VREG;
2920 		nva.na_mode = 0;
2921 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2922 		how = fxdr_unsigned(int, *tl);
2923 		switch (how) {
2924 		case NFSCREATE_UNCHECKED:
2925 		case NFSCREATE_GUARDED:
2926 			error = nfsv4_sattr(nd, NULL, &nva, &attrbits, aclp, p);
2927 			if (error)
2928 				goto nfsmout;
2929 			/*
2930 			 * If the na_gid being set is the same as that of
2931 			 * the directory it is going in, clear it, since
2932 			 * that is what will be set by default. This allows
2933 			 * a user that isn't in that group to do the create.
2934 			 */
2935 			if (!nd->nd_repstat && NFSVNO_ISSETGID(&nva) &&
2936 			    nva.na_gid == dirfor.na_gid)
2937 				NFSVNO_UNSET(&nva, gid);
2938 			if (!nd->nd_repstat)
2939 				nd->nd_repstat = nfsrv_checkuidgid(nd, &nva);
2940 			break;
2941 		case NFSCREATE_EXCLUSIVE:
2942 			NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF);
2943 			cverf[0] = *tl++;
2944 			cverf[1] = *tl;
2945 			break;
2946 		case NFSCREATE_EXCLUSIVE41:
2947 			NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF);
2948 			cverf[0] = *tl++;
2949 			cverf[1] = *tl;
2950 			error = nfsv4_sattr(nd, NULL, &nva, &attrbits, aclp, p);
2951 			if (error != 0)
2952 				goto nfsmout;
2953 			if (NFSISSET_ATTRBIT(&attrbits,
2954 			    NFSATTRBIT_TIMEACCESSSET))
2955 				nd->nd_repstat = NFSERR_INVAL;
2956 			/*
2957 			 * If the na_gid being set is the same as that of
2958 			 * the directory it is going in, clear it, since
2959 			 * that is what will be set by default. This allows
2960 			 * a user that isn't in that group to do the create.
2961 			 */
2962 			if (nd->nd_repstat == 0 && NFSVNO_ISSETGID(&nva) &&
2963 			    nva.na_gid == dirfor.na_gid)
2964 				NFSVNO_UNSET(&nva, gid);
2965 			if (nd->nd_repstat == 0)
2966 				nd->nd_repstat = nfsrv_checkuidgid(nd, &nva);
2967 			break;
2968 		default:
2969 			nd->nd_repstat = NFSERR_BADXDR;
2970 			goto nfsmout;
2971 		}
2972 	} else if (create != NFSV4OPEN_NOCREATE) {
2973 		nd->nd_repstat = NFSERR_BADXDR;
2974 		goto nfsmout;
2975 	}
2976 
2977 	/*
2978 	 * Now, handle the claim, which usually includes looking up a
2979 	 * name in the directory referenced by dp. The exception is
2980 	 * NFSV4OPEN_CLAIMPREVIOUS.
2981 	 */
2982 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2983 	claim = fxdr_unsigned(int, *tl);
2984 	if (claim == NFSV4OPEN_CLAIMDELEGATECUR || claim ==
2985 	    NFSV4OPEN_CLAIMDELEGATECURFH) {
2986 		NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
2987 		stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
2988 		NFSBCOPY((caddr_t)tl,(caddr_t)stateid.other,NFSX_STATEIDOTHER);
2989 		stp->ls_flags |= NFSLCK_DELEGCUR;
2990 	} else if (claim == NFSV4OPEN_CLAIMDELEGATEPREV || claim ==
2991 	    NFSV4OPEN_CLAIMDELEGATEPREVFH) {
2992 		stp->ls_flags |= NFSLCK_DELEGPREV;
2993 	}
2994 	if (claim == NFSV4OPEN_CLAIMNULL || claim == NFSV4OPEN_CLAIMDELEGATECUR
2995 	    || claim == NFSV4OPEN_CLAIMDELEGATEPREV) {
2996 		if (!nd->nd_repstat && create == NFSV4OPEN_CREATE &&
2997 		    claim != NFSV4OPEN_CLAIMNULL)
2998 			nd->nd_repstat = NFSERR_INVAL;
2999 		if (nd->nd_repstat) {
3000 			nd->nd_repstat = nfsrv_opencheck(clientid,
3001 			    &stateid, stp, NULL, nd, p, nd->nd_repstat);
3002 			goto nfsmout;
3003 		}
3004 		if (create == NFSV4OPEN_CREATE)
3005 		    NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
3006 			LOCKPARENT | LOCKLEAF | SAVESTART | NOCACHE);
3007 		else
3008 		    NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP,
3009 			LOCKLEAF | SAVESTART);
3010 		nfsvno_setpathbuf(&named, &bufp, &hashp);
3011 		error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
3012 		if (error) {
3013 			vrele(dp);
3014 #ifdef NFS4_ACL_EXTATTR_NAME
3015 			acl_free(aclp);
3016 #endif
3017 			free(stp, M_NFSDSTATE);
3018 			nfsvno_relpathbuf(&named);
3019 			NFSEXITCODE2(error, nd);
3020 			return (error);
3021 		}
3022 		if (!nd->nd_repstat) {
3023 			nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp,
3024 			    p, &dirp);
3025 		} else {
3026 			vrele(dp);
3027 			nfsvno_relpathbuf(&named);
3028 		}
3029 		if (create == NFSV4OPEN_CREATE) {
3030 		    switch (how) {
3031 		    case NFSCREATE_UNCHECKED:
3032 			if (named.ni_vp) {
3033 				/*
3034 				 * Clear the setable attribute bits, except
3035 				 * for Size, if it is being truncated.
3036 				 */
3037 				NFSZERO_ATTRBIT(&attrbits);
3038 				if (NFSVNO_ISSETSIZE(&nva))
3039 					NFSSETBIT_ATTRBIT(&attrbits,
3040 					    NFSATTRBIT_SIZE);
3041 			}
3042 			break;
3043 		    case NFSCREATE_GUARDED:
3044 			if (named.ni_vp && !nd->nd_repstat)
3045 				nd->nd_repstat = EEXIST;
3046 			break;
3047 		    case NFSCREATE_EXCLUSIVE:
3048 			exclusive_flag = 1;
3049 			if (!named.ni_vp)
3050 				nva.na_mode = 0;
3051 			break;
3052 		    case NFSCREATE_EXCLUSIVE41:
3053 			exclusive_flag = 1;
3054 			break;
3055 		    }
3056 		}
3057 		nfsvno_open(nd, &named, clientid, &stateid, stp,
3058 		    &exclusive_flag, &nva, cverf, create, aclp, &attrbits,
3059 		    nd->nd_cred, exp, &vp);
3060 	} else if (claim == NFSV4OPEN_CLAIMPREVIOUS || claim ==
3061 	    NFSV4OPEN_CLAIMFH || claim == NFSV4OPEN_CLAIMDELEGATECURFH ||
3062 	    claim == NFSV4OPEN_CLAIMDELEGATEPREVFH) {
3063 		if (claim == NFSV4OPEN_CLAIMPREVIOUS) {
3064 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
3065 			i = fxdr_unsigned(int, *tl);
3066 			switch (i) {
3067 			case NFSV4OPEN_DELEGATEREAD:
3068 				stp->ls_flags |= NFSLCK_DELEGREAD;
3069 				break;
3070 			case NFSV4OPEN_DELEGATEWRITE:
3071 				stp->ls_flags |= NFSLCK_DELEGWRITE;
3072 			case NFSV4OPEN_DELEGATENONE:
3073 				break;
3074 			default:
3075 				nd->nd_repstat = NFSERR_BADXDR;
3076 				goto nfsmout;
3077 			}
3078 			stp->ls_flags |= NFSLCK_RECLAIM;
3079 		} else {
3080 			if (nd->nd_repstat == 0 && create == NFSV4OPEN_CREATE)
3081 				nd->nd_repstat = NFSERR_INVAL;
3082 		}
3083 		vp = dp;
3084 		NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
3085 		if (!VN_IS_DOOMED(vp))
3086 			nd->nd_repstat = nfsrv_opencheck(clientid, &stateid,
3087 			    stp, vp, nd, p, nd->nd_repstat);
3088 		else
3089 			nd->nd_repstat = NFSERR_PERM;
3090 	} else {
3091 		nd->nd_repstat = NFSERR_BADXDR;
3092 		goto nfsmout;
3093 	}
3094 
3095 	/*
3096 	 * Do basic access checking.
3097 	 */
3098 	if (!nd->nd_repstat && vnode_vtype(vp) != VREG) {
3099 		/*
3100 		 * The IETF working group decided that this is the correct
3101 		 * error return for all non-regular files.
3102 		 */
3103 		nd->nd_repstat = (vp->v_type == VDIR) ? NFSERR_ISDIR : NFSERR_SYMLINK;
3104 	}
3105 
3106 	/*
3107 	 * If the Open is being done for a file that already exists, apply
3108 	 * normal permission checking including for the file owner, if
3109 	 * vfs.nfsd.v4openaccess is set.
3110 	 * Previously, the owner was always allowed to open the file to
3111 	 * be consistent with the NFS tradition of always allowing the
3112 	 * owner of the file to write to the file regardless of permissions.
3113 	 * It now appears that the Linux client expects the owner
3114 	 * permissions to be checked for opens that are not creating the
3115 	 * file.  I believe the correct approach is to use the Access
3116 	 * operation's results to be consistent with NFSv3, but that is
3117 	 * not what the current Linux client appears to be doing.
3118 	 * Since both the Linux and OpenSolaris NFSv4 servers do this check,
3119 	 * I have enabled it by default.
3120 	 * If this semantic change causes a problem, it can be disabled by
3121 	 * setting the sysctl vfs.nfsd.v4openaccess to 0 to re-enable the
3122 	 * previous semantics.
3123 	 */
3124 	if (nfsrv_openaccess && create == NFSV4OPEN_NOCREATE)
3125 		override = NFSACCCHK_NOOVERRIDE;
3126 	else
3127 		override = NFSACCCHK_ALLOWOWNER;
3128 	if (!nd->nd_repstat && (stp->ls_flags & NFSLCK_WRITEACCESS))
3129 	    nd->nd_repstat = nfsvno_accchk(vp, VWRITE, nd->nd_cred,
3130 	        exp, p, override, NFSACCCHK_VPISLOCKED, NULL);
3131 	if (!nd->nd_repstat && (stp->ls_flags & NFSLCK_READACCESS)) {
3132 	    nd->nd_repstat = nfsvno_accchk(vp, VREAD, nd->nd_cred,
3133 	        exp, p, override, NFSACCCHK_VPISLOCKED, NULL);
3134 	    if (nd->nd_repstat)
3135 		nd->nd_repstat = nfsvno_accchk(vp, VEXEC,
3136 		    nd->nd_cred, exp, p, override,
3137 		    NFSACCCHK_VPISLOCKED, NULL);
3138 	}
3139 
3140 	if (!nd->nd_repstat) {
3141 		nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
3142 		if (!nd->nd_repstat) {
3143 			tverf[0] = nva.na_atime.tv_sec;
3144 			tverf[1] = nva.na_atime.tv_nsec;
3145 		}
3146 	}
3147 	if (!nd->nd_repstat && exclusive_flag && (cverf[0] != tverf[0] ||
3148 	    cverf[1] != tverf[1]))
3149 		nd->nd_repstat = EEXIST;
3150 	/*
3151 	 * Do the open locking/delegation stuff.
3152 	 */
3153 	if (!nd->nd_repstat)
3154 	    nd->nd_repstat = nfsrv_openctrl(nd, vp, &stp, clientid, &stateid,
3155 		&delegstateid, &rflags, exp, p, nva.na_filerev);
3156 
3157 	/*
3158 	 * vp must be unlocked before the call to nfsvno_getattr(dirp,...)
3159 	 * below, to avoid a deadlock with the lookup in nfsvno_namei() above.
3160 	 * (ie: Leave the NFSVOPUNLOCK() about here.)
3161 	 */
3162 	if (vp)
3163 		NFSVOPUNLOCK(vp);
3164 	if (stp)
3165 		free(stp, M_NFSDSTATE);
3166 	if (!nd->nd_repstat && dirp)
3167 		nd->nd_repstat = nfsvno_getattr(dirp, &diraft, nd, p, 0, NULL);
3168 	if (!nd->nd_repstat) {
3169 		/* For NFSv4.1, set the Current StateID. */
3170 		if ((nd->nd_flag & ND_NFSV41) != 0) {
3171 			nd->nd_curstateid = stateid;
3172 			nd->nd_flag |= ND_CURSTATEID;
3173 		}
3174 		NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID + 6 * NFSX_UNSIGNED);
3175 		*tl++ = txdr_unsigned(stateid.seqid);
3176 		NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
3177 		tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
3178 		if (claim == NFSV4OPEN_CLAIMPREVIOUS) {
3179 			*tl++ = newnfs_true;
3180 			*tl++ = 0;
3181 			*tl++ = 0;
3182 			*tl++ = 0;
3183 			*tl++ = 0;
3184 		} else {
3185 			*tl++ = newnfs_false;	/* Since dirp is not locked */
3186 			txdr_hyper(dirfor.na_filerev, tl);
3187 			tl += 2;
3188 			txdr_hyper(diraft.na_filerev, tl);
3189 			tl += 2;
3190 		}
3191 		*tl = txdr_unsigned(rflags & NFSV4OPEN_RFLAGS);
3192 		(void) nfsrv_putattrbit(nd, &attrbits);
3193 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3194 		if (rflags & NFSV4OPEN_READDELEGATE)
3195 			*tl = txdr_unsigned(NFSV4OPEN_DELEGATEREAD);
3196 		else if (rflags & NFSV4OPEN_WRITEDELEGATE)
3197 			*tl = txdr_unsigned(NFSV4OPEN_DELEGATEWRITE);
3198 		else if (retext != 0) {
3199 			*tl = txdr_unsigned(NFSV4OPEN_DELEGATENONEEXT);
3200 			if ((rflags & NFSV4OPEN_WDNOTWANTED) != 0) {
3201 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3202 				*tl = txdr_unsigned(NFSV4OPEN_NOTWANTED);
3203 			} else if ((rflags & NFSV4OPEN_WDSUPPFTYPE) != 0) {
3204 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3205 				*tl = txdr_unsigned(NFSV4OPEN_NOTSUPPFTYPE);
3206 			} else if ((rflags & NFSV4OPEN_WDCONTENTION) != 0) {
3207 				NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
3208 				*tl++ = txdr_unsigned(NFSV4OPEN_CONTENTION);
3209 				*tl = newnfs_false;
3210 			} else if ((rflags & NFSV4OPEN_WDRESOURCE) != 0) {
3211 				NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
3212 				*tl++ = txdr_unsigned(NFSV4OPEN_RESOURCE);
3213 				*tl = newnfs_false;
3214 			} else {
3215 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3216 				*tl = txdr_unsigned(NFSV4OPEN_NOTWANTED);
3217 			}
3218 		} else
3219 			*tl = txdr_unsigned(NFSV4OPEN_DELEGATENONE);
3220 		if (rflags & (NFSV4OPEN_READDELEGATE|NFSV4OPEN_WRITEDELEGATE)) {
3221 			NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID+NFSX_UNSIGNED);
3222 			*tl++ = txdr_unsigned(delegstateid.seqid);
3223 			NFSBCOPY((caddr_t)delegstateid.other, (caddr_t)tl,
3224 			    NFSX_STATEIDOTHER);
3225 			tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
3226 			if (rflags & NFSV4OPEN_RECALL)
3227 				*tl = newnfs_true;
3228 			else
3229 				*tl = newnfs_false;
3230 			if (rflags & NFSV4OPEN_WRITEDELEGATE) {
3231 				NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
3232 				*tl++ = txdr_unsigned(NFSV4OPEN_LIMITSIZE);
3233 				txdr_hyper(nva.na_size, tl);
3234 			}
3235 			NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
3236 			*tl++ = txdr_unsigned(NFSV4ACE_ALLOWEDTYPE);
3237 			*tl++ = txdr_unsigned(0x0);
3238 			acemask = NFSV4ACE_ALLFILESMASK;
3239 			if (nva.na_mode & S_IRUSR)
3240 			    acemask |= NFSV4ACE_READMASK;
3241 			if (nva.na_mode & S_IWUSR)
3242 			    acemask |= NFSV4ACE_WRITEMASK;
3243 			if (nva.na_mode & S_IXUSR)
3244 			    acemask |= NFSV4ACE_EXECUTEMASK;
3245 			*tl = txdr_unsigned(acemask);
3246 			(void) nfsm_strtom(nd, "OWNER@", 6);
3247 		}
3248 		*vpp = vp;
3249 	} else if (vp) {
3250 		vrele(vp);
3251 	}
3252 	if (dirp)
3253 		vrele(dirp);
3254 #ifdef NFS4_ACL_EXTATTR_NAME
3255 	acl_free(aclp);
3256 #endif
3257 	NFSEXITCODE2(0, nd);
3258 	return (0);
3259 nfsmout:
3260 	vrele(dp);
3261 #ifdef NFS4_ACL_EXTATTR_NAME
3262 	acl_free(aclp);
3263 #endif
3264 	if (stp)
3265 		free(stp, M_NFSDSTATE);
3266 	NFSEXITCODE2(error, nd);
3267 	return (error);
3268 }
3269 
3270 /*
3271  * nfsv4 close service
3272  */
3273 int
3274 nfsrvd_close(struct nfsrv_descript *nd, __unused int isdgram,
3275     vnode_t vp, __unused struct nfsexstuff *exp)
3276 {
3277 	u_int32_t *tl;
3278 	struct nfsstate st, *stp = &st;
3279 	int error = 0, writeacc;
3280 	nfsv4stateid_t stateid;
3281 	nfsquad_t clientid;
3282 	struct nfsvattr na;
3283 	struct thread *p = curthread;
3284 
3285 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID);
3286 	stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++);
3287 	stp->ls_ownerlen = 0;
3288 	stp->ls_op = nd->nd_rp;
3289 	stp->ls_uid = nd->nd_cred->cr_uid;
3290 	stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
3291 	NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
3292 	    NFSX_STATEIDOTHER);
3293 
3294 	/*
3295 	 * For the special stateid of other all 0s and seqid == 1, set the
3296 	 * stateid to the current stateid, if it is set.
3297 	 */
3298 	if ((nd->nd_flag & ND_NFSV41) != 0 && stp->ls_stateid.seqid == 1 &&
3299 	    stp->ls_stateid.other[0] == 0 && stp->ls_stateid.other[1] == 0 &&
3300 	    stp->ls_stateid.other[2] == 0) {
3301 		if ((nd->nd_flag & ND_CURSTATEID) != 0)
3302 			stp->ls_stateid = nd->nd_curstateid;
3303 		else {
3304 			nd->nd_repstat = NFSERR_BADSTATEID;
3305 			goto nfsmout;
3306 		}
3307 	}
3308 
3309 	stp->ls_flags = NFSLCK_CLOSE;
3310 	clientid.lval[0] = stp->ls_stateid.other[0];
3311 	clientid.lval[1] = stp->ls_stateid.other[1];
3312 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
3313 		if ((nd->nd_flag & ND_NFSV41) != 0)
3314 			clientid.qval = nd->nd_clientid.qval;
3315 		else if (nd->nd_clientid.qval != clientid.qval)
3316 			printf("EEK8 multiple clids\n");
3317 	} else {
3318 		if ((nd->nd_flag & ND_NFSV41) != 0)
3319 			printf("EEK! no clientid from session\n");
3320 		nd->nd_flag |= ND_IMPLIEDCLID;
3321 		nd->nd_clientid.qval = clientid.qval;
3322 	}
3323 	nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p,
3324 	    &writeacc);
3325 	/* For pNFS, update the attributes. */
3326 	if (writeacc != 0 || nfsrv_pnfsatime != 0)
3327 		nfsrv_updatemdsattr(vp, &na, p);
3328 	vput(vp);
3329 	if (!nd->nd_repstat) {
3330 		/*
3331 		 * If the stateid that has been closed is the current stateid,
3332 		 * unset it.
3333 		 */
3334 		if ((nd->nd_flag & ND_CURSTATEID) != 0 &&
3335 		    stateid.other[0] == nd->nd_curstateid.other[0] &&
3336 		    stateid.other[1] == nd->nd_curstateid.other[1] &&
3337 		    stateid.other[2] == nd->nd_curstateid.other[2])
3338 			nd->nd_flag &= ~ND_CURSTATEID;
3339 		NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
3340 		*tl++ = txdr_unsigned(stateid.seqid);
3341 		NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
3342 	}
3343 	NFSEXITCODE2(0, nd);
3344 	return (0);
3345 nfsmout:
3346 	vput(vp);
3347 	NFSEXITCODE2(error, nd);
3348 	return (error);
3349 }
3350 
3351 /*
3352  * nfsv4 delegpurge service
3353  */
3354 int
3355 nfsrvd_delegpurge(struct nfsrv_descript *nd, __unused int isdgram,
3356     __unused vnode_t vp, __unused struct nfsexstuff *exp)
3357 {
3358 	u_int32_t *tl;
3359 	int error = 0;
3360 	nfsquad_t clientid;
3361 	struct thread *p = curthread;
3362 
3363 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
3364 		goto nfsmout;
3365 	NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
3366 	clientid.lval[0] = *tl++;
3367 	clientid.lval[1] = *tl;
3368 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
3369 		if ((nd->nd_flag & ND_NFSV41) != 0)
3370 			clientid.qval = nd->nd_clientid.qval;
3371 		else if (nd->nd_clientid.qval != clientid.qval)
3372 			printf("EEK9 multiple clids\n");
3373 	} else {
3374 		if ((nd->nd_flag & ND_NFSV41) != 0)
3375 			printf("EEK! no clientid from session\n");
3376 		nd->nd_flag |= ND_IMPLIEDCLID;
3377 		nd->nd_clientid.qval = clientid.qval;
3378 	}
3379 	nd->nd_repstat = nfsrv_delegupdate(nd, clientid, NULL, NULL,
3380 	    NFSV4OP_DELEGPURGE, nd->nd_cred, p, NULL);
3381 nfsmout:
3382 	NFSEXITCODE2(error, nd);
3383 	return (error);
3384 }
3385 
3386 /*
3387  * nfsv4 delegreturn service
3388  */
3389 int
3390 nfsrvd_delegreturn(struct nfsrv_descript *nd, __unused int isdgram,
3391     vnode_t vp, __unused struct nfsexstuff *exp)
3392 {
3393 	u_int32_t *tl;
3394 	int error = 0, writeacc;
3395 	nfsv4stateid_t stateid;
3396 	nfsquad_t clientid;
3397 	struct nfsvattr na;
3398 	struct thread *p = curthread;
3399 
3400 	NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
3401 	stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
3402 	NFSBCOPY((caddr_t)tl, (caddr_t)stateid.other, NFSX_STATEIDOTHER);
3403 	clientid.lval[0] = stateid.other[0];
3404 	clientid.lval[1] = stateid.other[1];
3405 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
3406 		if ((nd->nd_flag & ND_NFSV41) != 0)
3407 			clientid.qval = nd->nd_clientid.qval;
3408 		else if (nd->nd_clientid.qval != clientid.qval)
3409 			printf("EEK10 multiple clids\n");
3410 	} else {
3411 		if ((nd->nd_flag & ND_NFSV41) != 0)
3412 			printf("EEK! no clientid from session\n");
3413 		nd->nd_flag |= ND_IMPLIEDCLID;
3414 		nd->nd_clientid.qval = clientid.qval;
3415 	}
3416 	nd->nd_repstat = nfsrv_delegupdate(nd, clientid, &stateid, vp,
3417 	    NFSV4OP_DELEGRETURN, nd->nd_cred, p, &writeacc);
3418 	/* For pNFS, update the attributes. */
3419 	if (writeacc != 0 || nfsrv_pnfsatime != 0)
3420 		nfsrv_updatemdsattr(vp, &na, p);
3421 nfsmout:
3422 	vput(vp);
3423 	NFSEXITCODE2(error, nd);
3424 	return (error);
3425 }
3426 
3427 /*
3428  * nfsv4 get file handle service
3429  */
3430 int
3431 nfsrvd_getfh(struct nfsrv_descript *nd, __unused int isdgram,
3432     vnode_t vp, __unused struct nfsexstuff *exp)
3433 {
3434 	fhandle_t fh;
3435 	struct thread *p = curthread;
3436 
3437 	nd->nd_repstat = nfsvno_getfh(vp, &fh, p);
3438 	vput(vp);
3439 	if (!nd->nd_repstat)
3440 		(void) nfsm_fhtom(nd, (u_int8_t *)&fh, 0, 0);
3441 	NFSEXITCODE2(0, nd);
3442 	return (0);
3443 }
3444 
3445 /*
3446  * nfsv4 open confirm service
3447  */
3448 int
3449 nfsrvd_openconfirm(struct nfsrv_descript *nd, __unused int isdgram,
3450     vnode_t vp, __unused struct nfsexstuff *exp)
3451 {
3452 	u_int32_t *tl;
3453 	struct nfsstate st, *stp = &st;
3454 	int error = 0;
3455 	nfsv4stateid_t stateid;
3456 	nfsquad_t clientid;
3457 	struct thread *p = curthread;
3458 
3459 	if ((nd->nd_flag & ND_NFSV41) != 0) {
3460 		nd->nd_repstat = NFSERR_NOTSUPP;
3461 		goto nfsmout;
3462 	}
3463 	NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + NFSX_UNSIGNED);
3464 	stp->ls_ownerlen = 0;
3465 	stp->ls_op = nd->nd_rp;
3466 	stp->ls_uid = nd->nd_cred->cr_uid;
3467 	stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
3468 	NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
3469 	    NFSX_STATEIDOTHER);
3470 	tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
3471 	stp->ls_seq = fxdr_unsigned(u_int32_t, *tl);
3472 	stp->ls_flags = NFSLCK_CONFIRM;
3473 	clientid.lval[0] = stp->ls_stateid.other[0];
3474 	clientid.lval[1] = stp->ls_stateid.other[1];
3475 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
3476 		if ((nd->nd_flag & ND_NFSV41) != 0)
3477 			clientid.qval = nd->nd_clientid.qval;
3478 		else if (nd->nd_clientid.qval != clientid.qval)
3479 			printf("EEK11 multiple clids\n");
3480 	} else {
3481 		if ((nd->nd_flag & ND_NFSV41) != 0)
3482 			printf("EEK! no clientid from session\n");
3483 		nd->nd_flag |= ND_IMPLIEDCLID;
3484 		nd->nd_clientid.qval = clientid.qval;
3485 	}
3486 	nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p,
3487 	    NULL);
3488 	if (!nd->nd_repstat) {
3489 		NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
3490 		*tl++ = txdr_unsigned(stateid.seqid);
3491 		NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
3492 	}
3493 nfsmout:
3494 	vput(vp);
3495 	NFSEXITCODE2(error, nd);
3496 	return (error);
3497 }
3498 
3499 /*
3500  * nfsv4 open downgrade service
3501  */
3502 int
3503 nfsrvd_opendowngrade(struct nfsrv_descript *nd, __unused int isdgram,
3504     vnode_t vp, __unused struct nfsexstuff *exp)
3505 {
3506 	u_int32_t *tl;
3507 	int i;
3508 	struct nfsstate st, *stp = &st;
3509 	int error = 0;
3510 	nfsv4stateid_t stateid;
3511 	nfsquad_t clientid;
3512 	struct thread *p = curthread;
3513 
3514 	/* opendowngrade can only work on a file object.*/
3515 	if (vp->v_type != VREG) {
3516 		error = NFSERR_INVAL;
3517 		goto nfsmout;
3518 	}
3519 	NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + 3 * NFSX_UNSIGNED);
3520 	stp->ls_ownerlen = 0;
3521 	stp->ls_op = nd->nd_rp;
3522 	stp->ls_uid = nd->nd_cred->cr_uid;
3523 	stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
3524 	NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
3525 	    NFSX_STATEIDOTHER);
3526 	tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
3527 
3528 	/*
3529 	 * For the special stateid of other all 0s and seqid == 1, set the
3530 	 * stateid to the current stateid, if it is set.
3531 	 */
3532 	if ((nd->nd_flag & ND_NFSV41) != 0 && stp->ls_stateid.seqid == 1 &&
3533 	    stp->ls_stateid.other[0] == 0 && stp->ls_stateid.other[1] == 0 &&
3534 	    stp->ls_stateid.other[2] == 0) {
3535 		if ((nd->nd_flag & ND_CURSTATEID) != 0)
3536 			stp->ls_stateid = nd->nd_curstateid;
3537 		else {
3538 			nd->nd_repstat = NFSERR_BADSTATEID;
3539 			goto nfsmout;
3540 		}
3541 	}
3542 
3543 	stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++);
3544 	i = fxdr_unsigned(int, *tl++);
3545 	if ((nd->nd_flag & ND_NFSV41) != 0)
3546 		i &= ~NFSV4OPEN_WANTDELEGMASK;
3547 	switch (i) {
3548 	case NFSV4OPEN_ACCESSREAD:
3549 		stp->ls_flags = (NFSLCK_READACCESS | NFSLCK_DOWNGRADE);
3550 		break;
3551 	case NFSV4OPEN_ACCESSWRITE:
3552 		stp->ls_flags = (NFSLCK_WRITEACCESS | NFSLCK_DOWNGRADE);
3553 		break;
3554 	case NFSV4OPEN_ACCESSBOTH:
3555 		stp->ls_flags = (NFSLCK_READACCESS | NFSLCK_WRITEACCESS |
3556 		    NFSLCK_DOWNGRADE);
3557 		break;
3558 	default:
3559 		nd->nd_repstat = NFSERR_INVAL;
3560 	}
3561 	i = fxdr_unsigned(int, *tl);
3562 	switch (i) {
3563 	case NFSV4OPEN_DENYNONE:
3564 		break;
3565 	case NFSV4OPEN_DENYREAD:
3566 		stp->ls_flags |= NFSLCK_READDENY;
3567 		break;
3568 	case NFSV4OPEN_DENYWRITE:
3569 		stp->ls_flags |= NFSLCK_WRITEDENY;
3570 		break;
3571 	case NFSV4OPEN_DENYBOTH:
3572 		stp->ls_flags |= (NFSLCK_READDENY | NFSLCK_WRITEDENY);
3573 		break;
3574 	default:
3575 		nd->nd_repstat = NFSERR_INVAL;
3576 	}
3577 
3578 	clientid.lval[0] = stp->ls_stateid.other[0];
3579 	clientid.lval[1] = stp->ls_stateid.other[1];
3580 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
3581 		if ((nd->nd_flag & ND_NFSV41) != 0)
3582 			clientid.qval = nd->nd_clientid.qval;
3583 		else if (nd->nd_clientid.qval != clientid.qval)
3584 			printf("EEK12 multiple clids\n");
3585 	} else {
3586 		if ((nd->nd_flag & ND_NFSV41) != 0)
3587 			printf("EEK! no clientid from session\n");
3588 		nd->nd_flag |= ND_IMPLIEDCLID;
3589 		nd->nd_clientid.qval = clientid.qval;
3590 	}
3591 	if (!nd->nd_repstat)
3592 		nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid,
3593 		    nd, p, NULL);
3594 	if (!nd->nd_repstat) {
3595 		/* For NFSv4.1, set the Current StateID. */
3596 		if ((nd->nd_flag & ND_NFSV41) != 0) {
3597 			nd->nd_curstateid = stateid;
3598 			nd->nd_flag |= ND_CURSTATEID;
3599 		}
3600 		NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
3601 		*tl++ = txdr_unsigned(stateid.seqid);
3602 		NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
3603 	}
3604 nfsmout:
3605 	vput(vp);
3606 	NFSEXITCODE2(error, nd);
3607 	return (error);
3608 }
3609 
3610 /*
3611  * nfsv4 renew lease service
3612  */
3613 int
3614 nfsrvd_renew(struct nfsrv_descript *nd, __unused int isdgram,
3615     __unused vnode_t vp, __unused struct nfsexstuff *exp)
3616 {
3617 	u_int32_t *tl;
3618 	int error = 0;
3619 	nfsquad_t clientid;
3620 	struct thread *p = curthread;
3621 
3622 	if ((nd->nd_flag & ND_NFSV41) != 0) {
3623 		nd->nd_repstat = NFSERR_NOTSUPP;
3624 		goto nfsmout;
3625 	}
3626 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
3627 		goto nfsmout;
3628 	NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
3629 	clientid.lval[0] = *tl++;
3630 	clientid.lval[1] = *tl;
3631 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
3632 		if ((nd->nd_flag & ND_NFSV41) != 0)
3633 			clientid.qval = nd->nd_clientid.qval;
3634 		else if (nd->nd_clientid.qval != clientid.qval)
3635 			printf("EEK13 multiple clids\n");
3636 	} else {
3637 		if ((nd->nd_flag & ND_NFSV41) != 0)
3638 			printf("EEK! no clientid from session\n");
3639 		nd->nd_flag |= ND_IMPLIEDCLID;
3640 		nd->nd_clientid.qval = clientid.qval;
3641 	}
3642 	nd->nd_repstat = nfsrv_getclient(clientid, (CLOPS_RENEWOP|CLOPS_RENEW),
3643 	    NULL, NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p);
3644 nfsmout:
3645 	NFSEXITCODE2(error, nd);
3646 	return (error);
3647 }
3648 
3649 /*
3650  * nfsv4 security info service
3651  */
3652 int
3653 nfsrvd_secinfo(struct nfsrv_descript *nd, int isdgram,
3654     vnode_t dp, struct nfsexstuff *exp)
3655 {
3656 	u_int32_t *tl;
3657 	int len;
3658 	struct nameidata named;
3659 	vnode_t dirp = NULL, vp;
3660 	struct nfsrvfh fh;
3661 	struct nfsexstuff retnes;
3662 	u_int32_t *sizp;
3663 	int error = 0, i;
3664 	uint64_t savflag;
3665 	char *bufp;
3666 	u_long *hashp;
3667 	struct thread *p = curthread;
3668 
3669 	/*
3670 	 * All this just to get the export flags for the name.
3671 	 */
3672 	NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP,
3673 	    LOCKLEAF | SAVESTART);
3674 	nfsvno_setpathbuf(&named, &bufp, &hashp);
3675 	error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
3676 	if (error) {
3677 		vput(dp);
3678 		nfsvno_relpathbuf(&named);
3679 		goto out;
3680 	}
3681 	if (!nd->nd_repstat) {
3682 		nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, p, &dirp);
3683 	} else {
3684 		vput(dp);
3685 		nfsvno_relpathbuf(&named);
3686 	}
3687 	if (dirp)
3688 		vrele(dirp);
3689 	if (nd->nd_repstat)
3690 		goto out;
3691 	vrele(named.ni_startdir);
3692 	nfsvno_relpathbuf(&named);
3693 	fh.nfsrvfh_len = NFSX_MYFH;
3694 	vp = named.ni_vp;
3695 	nd->nd_repstat = nfsvno_getfh(vp, (fhandle_t *)fh.nfsrvfh_data, p);
3696 	vput(vp);
3697 	savflag = nd->nd_flag;
3698 	if (!nd->nd_repstat) {
3699 		/*
3700 		 * Pretend the next op is Secinfo, so that no wrongsec
3701 		 * test will be done.
3702 		 */
3703 		nfsd_fhtovp(nd, &fh, LK_SHARED, &vp, &retnes, NULL, 0,
3704 		    NFSV4OP_SECINFO);
3705 		if (vp)
3706 			vput(vp);
3707 	}
3708 	nd->nd_flag = savflag;
3709 	if (nd->nd_repstat)
3710 		goto out;
3711 
3712 	/*
3713 	 * Finally have the export flags for name, so we can create
3714 	 * the security info.
3715 	 */
3716 	len = 0;
3717 	NFSM_BUILD(sizp, u_int32_t *, NFSX_UNSIGNED);
3718 
3719 	/* If nes_numsecflavor == 0, all are allowed. */
3720 	if (retnes.nes_numsecflavor == 0) {
3721 		NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
3722 		*tl++ = txdr_unsigned(RPCAUTH_UNIX);
3723 		*tl = txdr_unsigned(RPCAUTH_GSS);
3724 		nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
3725 		    nfsgss_mechlist[KERBV_MECH].len);
3726 		NFSM_BUILD(tl, uint32_t *, 3 * NFSX_UNSIGNED);
3727 		*tl++ = txdr_unsigned(GSS_KERBV_QOP);
3728 		*tl++ = txdr_unsigned(RPCAUTHGSS_SVCNONE);
3729 		*tl = txdr_unsigned(RPCAUTH_GSS);
3730 		nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
3731 		    nfsgss_mechlist[KERBV_MECH].len);
3732 		NFSM_BUILD(tl, uint32_t *, 3 * NFSX_UNSIGNED);
3733 		*tl++ = txdr_unsigned(GSS_KERBV_QOP);
3734 		*tl++ = txdr_unsigned(RPCAUTHGSS_SVCINTEGRITY);
3735 		*tl = txdr_unsigned(RPCAUTH_GSS);
3736 		nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
3737 		    nfsgss_mechlist[KERBV_MECH].len);
3738 		NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
3739 		*tl++ = txdr_unsigned(GSS_KERBV_QOP);
3740 		*tl = txdr_unsigned(RPCAUTHGSS_SVCPRIVACY);
3741 		len = 4;
3742 	}
3743 	for (i = 0; i < retnes.nes_numsecflavor; i++) {
3744 		if (retnes.nes_secflavors[i] == AUTH_SYS) {
3745 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3746 			*tl = txdr_unsigned(RPCAUTH_UNIX);
3747 			len++;
3748 		} else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5) {
3749 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3750 			*tl++ = txdr_unsigned(RPCAUTH_GSS);
3751 			(void) nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
3752 			    nfsgss_mechlist[KERBV_MECH].len);
3753 			NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
3754 			*tl++ = txdr_unsigned(GSS_KERBV_QOP);
3755 			*tl = txdr_unsigned(RPCAUTHGSS_SVCNONE);
3756 			len++;
3757 		} else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5I) {
3758 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3759 			*tl++ = txdr_unsigned(RPCAUTH_GSS);
3760 			(void) nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
3761 			    nfsgss_mechlist[KERBV_MECH].len);
3762 			NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
3763 			*tl++ = txdr_unsigned(GSS_KERBV_QOP);
3764 			*tl = txdr_unsigned(RPCAUTHGSS_SVCINTEGRITY);
3765 			len++;
3766 		} else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5P) {
3767 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3768 			*tl++ = txdr_unsigned(RPCAUTH_GSS);
3769 			(void) nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
3770 			    nfsgss_mechlist[KERBV_MECH].len);
3771 			NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
3772 			*tl++ = txdr_unsigned(GSS_KERBV_QOP);
3773 			*tl = txdr_unsigned(RPCAUTHGSS_SVCPRIVACY);
3774 			len++;
3775 		}
3776 	}
3777 	*sizp = txdr_unsigned(len);
3778 
3779 out:
3780 	NFSEXITCODE2(error, nd);
3781 	return (error);
3782 }
3783 
3784 /*
3785  * nfsv4 security info no name service
3786  */
3787 int
3788 nfsrvd_secinfononame(struct nfsrv_descript *nd, int isdgram,
3789     vnode_t dp, struct nfsexstuff *exp)
3790 {
3791 	uint32_t *tl, *sizp;
3792 	struct nameidata named;
3793 	vnode_t dirp = NULL, vp;
3794 	struct nfsrvfh fh;
3795 	struct nfsexstuff retnes;
3796 	int error = 0, fhstyle, i, len;
3797 	uint64_t savflag;
3798 	char *bufp;
3799 	u_long *hashp;
3800 	struct thread *p = curthread;
3801 
3802 	NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
3803 	fhstyle = fxdr_unsigned(int, *tl);
3804 	switch (fhstyle) {
3805 	case NFSSECINFONONAME_PARENT:
3806 		NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP,
3807 		    LOCKLEAF | SAVESTART);
3808 		nfsvno_setpathbuf(&named, &bufp, &hashp);
3809 		error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
3810 		if (error != 0) {
3811 			vput(dp);
3812 			nfsvno_relpathbuf(&named);
3813 			goto nfsmout;
3814 		}
3815 		if (nd->nd_repstat == 0)
3816 			nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, p, &dirp);
3817 		else
3818 			vput(dp);
3819 		if (dirp != NULL)
3820 			vrele(dirp);
3821 		vrele(named.ni_startdir);
3822 		nfsvno_relpathbuf(&named);
3823 		vp = named.ni_vp;
3824 		break;
3825 	case NFSSECINFONONAME_CURFH:
3826 		vp = dp;
3827 		break;
3828 	default:
3829 		nd->nd_repstat = NFSERR_INVAL;
3830 		vput(dp);
3831 	}
3832 	if (nd->nd_repstat != 0)
3833 		goto nfsmout;
3834 	fh.nfsrvfh_len = NFSX_MYFH;
3835 	nd->nd_repstat = nfsvno_getfh(vp, (fhandle_t *)fh.nfsrvfh_data, p);
3836 	vput(vp);
3837 	savflag = nd->nd_flag;
3838 	if (nd->nd_repstat == 0) {
3839 		/*
3840 		 * Pretend the next op is Secinfo, so that no wrongsec
3841 		 * test will be done.
3842 		 */
3843 		nfsd_fhtovp(nd, &fh, LK_SHARED, &vp, &retnes, NULL, 0,
3844 		    NFSV4OP_SECINFO);
3845 		if (vp != NULL)
3846 			vput(vp);
3847 	}
3848 	nd->nd_flag = savflag;
3849 	if (nd->nd_repstat != 0)
3850 		goto nfsmout;
3851 
3852 	/*
3853 	 * Finally have the export flags for fh/parent, so we can create
3854 	 * the security info.
3855 	 */
3856 	len = 0;
3857 	NFSM_BUILD(sizp, uint32_t *, NFSX_UNSIGNED);
3858 
3859 	/* If nes_numsecflavor == 0, all are allowed. */
3860 	if (retnes.nes_numsecflavor == 0) {
3861 		NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
3862 		*tl++ = txdr_unsigned(RPCAUTH_UNIX);
3863 		*tl = txdr_unsigned(RPCAUTH_GSS);
3864 		nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
3865 		    nfsgss_mechlist[KERBV_MECH].len);
3866 		NFSM_BUILD(tl, uint32_t *, 3 * NFSX_UNSIGNED);
3867 		*tl++ = txdr_unsigned(GSS_KERBV_QOP);
3868 		*tl++ = txdr_unsigned(RPCAUTHGSS_SVCNONE);
3869 		*tl = txdr_unsigned(RPCAUTH_GSS);
3870 		nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
3871 		    nfsgss_mechlist[KERBV_MECH].len);
3872 		NFSM_BUILD(tl, uint32_t *, 3 * NFSX_UNSIGNED);
3873 		*tl++ = txdr_unsigned(GSS_KERBV_QOP);
3874 		*tl++ = txdr_unsigned(RPCAUTHGSS_SVCINTEGRITY);
3875 		*tl = txdr_unsigned(RPCAUTH_GSS);
3876 		nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
3877 		    nfsgss_mechlist[KERBV_MECH].len);
3878 		NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
3879 		*tl++ = txdr_unsigned(GSS_KERBV_QOP);
3880 		*tl = txdr_unsigned(RPCAUTHGSS_SVCPRIVACY);
3881 		len = 4;
3882 	}
3883 	for (i = 0; i < retnes.nes_numsecflavor; i++) {
3884 		if (retnes.nes_secflavors[i] == AUTH_SYS) {
3885 			NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
3886 			*tl = txdr_unsigned(RPCAUTH_UNIX);
3887 			len++;
3888 		} else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5) {
3889 			NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
3890 			*tl = txdr_unsigned(RPCAUTH_GSS);
3891 			nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
3892 			    nfsgss_mechlist[KERBV_MECH].len);
3893 			NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
3894 			*tl++ = txdr_unsigned(GSS_KERBV_QOP);
3895 			*tl = txdr_unsigned(RPCAUTHGSS_SVCNONE);
3896 			len++;
3897 		} else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5I) {
3898 			NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
3899 			*tl = txdr_unsigned(RPCAUTH_GSS);
3900 			nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
3901 			    nfsgss_mechlist[KERBV_MECH].len);
3902 			NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
3903 			*tl++ = txdr_unsigned(GSS_KERBV_QOP);
3904 			*tl = txdr_unsigned(RPCAUTHGSS_SVCINTEGRITY);
3905 			len++;
3906 		} else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5P) {
3907 			NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
3908 			*tl = txdr_unsigned(RPCAUTH_GSS);
3909 			nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
3910 			    nfsgss_mechlist[KERBV_MECH].len);
3911 			NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
3912 			*tl++ = txdr_unsigned(GSS_KERBV_QOP);
3913 			*tl = txdr_unsigned(RPCAUTHGSS_SVCPRIVACY);
3914 			len++;
3915 		}
3916 	}
3917 	*sizp = txdr_unsigned(len);
3918 
3919 nfsmout:
3920 	NFSEXITCODE2(error, nd);
3921 	return (error);
3922 }
3923 
3924 /*
3925  * nfsv4 set client id service
3926  */
3927 int
3928 nfsrvd_setclientid(struct nfsrv_descript *nd, __unused int isdgram,
3929     __unused vnode_t vp, __unused struct nfsexstuff *exp)
3930 {
3931 	u_int32_t *tl;
3932 	int i;
3933 	int error = 0, idlen;
3934 	struct nfsclient *clp = NULL;
3935 #ifdef INET
3936 	struct sockaddr_in *rin;
3937 #endif
3938 #ifdef INET6
3939 	struct sockaddr_in6 *rin6;
3940 #endif
3941 #if defined(INET) || defined(INET6)
3942 	u_char *ucp, *ucp2;
3943 #endif
3944 	u_char *verf, *addrbuf;
3945 	nfsquad_t clientid, confirm;
3946 	struct thread *p = curthread;
3947 
3948 	if ((nd->nd_flag & ND_NFSV41) != 0) {
3949 		nd->nd_repstat = NFSERR_NOTSUPP;
3950 		goto nfsmout;
3951 	}
3952 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
3953 		goto out;
3954 	NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF + NFSX_UNSIGNED);
3955 	verf = (u_char *)tl;
3956 	tl += (NFSX_VERF / NFSX_UNSIGNED);
3957 	i = fxdr_unsigned(int, *tl);
3958 	if (i > NFSV4_OPAQUELIMIT || i <= 0) {
3959 		nd->nd_repstat = NFSERR_BADXDR;
3960 		goto nfsmout;
3961 	}
3962 	idlen = i;
3963 	if (nd->nd_flag & ND_GSS)
3964 		i += nd->nd_princlen;
3965 	clp = malloc(sizeof(struct nfsclient) + i, M_NFSDCLIENT, M_WAITOK |
3966 	    M_ZERO);
3967 	clp->lc_stateid = malloc(sizeof(struct nfsstatehead) *
3968 	    nfsrv_statehashsize, M_NFSDCLIENT, M_WAITOK);
3969 	NFSINITSOCKMUTEX(&clp->lc_req.nr_mtx);
3970 	/* Allocated large enough for an AF_INET or AF_INET6 socket. */
3971 	clp->lc_req.nr_nam = malloc(sizeof(struct sockaddr_in6), M_SONAME,
3972 	    M_WAITOK | M_ZERO);
3973 	clp->lc_req.nr_cred = NULL;
3974 	NFSBCOPY(verf, clp->lc_verf, NFSX_VERF);
3975 	clp->lc_idlen = idlen;
3976 	error = nfsrv_mtostr(nd, clp->lc_id, idlen);
3977 	if (error)
3978 		goto nfsmout;
3979 	if (nd->nd_flag & ND_GSS) {
3980 		clp->lc_flags = LCL_GSS;
3981 		if (nd->nd_flag & ND_GSSINTEGRITY)
3982 			clp->lc_flags |= LCL_GSSINTEGRITY;
3983 		else if (nd->nd_flag & ND_GSSPRIVACY)
3984 			clp->lc_flags |= LCL_GSSPRIVACY;
3985 	} else {
3986 		clp->lc_flags = 0;
3987 	}
3988 	if ((nd->nd_flag & ND_GSS) && nd->nd_princlen > 0) {
3989 		clp->lc_flags |= LCL_NAME;
3990 		clp->lc_namelen = nd->nd_princlen;
3991 		clp->lc_name = &clp->lc_id[idlen];
3992 		NFSBCOPY(nd->nd_principal, clp->lc_name, clp->lc_namelen);
3993 	} else {
3994 		clp->lc_uid = nd->nd_cred->cr_uid;
3995 		clp->lc_gid = nd->nd_cred->cr_gid;
3996 	}
3997 
3998 	/* If the client is using TLS, do so for the callback connection. */
3999 	if (nd->nd_flag & ND_TLS)
4000 		clp->lc_flags |= LCL_TLSCB;
4001 
4002 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
4003 	clp->lc_program = fxdr_unsigned(u_int32_t, *tl);
4004 	error = nfsrv_getclientipaddr(nd, clp);
4005 	if (error)
4006 		goto nfsmout;
4007 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
4008 	clp->lc_callback = fxdr_unsigned(u_int32_t, *tl);
4009 
4010 	/*
4011 	 * nfsrv_setclient() does the actual work of adding it to the
4012 	 * client list. If there is no error, the structure has been
4013 	 * linked into the client list and clp should no longer be used
4014 	 * here. When an error is returned, it has not been linked in,
4015 	 * so it should be free'd.
4016 	 */
4017 	nd->nd_repstat = nfsrv_setclient(nd, &clp, &clientid, &confirm, p);
4018 	if (nd->nd_repstat == NFSERR_CLIDINUSE) {
4019 		/*
4020 		 * 8 is the maximum length of the port# string.
4021 		 */
4022 		addrbuf = malloc(INET6_ADDRSTRLEN + 8, M_TEMP, M_WAITOK);
4023 		switch (clp->lc_req.nr_nam->sa_family) {
4024 #ifdef INET
4025 		case AF_INET:
4026 			if (clp->lc_flags & LCL_TCPCALLBACK)
4027 				(void) nfsm_strtom(nd, "tcp", 3);
4028 			else
4029 				(void) nfsm_strtom(nd, "udp", 3);
4030 			rin = (struct sockaddr_in *)clp->lc_req.nr_nam;
4031 			ucp = (u_char *)&rin->sin_addr.s_addr;
4032 			ucp2 = (u_char *)&rin->sin_port;
4033 			sprintf(addrbuf, "%d.%d.%d.%d.%d.%d", ucp[0] & 0xff,
4034 			    ucp[1] & 0xff, ucp[2] & 0xff, ucp[3] & 0xff,
4035 			    ucp2[0] & 0xff, ucp2[1] & 0xff);
4036 			break;
4037 #endif
4038 #ifdef INET6
4039 		case AF_INET6:
4040 			if (clp->lc_flags & LCL_TCPCALLBACK)
4041 				(void) nfsm_strtom(nd, "tcp6", 4);
4042 			else
4043 				(void) nfsm_strtom(nd, "udp6", 4);
4044 			rin6 = (struct sockaddr_in6 *)clp->lc_req.nr_nam;
4045 			ucp = inet_ntop(AF_INET6, &rin6->sin6_addr, addrbuf,
4046 			    INET6_ADDRSTRLEN);
4047 			if (ucp != NULL)
4048 				i = strlen(ucp);
4049 			else
4050 				i = 0;
4051 			ucp2 = (u_char *)&rin6->sin6_port;
4052 			sprintf(&addrbuf[i], ".%d.%d", ucp2[0] & 0xff,
4053 			    ucp2[1] & 0xff);
4054 			break;
4055 #endif
4056 		}
4057 		(void) nfsm_strtom(nd, addrbuf, strlen(addrbuf));
4058 		free(addrbuf, M_TEMP);
4059 	}
4060 	if (clp) {
4061 		free(clp->lc_req.nr_nam, M_SONAME);
4062 		NFSFREEMUTEX(&clp->lc_req.nr_mtx);
4063 		free(clp->lc_stateid, M_NFSDCLIENT);
4064 		free(clp, M_NFSDCLIENT);
4065 	}
4066 	if (!nd->nd_repstat) {
4067 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_HYPER);
4068 		*tl++ = clientid.lval[0];
4069 		*tl++ = clientid.lval[1];
4070 		*tl++ = confirm.lval[0];
4071 		*tl = confirm.lval[1];
4072 	}
4073 
4074 out:
4075 	NFSEXITCODE2(0, nd);
4076 	return (0);
4077 nfsmout:
4078 	if (clp) {
4079 		free(clp->lc_req.nr_nam, M_SONAME);
4080 		NFSFREEMUTEX(&clp->lc_req.nr_mtx);
4081 		free(clp->lc_stateid, M_NFSDCLIENT);
4082 		free(clp, M_NFSDCLIENT);
4083 	}
4084 	NFSEXITCODE2(error, nd);
4085 	return (error);
4086 }
4087 
4088 /*
4089  * nfsv4 set client id confirm service
4090  */
4091 int
4092 nfsrvd_setclientidcfrm(struct nfsrv_descript *nd,
4093     __unused int isdgram, __unused vnode_t vp,
4094     __unused struct nfsexstuff *exp)
4095 {
4096 	u_int32_t *tl;
4097 	int error = 0;
4098 	nfsquad_t clientid, confirm;
4099 	struct thread *p = curthread;
4100 
4101 	if ((nd->nd_flag & ND_NFSV41) != 0) {
4102 		nd->nd_repstat = NFSERR_NOTSUPP;
4103 		goto nfsmout;
4104 	}
4105 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
4106 		goto nfsmout;
4107 	NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_HYPER);
4108 	clientid.lval[0] = *tl++;
4109 	clientid.lval[1] = *tl++;
4110 	confirm.lval[0] = *tl++;
4111 	confirm.lval[1] = *tl;
4112 
4113 	/*
4114 	 * nfsrv_getclient() searches the client list for a match and
4115 	 * returns the appropriate NFSERR status.
4116 	 */
4117 	nd->nd_repstat = nfsrv_getclient(clientid, (CLOPS_CONFIRM|CLOPS_RENEW),
4118 	    NULL, NULL, confirm, 0, nd, p);
4119 nfsmout:
4120 	NFSEXITCODE2(error, nd);
4121 	return (error);
4122 }
4123 
4124 /*
4125  * nfsv4 verify service
4126  */
4127 int
4128 nfsrvd_verify(struct nfsrv_descript *nd, int isdgram,
4129     vnode_t vp, __unused struct nfsexstuff *exp)
4130 {
4131 	int error = 0, ret, fhsize = NFSX_MYFH;
4132 	struct nfsvattr nva;
4133 	struct statfs *sf;
4134 	struct nfsfsinfo fs;
4135 	fhandle_t fh;
4136 	struct thread *p = curthread;
4137 
4138 	sf = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
4139 	nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
4140 	if (!nd->nd_repstat)
4141 		nd->nd_repstat = nfsvno_statfs(vp, sf);
4142 	if (!nd->nd_repstat)
4143 		nd->nd_repstat = nfsvno_getfh(vp, &fh, p);
4144 	if (!nd->nd_repstat) {
4145 		nfsvno_getfs(&fs, isdgram);
4146 		error = nfsv4_loadattr(nd, vp, &nva, NULL, &fh, fhsize, NULL,
4147 		    sf, NULL, &fs, NULL, 1, &ret, NULL, NULL, p, nd->nd_cred);
4148 		if (!error) {
4149 			if (nd->nd_procnum == NFSV4OP_NVERIFY) {
4150 				if (ret == 0)
4151 					nd->nd_repstat = NFSERR_SAME;
4152 				else if (ret != NFSERR_NOTSAME)
4153 					nd->nd_repstat = ret;
4154 			} else if (ret)
4155 				nd->nd_repstat = ret;
4156 		}
4157 	}
4158 	vput(vp);
4159 	free(sf, M_STATFS);
4160 	NFSEXITCODE2(error, nd);
4161 	return (error);
4162 }
4163 
4164 /*
4165  * nfs openattr rpc
4166  */
4167 int
4168 nfsrvd_openattr(struct nfsrv_descript *nd, __unused int isdgram,
4169     vnode_t dp, __unused vnode_t *vpp, __unused fhandle_t *fhp,
4170     __unused struct nfsexstuff *exp)
4171 {
4172 	u_int32_t *tl;
4173 	int error = 0, createdir __unused;
4174 
4175 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
4176 	createdir = fxdr_unsigned(int, *tl);
4177 	nd->nd_repstat = NFSERR_NOTSUPP;
4178 nfsmout:
4179 	vrele(dp);
4180 	NFSEXITCODE2(error, nd);
4181 	return (error);
4182 }
4183 
4184 /*
4185  * nfsv4 release lock owner service
4186  */
4187 int
4188 nfsrvd_releaselckown(struct nfsrv_descript *nd, __unused int isdgram,
4189     __unused vnode_t vp, __unused struct nfsexstuff *exp)
4190 {
4191 	u_int32_t *tl;
4192 	struct nfsstate *stp = NULL;
4193 	int error = 0, len;
4194 	nfsquad_t clientid;
4195 	struct thread *p = curthread;
4196 
4197 	if ((nd->nd_flag & ND_NFSV41) != 0) {
4198 		nd->nd_repstat = NFSERR_NOTSUPP;
4199 		goto nfsmout;
4200 	}
4201 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
4202 		goto nfsmout;
4203 	NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
4204 	len = fxdr_unsigned(int, *(tl + 2));
4205 	if (len <= 0 || len > NFSV4_OPAQUELIMIT) {
4206 		nd->nd_repstat = NFSERR_BADXDR;
4207 		goto nfsmout;
4208 	}
4209 	stp = malloc(sizeof (struct nfsstate) + len,
4210 	    M_NFSDSTATE, M_WAITOK);
4211 	stp->ls_ownerlen = len;
4212 	stp->ls_op = NULL;
4213 	stp->ls_flags = NFSLCK_RELEASE;
4214 	stp->ls_uid = nd->nd_cred->cr_uid;
4215 	clientid.lval[0] = *tl++;
4216 	clientid.lval[1] = *tl;
4217 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
4218 		if ((nd->nd_flag & ND_NFSV41) != 0)
4219 			clientid.qval = nd->nd_clientid.qval;
4220 		else if (nd->nd_clientid.qval != clientid.qval)
4221 			printf("EEK14 multiple clids\n");
4222 	} else {
4223 		if ((nd->nd_flag & ND_NFSV41) != 0)
4224 			printf("EEK! no clientid from session\n");
4225 		nd->nd_flag |= ND_IMPLIEDCLID;
4226 		nd->nd_clientid.qval = clientid.qval;
4227 	}
4228 	error = nfsrv_mtostr(nd, stp->ls_owner, len);
4229 	if (error)
4230 		goto nfsmout;
4231 	nd->nd_repstat = nfsrv_releaselckown(stp, clientid, p);
4232 	free(stp, M_NFSDSTATE);
4233 
4234 	NFSEXITCODE2(0, nd);
4235 	return (0);
4236 nfsmout:
4237 	if (stp)
4238 		free(stp, M_NFSDSTATE);
4239 	NFSEXITCODE2(error, nd);
4240 	return (error);
4241 }
4242 
4243 /*
4244  * nfsv4 exchange_id service
4245  */
4246 int
4247 nfsrvd_exchangeid(struct nfsrv_descript *nd, __unused int isdgram,
4248     __unused vnode_t vp, __unused struct nfsexstuff *exp)
4249 {
4250 	uint32_t *tl;
4251 	int error = 0, i, idlen;
4252 	struct nfsclient *clp = NULL;
4253 	nfsquad_t clientid, confirm;
4254 	uint8_t *verf;
4255 	uint32_t sp4type, v41flags;
4256 	uint64_t owner_minor;
4257 	struct timespec verstime;
4258 #ifdef INET
4259 	struct sockaddr_in *sin, *rin;
4260 #endif
4261 #ifdef INET6
4262 	struct sockaddr_in6 *sin6, *rin6;
4263 #endif
4264 	struct thread *p = curthread;
4265 
4266 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
4267 		goto nfsmout;
4268 	NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF + NFSX_UNSIGNED);
4269 	verf = (uint8_t *)tl;
4270 	tl += (NFSX_VERF / NFSX_UNSIGNED);
4271 	i = fxdr_unsigned(int, *tl);
4272 	if (i > NFSV4_OPAQUELIMIT || i <= 0) {
4273 		nd->nd_repstat = NFSERR_BADXDR;
4274 		goto nfsmout;
4275 	}
4276 	idlen = i;
4277 	if (nd->nd_flag & ND_GSS)
4278 		i += nd->nd_princlen;
4279 	clp = malloc(sizeof(struct nfsclient) + i, M_NFSDCLIENT, M_WAITOK |
4280 	    M_ZERO);
4281 	clp->lc_stateid = malloc(sizeof(struct nfsstatehead) *
4282 	    nfsrv_statehashsize, M_NFSDCLIENT, M_WAITOK);
4283 	NFSINITSOCKMUTEX(&clp->lc_req.nr_mtx);
4284 	/* Allocated large enough for an AF_INET or AF_INET6 socket. */
4285 	clp->lc_req.nr_nam = malloc(sizeof(struct sockaddr_in6), M_SONAME,
4286 	    M_WAITOK | M_ZERO);
4287 	switch (nd->nd_nam->sa_family) {
4288 #ifdef INET
4289 	case AF_INET:
4290 		rin = (struct sockaddr_in *)clp->lc_req.nr_nam;
4291 		sin = (struct sockaddr_in *)nd->nd_nam;
4292 		rin->sin_family = AF_INET;
4293 		rin->sin_len = sizeof(struct sockaddr_in);
4294 		rin->sin_port = 0;
4295 		rin->sin_addr.s_addr = sin->sin_addr.s_addr;
4296 		break;
4297 #endif
4298 #ifdef INET6
4299 	case AF_INET6:
4300 		rin6 = (struct sockaddr_in6 *)clp->lc_req.nr_nam;
4301 		sin6 = (struct sockaddr_in6 *)nd->nd_nam;
4302 		rin6->sin6_family = AF_INET6;
4303 		rin6->sin6_len = sizeof(struct sockaddr_in6);
4304 		rin6->sin6_port = 0;
4305 		rin6->sin6_addr = sin6->sin6_addr;
4306 		break;
4307 #endif
4308 	}
4309 	clp->lc_req.nr_cred = NULL;
4310 	NFSBCOPY(verf, clp->lc_verf, NFSX_VERF);
4311 	clp->lc_idlen = idlen;
4312 	error = nfsrv_mtostr(nd, clp->lc_id, idlen);
4313 	if (error != 0)
4314 		goto nfsmout;
4315 	if ((nd->nd_flag & ND_GSS) != 0) {
4316 		clp->lc_flags = LCL_GSS | LCL_NFSV41;
4317 		if ((nd->nd_flag & ND_GSSINTEGRITY) != 0)
4318 			clp->lc_flags |= LCL_GSSINTEGRITY;
4319 		else if ((nd->nd_flag & ND_GSSPRIVACY) != 0)
4320 			clp->lc_flags |= LCL_GSSPRIVACY;
4321 	} else
4322 		clp->lc_flags = LCL_NFSV41;
4323 	if ((nd->nd_flag & ND_NFSV42) != 0)
4324 		clp->lc_flags |= LCL_NFSV42;
4325 	if ((nd->nd_flag & ND_GSS) != 0 && nd->nd_princlen > 0) {
4326 		clp->lc_flags |= LCL_NAME;
4327 		clp->lc_namelen = nd->nd_princlen;
4328 		clp->lc_name = &clp->lc_id[idlen];
4329 		NFSBCOPY(nd->nd_principal, clp->lc_name, clp->lc_namelen);
4330 	} else {
4331 		clp->lc_uid = nd->nd_cred->cr_uid;
4332 		clp->lc_gid = nd->nd_cred->cr_gid;
4333 	}
4334 	NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
4335 	v41flags = fxdr_unsigned(uint32_t, *tl++);
4336 	if ((v41flags & ~(NFSV4EXCH_SUPPMOVEDREFER | NFSV4EXCH_SUPPMOVEDMIGR |
4337 	    NFSV4EXCH_BINDPRINCSTATEID | NFSV4EXCH_MASKPNFS |
4338 	    NFSV4EXCH_UPDCONFIRMEDRECA)) != 0) {
4339 		nd->nd_repstat = NFSERR_INVAL;
4340 		goto nfsmout;
4341 	}
4342 	if ((v41flags & NFSV4EXCH_UPDCONFIRMEDRECA) != 0)
4343 		confirm.lval[1] = 1;
4344 	else
4345 		confirm.lval[1] = 0;
4346 	if (nfsrv_devidcnt == 0)
4347 		v41flags = NFSV4EXCH_USENONPNFS | NFSV4EXCH_USEPNFSDS;
4348  	else
4349  		v41flags = NFSV4EXCH_USEPNFSMDS;
4350 	sp4type = fxdr_unsigned(uint32_t, *tl);
4351 	if (sp4type != NFSV4EXCH_SP4NONE) {
4352 		nd->nd_repstat = NFSERR_NOTSUPP;
4353 		goto nfsmout;
4354 	}
4355 
4356 	/*
4357 	 * nfsrv_setclient() does the actual work of adding it to the
4358 	 * client list. If there is no error, the structure has been
4359 	 * linked into the client list and clp should no longer be used
4360 	 * here. When an error is returned, it has not been linked in,
4361 	 * so it should be free'd.
4362 	 */
4363 	nd->nd_repstat = nfsrv_setclient(nd, &clp, &clientid, &confirm, p);
4364 	if (clp != NULL) {
4365 		free(clp->lc_req.nr_nam, M_SONAME);
4366 		NFSFREEMUTEX(&clp->lc_req.nr_mtx);
4367 		free(clp->lc_stateid, M_NFSDCLIENT);
4368 		free(clp, M_NFSDCLIENT);
4369 	}
4370 	if (nd->nd_repstat == 0) {
4371 		if (confirm.lval[1] != 0)
4372 			v41flags |= NFSV4EXCH_CONFIRMEDR;
4373 		NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER + 3 * NFSX_UNSIGNED);
4374 		*tl++ = clientid.lval[0];			/* ClientID */
4375 		*tl++ = clientid.lval[1];
4376 		*tl++ = txdr_unsigned(confirm.lval[0]);		/* SequenceID */
4377 		*tl++ = txdr_unsigned(v41flags);		/* Exch flags */
4378 		*tl++ = txdr_unsigned(NFSV4EXCH_SP4NONE);	/* No SSV */
4379 		owner_minor = 0;				/* Owner */
4380 		txdr_hyper(owner_minor, tl);			/* Minor */
4381 		(void)nfsm_strtom(nd, nd->nd_cred->cr_prison->pr_hostuuid,
4382 		    strlen(nd->nd_cred->cr_prison->pr_hostuuid)); /* Major */
4383 		(void)nfsm_strtom(nd, nd->nd_cred->cr_prison->pr_hostuuid,
4384 		    strlen(nd->nd_cred->cr_prison->pr_hostuuid)); /* Scope */
4385 		NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
4386 		*tl = txdr_unsigned(1);
4387 		(void)nfsm_strtom(nd, "freebsd.org", strlen("freebsd.org"));
4388 		(void)nfsm_strtom(nd, version, strlen(version));
4389 		NFSM_BUILD(tl, uint32_t *, NFSX_V4TIME);
4390 		verstime.tv_sec = 1293840000;		/* Jan 1, 2011 */
4391 		verstime.tv_nsec = 0;
4392 		txdr_nfsv4time(&verstime, tl);
4393 	}
4394 	NFSEXITCODE2(0, nd);
4395 	return (0);
4396 nfsmout:
4397 	if (clp != NULL) {
4398 		free(clp->lc_req.nr_nam, M_SONAME);
4399 		NFSFREEMUTEX(&clp->lc_req.nr_mtx);
4400 		free(clp->lc_stateid, M_NFSDCLIENT);
4401 		free(clp, M_NFSDCLIENT);
4402 	}
4403 	NFSEXITCODE2(error, nd);
4404 	return (error);
4405 }
4406 
4407 /*
4408  * nfsv4 create session service
4409  */
4410 int
4411 nfsrvd_createsession(struct nfsrv_descript *nd, __unused int isdgram,
4412     __unused vnode_t vp, __unused struct nfsexstuff *exp)
4413 {
4414 	uint32_t *tl;
4415 	int error = 0;
4416 	nfsquad_t clientid, confirm;
4417 	struct nfsdsession *sep = NULL;
4418 	uint32_t rdmacnt;
4419 	struct thread *p = curthread;
4420 
4421 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
4422 		goto nfsmout;
4423 	sep = (struct nfsdsession *)malloc(sizeof(struct nfsdsession),
4424 	    M_NFSDSESSION, M_WAITOK | M_ZERO);
4425 	sep->sess_refcnt = 1;
4426 	mtx_init(&sep->sess_cbsess.nfsess_mtx, "nfscbsession", NULL, MTX_DEF);
4427 	NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + 2 * NFSX_UNSIGNED);
4428 	clientid.lval[0] = *tl++;
4429 	clientid.lval[1] = *tl++;
4430 	confirm.lval[0] = fxdr_unsigned(uint32_t, *tl++);
4431 	sep->sess_crflags = fxdr_unsigned(uint32_t, *tl);
4432 	/* Persistent sessions and RDMA are not supported. */
4433 	sep->sess_crflags &= NFSV4CRSESS_CONNBACKCHAN;
4434 
4435 	/* Fore channel attributes. */
4436 	NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED);
4437 	tl++;					/* Header pad always 0. */
4438 	sep->sess_maxreq = fxdr_unsigned(uint32_t, *tl++);
4439 	if (sep->sess_maxreq > sb_max_adj - NFS_MAXXDR) {
4440 		sep->sess_maxreq = sb_max_adj - NFS_MAXXDR;
4441 		printf("Consider increasing kern.ipc.maxsockbuf\n");
4442 	}
4443 	sep->sess_maxresp = fxdr_unsigned(uint32_t, *tl++);
4444 	if (sep->sess_maxresp > sb_max_adj - NFS_MAXXDR) {
4445 		sep->sess_maxresp = sb_max_adj - NFS_MAXXDR;
4446 		printf("Consider increasing kern.ipc.maxsockbuf\n");
4447 	}
4448 	sep->sess_maxrespcached = fxdr_unsigned(uint32_t, *tl++);
4449 	sep->sess_maxops = fxdr_unsigned(uint32_t, *tl++);
4450 	sep->sess_maxslots = fxdr_unsigned(uint32_t, *tl++);
4451 	if (sep->sess_maxslots > NFSV4_SLOTS)
4452 		sep->sess_maxslots = NFSV4_SLOTS;
4453 	rdmacnt = fxdr_unsigned(uint32_t, *tl);
4454 	if (rdmacnt > 1) {
4455 		nd->nd_repstat = NFSERR_BADXDR;
4456 		goto nfsmout;
4457 	} else if (rdmacnt == 1)
4458 		NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
4459 
4460 	/* Back channel attributes. */
4461 	NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED);
4462 	tl++;					/* Header pad always 0. */
4463 	sep->sess_cbmaxreq = fxdr_unsigned(uint32_t, *tl++);
4464 	sep->sess_cbmaxresp = fxdr_unsigned(uint32_t, *tl++);
4465 	sep->sess_cbmaxrespcached = fxdr_unsigned(uint32_t, *tl++);
4466 	sep->sess_cbmaxops = fxdr_unsigned(uint32_t, *tl++);
4467 	sep->sess_cbsess.nfsess_foreslots = fxdr_unsigned(uint32_t, *tl++);
4468 	rdmacnt = fxdr_unsigned(uint32_t, *tl);
4469 	if (rdmacnt > 1) {
4470 		nd->nd_repstat = NFSERR_BADXDR;
4471 		goto nfsmout;
4472 	} else if (rdmacnt == 1)
4473 		NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
4474 
4475 	NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
4476 	sep->sess_cbprogram = fxdr_unsigned(uint32_t, *tl);
4477 
4478 	/*
4479 	 * nfsrv_getclient() searches the client list for a match and
4480 	 * returns the appropriate NFSERR status.
4481 	 */
4482 	nd->nd_repstat = nfsrv_getclient(clientid, CLOPS_CONFIRM | CLOPS_RENEW,
4483 	    NULL, sep, confirm, sep->sess_cbprogram, nd, p);
4484 	if (nd->nd_repstat == 0) {
4485 		NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID);
4486 		NFSBCOPY(sep->sess_sessionid, tl, NFSX_V4SESSIONID);
4487 		NFSM_BUILD(tl, uint32_t *, 18 * NFSX_UNSIGNED);
4488 		*tl++ = txdr_unsigned(confirm.lval[0]);	/* sequenceid */
4489 		*tl++ = txdr_unsigned(sep->sess_crflags);
4490 
4491 		/* Fore channel attributes. */
4492 		*tl++ = 0;
4493 		*tl++ = txdr_unsigned(sep->sess_maxreq);
4494 		*tl++ = txdr_unsigned(sep->sess_maxresp);
4495 		*tl++ = txdr_unsigned(sep->sess_maxrespcached);
4496 		*tl++ = txdr_unsigned(sep->sess_maxops);
4497 		*tl++ = txdr_unsigned(sep->sess_maxslots);
4498 		*tl++ = txdr_unsigned(1);
4499 		*tl++ = txdr_unsigned(0);			/* No RDMA. */
4500 
4501 		/* Back channel attributes. */
4502 		*tl++ = 0;
4503 		*tl++ = txdr_unsigned(sep->sess_cbmaxreq);
4504 		*tl++ = txdr_unsigned(sep->sess_cbmaxresp);
4505 		*tl++ = txdr_unsigned(sep->sess_cbmaxrespcached);
4506 		*tl++ = txdr_unsigned(sep->sess_cbmaxops);
4507 		*tl++ = txdr_unsigned(sep->sess_cbsess.nfsess_foreslots);
4508 		*tl++ = txdr_unsigned(1);
4509 		*tl = txdr_unsigned(0);			/* No RDMA. */
4510 	}
4511 nfsmout:
4512 	if (nd->nd_repstat != 0 && sep != NULL)
4513 		free(sep, M_NFSDSESSION);
4514 	NFSEXITCODE2(error, nd);
4515 	return (error);
4516 }
4517 
4518 /*
4519  * nfsv4 sequence service
4520  */
4521 int
4522 nfsrvd_sequence(struct nfsrv_descript *nd, __unused int isdgram,
4523     __unused vnode_t vp, __unused struct nfsexstuff *exp)
4524 {
4525 	uint32_t *tl;
4526 	uint32_t highest_slotid, sequenceid, sflags, target_highest_slotid;
4527 	int cache_this, error = 0;
4528 	struct thread *p = curthread;
4529 
4530 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
4531 		goto nfsmout;
4532 	NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID);
4533 	NFSBCOPY(tl, nd->nd_sessionid, NFSX_V4SESSIONID);
4534 	NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED);
4535 	sequenceid = fxdr_unsigned(uint32_t, *tl++);
4536 	nd->nd_slotid = fxdr_unsigned(uint32_t, *tl++);
4537 	highest_slotid = fxdr_unsigned(uint32_t, *tl++);
4538 	if (*tl == newnfs_true)
4539 		cache_this = 1;
4540 	else
4541 		cache_this = 0;
4542 	nd->nd_flag |= ND_HASSEQUENCE;
4543 	nd->nd_repstat = nfsrv_checksequence(nd, sequenceid, &highest_slotid,
4544 	    &target_highest_slotid, cache_this, &sflags, p);
4545 	if (nd->nd_repstat == 0) {
4546 		NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID);
4547 		NFSBCOPY(nd->nd_sessionid, tl, NFSX_V4SESSIONID);
4548 		NFSM_BUILD(tl, uint32_t *, 5 * NFSX_UNSIGNED);
4549 		*tl++ = txdr_unsigned(sequenceid);
4550 		*tl++ = txdr_unsigned(nd->nd_slotid);
4551 		*tl++ = txdr_unsigned(highest_slotid);
4552 		*tl++ = txdr_unsigned(target_highest_slotid);
4553 		*tl = txdr_unsigned(sflags);
4554 	}
4555 nfsmout:
4556 	NFSEXITCODE2(error, nd);
4557 	return (error);
4558 }
4559 
4560 /*
4561  * nfsv4 reclaim complete service
4562  */
4563 int
4564 nfsrvd_reclaimcomplete(struct nfsrv_descript *nd, __unused int isdgram,
4565     __unused vnode_t vp, __unused struct nfsexstuff *exp)
4566 {
4567 	uint32_t *tl;
4568 	int error = 0, onefs;
4569 
4570 	NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
4571 	/*
4572 	 * I believe that a ReclaimComplete with rca_one_fs == TRUE is only
4573 	 * to be used after a file system has been transferred to a different
4574 	 * file server.  However, RFC5661 is somewhat vague w.r.t. this and
4575 	 * the ESXi 6.7 client does both a ReclaimComplete with rca_one_fs
4576 	 * == TRUE and one with ReclaimComplete with rca_one_fs == FALSE.
4577 	 * Therefore, just ignore the rca_one_fs == TRUE operation and return
4578 	 * NFS_OK without doing anything.
4579 	 */
4580 	onefs = 0;
4581 	if (*tl == newnfs_true)
4582 		onefs = 1;
4583 	nd->nd_repstat = nfsrv_checkreclaimcomplete(nd, onefs);
4584 nfsmout:
4585 	NFSEXITCODE2(error, nd);
4586 	return (error);
4587 }
4588 
4589 /*
4590  * nfsv4 destroy clientid service
4591  */
4592 int
4593 nfsrvd_destroyclientid(struct nfsrv_descript *nd, __unused int isdgram,
4594     __unused vnode_t vp, __unused struct nfsexstuff *exp)
4595 {
4596 	uint32_t *tl;
4597 	nfsquad_t clientid;
4598 	int error = 0;
4599 	struct thread *p = curthread;
4600 
4601 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
4602 		goto nfsmout;
4603 	NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
4604 	clientid.lval[0] = *tl++;
4605 	clientid.lval[1] = *tl;
4606 	nd->nd_repstat = nfsrv_destroyclient(clientid, p);
4607 nfsmout:
4608 	NFSEXITCODE2(error, nd);
4609 	return (error);
4610 }
4611 
4612 /*
4613  * nfsv4 bind connection to session service
4614  */
4615 int
4616 nfsrvd_bindconnsess(struct nfsrv_descript *nd, __unused int isdgram,
4617     __unused vnode_t vp, __unused struct nfsexstuff *exp)
4618 {
4619 	uint32_t *tl;
4620 	uint8_t sessid[NFSX_V4SESSIONID];
4621 	int error = 0, foreaft;
4622 
4623 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
4624 		goto nfsmout;
4625 	NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID + 2 * NFSX_UNSIGNED);
4626 	NFSBCOPY(tl, sessid, NFSX_V4SESSIONID);
4627 	tl += (NFSX_V4SESSIONID / NFSX_UNSIGNED);
4628 	foreaft = fxdr_unsigned(int, *tl++);
4629 	if (*tl == newnfs_true) {
4630 		/* RDMA is not supported. */
4631 		nd->nd_repstat = NFSERR_NOTSUPP;
4632 		goto nfsmout;
4633 	}
4634 
4635 	nd->nd_repstat = nfsrv_bindconnsess(nd, sessid, &foreaft);
4636 	if (nd->nd_repstat == 0) {
4637 		NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 2 *
4638 		    NFSX_UNSIGNED);
4639 		NFSBCOPY(sessid, tl, NFSX_V4SESSIONID);
4640 		tl += (NFSX_V4SESSIONID / NFSX_UNSIGNED);
4641 		*tl++ = txdr_unsigned(foreaft);
4642 		*tl = newnfs_false;
4643 	}
4644 nfsmout:
4645 	NFSEXITCODE2(error, nd);
4646 	return (error);
4647 }
4648 
4649 /*
4650  * nfsv4 destroy session service
4651  */
4652 int
4653 nfsrvd_destroysession(struct nfsrv_descript *nd, __unused int isdgram,
4654     __unused vnode_t vp, __unused struct nfsexstuff *exp)
4655 {
4656 	uint8_t *cp, sessid[NFSX_V4SESSIONID];
4657 	int error = 0;
4658 
4659 	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
4660 		goto nfsmout;
4661 	NFSM_DISSECT(cp, uint8_t *, NFSX_V4SESSIONID);
4662 	NFSBCOPY(cp, sessid, NFSX_V4SESSIONID);
4663 	nd->nd_repstat = nfsrv_destroysession(nd, sessid);
4664 nfsmout:
4665 	NFSEXITCODE2(error, nd);
4666 	return (error);
4667 }
4668 
4669 /*
4670  * nfsv4 free stateid service
4671  */
4672 int
4673 nfsrvd_freestateid(struct nfsrv_descript *nd, __unused int isdgram,
4674     __unused vnode_t vp, __unused struct nfsexstuff *exp)
4675 {
4676 	uint32_t *tl;
4677 	nfsv4stateid_t stateid;
4678 	int error = 0;
4679 	struct thread *p = curthread;
4680 
4681 	NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID);
4682 	stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
4683 	NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
4684 
4685 	/*
4686 	 * For the special stateid of other all 0s and seqid == 1, set the
4687 	 * stateid to the current stateid, if it is set.
4688 	 */
4689 	if (stateid.seqid == 1 && stateid.other[0] == 0 &&
4690 	    stateid.other[1] == 0 && stateid.other[2] == 0) {
4691 		if ((nd->nd_flag & ND_CURSTATEID) != 0) {
4692 			stateid = nd->nd_curstateid;
4693 			stateid.seqid = 0;
4694 		} else {
4695 			nd->nd_repstat = NFSERR_BADSTATEID;
4696 			goto nfsmout;
4697 		}
4698 	}
4699 
4700 	nd->nd_repstat = nfsrv_freestateid(nd, &stateid, p);
4701 
4702 	/* If the current stateid has been free'd, unset it. */
4703 	if (nd->nd_repstat == 0 && (nd->nd_flag & ND_CURSTATEID) != 0 &&
4704 	    stateid.other[0] == nd->nd_curstateid.other[0] &&
4705 	    stateid.other[1] == nd->nd_curstateid.other[1] &&
4706 	    stateid.other[2] == nd->nd_curstateid.other[2])
4707 		nd->nd_flag &= ~ND_CURSTATEID;
4708 nfsmout:
4709 	NFSEXITCODE2(error, nd);
4710 	return (error);
4711 }
4712 
4713 /*
4714  * nfsv4 layoutget service
4715  */
4716 int
4717 nfsrvd_layoutget(struct nfsrv_descript *nd, __unused int isdgram,
4718     vnode_t vp, struct nfsexstuff *exp)
4719 {
4720 	uint32_t *tl;
4721 	nfsv4stateid_t stateid;
4722 	int error = 0, layoutlen, layouttype, iomode, maxcnt, retonclose;
4723 	uint64_t offset, len, minlen;
4724 	char *layp;
4725 	struct thread *p = curthread;
4726 
4727 	NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED + 3 * NFSX_HYPER +
4728 	    NFSX_STATEID);
4729 	tl++;		/* Signal layout available. Ignore for now. */
4730 	layouttype = fxdr_unsigned(int, *tl++);
4731 	iomode = fxdr_unsigned(int, *tl++);
4732 	offset = fxdr_hyper(tl); tl += 2;
4733 	len = fxdr_hyper(tl); tl += 2;
4734 	minlen = fxdr_hyper(tl); tl += 2;
4735 	stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
4736 	NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
4737 	tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
4738 	maxcnt = fxdr_unsigned(int, *tl);
4739 	NFSD_DEBUG(4, "layoutget ltyp=%d iom=%d off=%ju len=%ju mlen=%ju\n",
4740 	    layouttype, iomode, (uintmax_t)offset, (uintmax_t)len,
4741 	    (uintmax_t)minlen);
4742 	if (len < minlen ||
4743 	    (minlen != UINT64_MAX && offset + minlen < offset) ||
4744 	    (len != UINT64_MAX && offset + len < offset)) {
4745 		nd->nd_repstat = NFSERR_INVAL;
4746 		goto nfsmout;
4747 	}
4748 
4749 	/*
4750 	 * For the special stateid of other all 0s and seqid == 1, set the
4751 	 * stateid to the current stateid, if it is set.
4752 	 */
4753 	if (stateid.seqid == 1 && stateid.other[0] == 0 &&
4754 	    stateid.other[1] == 0 && stateid.other[2] == 0) {
4755 		if ((nd->nd_flag & ND_CURSTATEID) != 0) {
4756 			stateid = nd->nd_curstateid;
4757 			stateid.seqid = 0;
4758 		} else {
4759 			nd->nd_repstat = NFSERR_BADSTATEID;
4760 			goto nfsmout;
4761 		}
4762 	}
4763 
4764 	layp = NULL;
4765 	if (layouttype == NFSLAYOUT_NFSV4_1_FILES && nfsrv_maxpnfsmirror == 1)
4766 		layp = malloc(NFSX_V4FILELAYOUT, M_TEMP, M_WAITOK);
4767 	else if (layouttype == NFSLAYOUT_FLEXFILE)
4768 		layp = malloc(NFSX_V4FLEXLAYOUT(nfsrv_maxpnfsmirror), M_TEMP,
4769 		    M_WAITOK);
4770 	else
4771 		nd->nd_repstat = NFSERR_UNKNLAYOUTTYPE;
4772 	if (layp != NULL)
4773 		nd->nd_repstat = nfsrv_layoutget(nd, vp, exp, layouttype,
4774 		    &iomode, &offset, &len, minlen, &stateid, maxcnt,
4775 		    &retonclose, &layoutlen, layp, nd->nd_cred, p);
4776 	NFSD_DEBUG(4, "nfsrv_layoutget stat=%u layoutlen=%d\n", nd->nd_repstat,
4777 	    layoutlen);
4778 	if (nd->nd_repstat == 0) {
4779 		/* For NFSv4.1, set the Current StateID. */
4780 		if ((nd->nd_flag & ND_NFSV41) != 0) {
4781 			nd->nd_curstateid = stateid;
4782 			nd->nd_flag |= ND_CURSTATEID;
4783 		}
4784 		NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED + NFSX_STATEID +
4785 		    2 * NFSX_HYPER);
4786 		*tl++ = txdr_unsigned(retonclose);
4787 		*tl++ = txdr_unsigned(stateid.seqid);
4788 		NFSBCOPY(stateid.other, tl, NFSX_STATEIDOTHER);
4789 		tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
4790 		*tl++ = txdr_unsigned(1);	/* Only returns one layout. */
4791 		txdr_hyper(offset, tl); tl += 2;
4792 		txdr_hyper(len, tl); tl += 2;
4793 		*tl++ = txdr_unsigned(iomode);
4794 		*tl = txdr_unsigned(layouttype);
4795 		nfsm_strtom(nd, layp, layoutlen);
4796 	} else if (nd->nd_repstat == NFSERR_LAYOUTTRYLATER) {
4797 		NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
4798 		*tl = newnfs_false;
4799 	}
4800 	free(layp, M_TEMP);
4801 nfsmout:
4802 	vput(vp);
4803 	NFSEXITCODE2(error, nd);
4804 	return (error);
4805 }
4806 
4807 /*
4808  * nfsv4 layoutcommit service
4809  */
4810 int
4811 nfsrvd_layoutcommit(struct nfsrv_descript *nd, __unused int isdgram,
4812     vnode_t vp, struct nfsexstuff *exp)
4813 {
4814 	uint32_t *tl;
4815 	nfsv4stateid_t stateid;
4816 	int error = 0, hasnewoff, hasnewmtime, layouttype, maxcnt, reclaim;
4817 	int hasnewsize;
4818 	uint64_t offset, len, newoff = 0, newsize;
4819 	struct timespec newmtime;
4820 	char *layp;
4821 	struct thread *p = curthread;
4822 
4823 	layp = NULL;
4824 	NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED + 2 * NFSX_HYPER +
4825 	    NFSX_STATEID);
4826 	offset = fxdr_hyper(tl); tl += 2;
4827 	len = fxdr_hyper(tl); tl += 2;
4828 	reclaim = fxdr_unsigned(int, *tl++);
4829 	stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
4830 	NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
4831 	tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
4832 	/*
4833 	 * For the special stateid of other all 0s and seqid == 1, set the
4834 	 * stateid to the current stateid, if it is set.
4835 	 */
4836 	if (stateid.seqid == 1 && stateid.other[0] == 0 &&
4837 	    stateid.other[1] == 0 && stateid.other[2] == 0) {
4838 		if ((nd->nd_flag & ND_CURSTATEID) != 0) {
4839 			stateid = nd->nd_curstateid;
4840 			stateid.seqid = 0;
4841 		} else {
4842 			nd->nd_repstat = NFSERR_BADSTATEID;
4843 			goto nfsmout;
4844 		}
4845 	}
4846 
4847 	hasnewoff = fxdr_unsigned(int, *tl);
4848 	if (hasnewoff != 0) {
4849 		NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + NFSX_UNSIGNED);
4850 		newoff = fxdr_hyper(tl); tl += 2;
4851 	} else
4852 		NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
4853 	hasnewmtime = fxdr_unsigned(int, *tl);
4854 	if (hasnewmtime != 0) {
4855 		NFSM_DISSECT(tl, uint32_t *, NFSX_V4TIME + 2 * NFSX_UNSIGNED);
4856 		fxdr_nfsv4time(tl, &newmtime);
4857 		tl += (NFSX_V4TIME / NFSX_UNSIGNED);
4858 	} else
4859 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
4860 	layouttype = fxdr_unsigned(int, *tl++);
4861 	maxcnt = fxdr_unsigned(int, *tl);
4862 	if (maxcnt > 0) {
4863 		layp = malloc(maxcnt + 1, M_TEMP, M_WAITOK);
4864 		error = nfsrv_mtostr(nd, layp, maxcnt);
4865 		if (error != 0)
4866 			goto nfsmout;
4867 	}
4868 	nd->nd_repstat = nfsrv_layoutcommit(nd, vp, layouttype, hasnewoff,
4869 	    newoff, offset, len, hasnewmtime, &newmtime, reclaim, &stateid,
4870 	    maxcnt, layp, &hasnewsize, &newsize, nd->nd_cred, p);
4871 	NFSD_DEBUG(4, "nfsrv_layoutcommit stat=%u\n", nd->nd_repstat);
4872 	if (nd->nd_repstat == 0) {
4873 		if (hasnewsize != 0) {
4874 			NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED + NFSX_HYPER);
4875 			*tl++ = newnfs_true;
4876 			txdr_hyper(newsize, tl);
4877 		} else {
4878 			NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
4879 			*tl = newnfs_false;
4880 		}
4881 	}
4882 nfsmout:
4883 	free(layp, M_TEMP);
4884 	vput(vp);
4885 	NFSEXITCODE2(error, nd);
4886 	return (error);
4887 }
4888 
4889 /*
4890  * nfsv4 layoutreturn service
4891  */
4892 int
4893 nfsrvd_layoutreturn(struct nfsrv_descript *nd, __unused int isdgram,
4894     vnode_t vp, struct nfsexstuff *exp)
4895 {
4896 	uint32_t *tl, *layp;
4897 	nfsv4stateid_t stateid;
4898 	int error = 0, fnd, kind, layouttype, iomode, maxcnt, reclaim;
4899 	uint64_t offset, len;
4900 	struct thread *p = curthread;
4901 
4902 	layp = NULL;
4903 	NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED);
4904 	reclaim = *tl++;
4905 	layouttype = fxdr_unsigned(int, *tl++);
4906 	iomode = fxdr_unsigned(int, *tl++);
4907 	kind = fxdr_unsigned(int, *tl);
4908 	NFSD_DEBUG(4, "layoutreturn recl=%d ltyp=%d iom=%d kind=%d\n", reclaim,
4909 	    layouttype, iomode, kind);
4910 	if (kind == NFSV4LAYOUTRET_FILE) {
4911 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_STATEID +
4912 		    NFSX_UNSIGNED);
4913 		offset = fxdr_hyper(tl); tl += 2;
4914 		len = fxdr_hyper(tl); tl += 2;
4915 		stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
4916 		NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
4917 		tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
4918 
4919 		/*
4920 		 * For the special stateid of other all 0s and seqid == 1, set
4921 		 * the stateid to the current stateid, if it is set.
4922 		 */
4923 		if (stateid.seqid == 1 && stateid.other[0] == 0 &&
4924 		    stateid.other[1] == 0 && stateid.other[2] == 0) {
4925 			if ((nd->nd_flag & ND_CURSTATEID) != 0) {
4926 				stateid = nd->nd_curstateid;
4927 				stateid.seqid = 0;
4928 			} else {
4929 				nd->nd_repstat = NFSERR_BADSTATEID;
4930 				goto nfsmout;
4931 			}
4932 		}
4933 
4934 		maxcnt = fxdr_unsigned(int, *tl);
4935 		if (maxcnt > 0) {
4936 			layp = malloc(maxcnt + 1, M_TEMP, M_WAITOK);
4937 			error = nfsrv_mtostr(nd, (char *)layp, maxcnt);
4938 			if (error != 0)
4939 				goto nfsmout;
4940 		}
4941 	} else {
4942 		if (reclaim == newnfs_true) {
4943 			nd->nd_repstat = NFSERR_INVAL;
4944 			goto nfsmout;
4945 		}
4946 		offset = len = 0;
4947 		maxcnt = 0;
4948 	}
4949 	nd->nd_repstat = nfsrv_layoutreturn(nd, vp, layouttype, iomode,
4950 	    offset, len, reclaim, kind, &stateid, maxcnt, layp, &fnd,
4951 	    nd->nd_cred, p);
4952 	NFSD_DEBUG(4, "nfsrv_layoutreturn stat=%u fnd=%d\n", nd->nd_repstat,
4953 	    fnd);
4954 	if (nd->nd_repstat == 0) {
4955 		NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
4956 		if (fnd != 0) {
4957 			*tl = newnfs_true;
4958 			NFSM_BUILD(tl, uint32_t *, NFSX_STATEID);
4959 			*tl++ = txdr_unsigned(stateid.seqid);
4960 			NFSBCOPY(stateid.other, tl, NFSX_STATEIDOTHER);
4961 		} else
4962 			*tl = newnfs_false;
4963 	}
4964 nfsmout:
4965 	free(layp, M_TEMP);
4966 	vput(vp);
4967 	NFSEXITCODE2(error, nd);
4968 	return (error);
4969 }
4970 
4971 /*
4972  * nfsv4 layout error service
4973  */
4974 int
4975 nfsrvd_layouterror(struct nfsrv_descript *nd, __unused int isdgram,
4976     vnode_t vp, struct nfsexstuff *exp)
4977 {
4978 	uint32_t *tl;
4979 	nfsv4stateid_t stateid;
4980 	int cnt, error = 0, i, stat;
4981 	int opnum __unused;
4982 	char devid[NFSX_V4DEVICEID];
4983 	uint64_t offset, len;
4984 
4985 	NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_STATEID +
4986 	    NFSX_UNSIGNED);
4987 	offset = fxdr_hyper(tl); tl += 2;
4988 	len = fxdr_hyper(tl); tl += 2;
4989 	stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
4990 	NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
4991 	tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
4992 	cnt = fxdr_unsigned(int, *tl);
4993 	NFSD_DEBUG(4, "layouterror off=%ju len=%ju cnt=%d\n", (uintmax_t)offset,
4994 	    (uintmax_t)len, cnt);
4995 	/*
4996 	 * For the special stateid of other all 0s and seqid == 1, set
4997 	 * the stateid to the current stateid, if it is set.
4998 	 */
4999 	if (stateid.seqid == 1 && stateid.other[0] == 0 &&
5000 	    stateid.other[1] == 0 && stateid.other[2] == 0) {
5001 		if ((nd->nd_flag & ND_CURSTATEID) != 0) {
5002 			stateid = nd->nd_curstateid;
5003 			stateid.seqid = 0;
5004 		} else {
5005 			nd->nd_repstat = NFSERR_BADSTATEID;
5006 			goto nfsmout;
5007 		}
5008 	}
5009 
5010 	/*
5011 	 * Ignore offset, len and stateid for now.
5012 	 */
5013 	for (i = 0; i < cnt; i++) {
5014 		NFSM_DISSECT(tl, uint32_t *, NFSX_V4DEVICEID + 2 *
5015 		    NFSX_UNSIGNED);
5016 		NFSBCOPY(tl, devid, NFSX_V4DEVICEID);
5017 		tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
5018 		stat = fxdr_unsigned(int, *tl++);
5019 		opnum = fxdr_unsigned(int, *tl);
5020 		NFSD_DEBUG(4, "nfsrvd_layouterr op=%d stat=%d\n", opnum, stat);
5021 		/*
5022 		 * Except for NFSERR_ACCES and NFSERR_STALE errors,
5023 		 * disable the mirror.
5024 		 */
5025 		if (stat != NFSERR_ACCES && stat != NFSERR_STALE)
5026 			nfsrv_delds(devid, curthread);
5027 	}
5028 nfsmout:
5029 	vput(vp);
5030 	NFSEXITCODE2(error, nd);
5031 	return (error);
5032 }
5033 
5034 /*
5035  * nfsv4 layout stats service
5036  */
5037 int
5038 nfsrvd_layoutstats(struct nfsrv_descript *nd, __unused int isdgram,
5039     vnode_t vp, struct nfsexstuff *exp)
5040 {
5041 	uint32_t *tl;
5042 	nfsv4stateid_t stateid;
5043 	int cnt, error = 0;
5044 	int layouttype __unused;
5045 	char devid[NFSX_V4DEVICEID] __unused;
5046 	uint64_t offset, len, readcount, readbytes, writecount, writebytes
5047 	    __unused;
5048 
5049 	NFSM_DISSECT(tl, uint32_t *, 6 * NFSX_HYPER + NFSX_STATEID +
5050 	    NFSX_V4DEVICEID + 2 * NFSX_UNSIGNED);
5051 	offset = fxdr_hyper(tl); tl += 2;
5052 	len = fxdr_hyper(tl); tl += 2;
5053 	stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
5054 	NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
5055 	tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
5056 	readcount = fxdr_hyper(tl); tl += 2;
5057 	readbytes = fxdr_hyper(tl); tl += 2;
5058 	writecount = fxdr_hyper(tl); tl += 2;
5059 	writebytes = fxdr_hyper(tl); tl += 2;
5060 	NFSBCOPY(tl, devid, NFSX_V4DEVICEID);
5061 	tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
5062 	layouttype = fxdr_unsigned(int, *tl++);
5063 	cnt = fxdr_unsigned(int, *tl);
5064 	error = nfsm_advance(nd, NFSM_RNDUP(cnt), -1);
5065 	if (error != 0)
5066 		goto nfsmout;
5067 	NFSD_DEBUG(4, "layoutstats cnt=%d\n", cnt);
5068 	/*
5069 	 * For the special stateid of other all 0s and seqid == 1, set
5070 	 * the stateid to the current stateid, if it is set.
5071 	 */
5072 	if (stateid.seqid == 1 && stateid.other[0] == 0 &&
5073 	    stateid.other[1] == 0 && stateid.other[2] == 0) {
5074 		if ((nd->nd_flag & ND_CURSTATEID) != 0) {
5075 			stateid = nd->nd_curstateid;
5076 			stateid.seqid = 0;
5077 		} else {
5078 			nd->nd_repstat = NFSERR_BADSTATEID;
5079 			goto nfsmout;
5080 		}
5081 	}
5082 
5083 	/*
5084 	 * No use for the stats for now.
5085 	 */
5086 nfsmout:
5087 	vput(vp);
5088 	NFSEXITCODE2(error, nd);
5089 	return (error);
5090 }
5091 
5092 /*
5093  * nfsv4 io_advise service
5094  */
5095 int
5096 nfsrvd_ioadvise(struct nfsrv_descript *nd, __unused int isdgram,
5097     vnode_t vp, struct nfsexstuff *exp)
5098 {
5099 	uint32_t *tl;
5100 	nfsv4stateid_t stateid;
5101 	nfsattrbit_t hints;
5102 	int error = 0, ret;
5103 	off_t offset, len;
5104 
5105 	NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID + 2 * NFSX_HYPER);
5106 	stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
5107 	NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
5108 	tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
5109 	offset = fxdr_hyper(tl); tl += 2;
5110 	len = fxdr_hyper(tl);
5111 	error = nfsrv_getattrbits(nd, &hints, NULL, NULL);
5112 	if (error != 0)
5113 		goto nfsmout;
5114 	/*
5115 	 * For the special stateid of other all 0s and seqid == 1, set
5116 	 * the stateid to the current stateid, if it is set.
5117 	 */
5118 	if (stateid.seqid == 1 && stateid.other[0] == 0 &&
5119 	    stateid.other[1] == 0 && stateid.other[2] == 0) {
5120 		if ((nd->nd_flag & ND_CURSTATEID) != 0) {
5121 			stateid = nd->nd_curstateid;
5122 			stateid.seqid = 0;
5123 		} else {
5124 			nd->nd_repstat = NFSERR_BADSTATEID;
5125 			goto nfsmout;
5126 		}
5127 	}
5128 
5129 	if (offset < 0) {
5130 		nd->nd_repstat = NFSERR_INVAL;
5131 		goto nfsmout;
5132 	}
5133 	if (len < 0)
5134 		len = 0;
5135 	if (vp->v_type != VREG) {
5136 		if (vp->v_type == VDIR)
5137 			nd->nd_repstat = NFSERR_ISDIR;
5138 		else
5139 			nd->nd_repstat = NFSERR_WRONGTYPE;
5140 		goto nfsmout;
5141 	}
5142 
5143 	/*
5144 	 * For now, we can only handle WILLNEED and DONTNEED and don't use
5145 	 * the stateid.
5146 	 */
5147 	if ((NFSISSET_ATTRBIT(&hints, NFSV4IOHINT_WILLNEED) &&
5148 	    !NFSISSET_ATTRBIT(&hints, NFSV4IOHINT_DONTNEED)) ||
5149 	    (NFSISSET_ATTRBIT(&hints, NFSV4IOHINT_DONTNEED) &&
5150 	    !NFSISSET_ATTRBIT(&hints, NFSV4IOHINT_WILLNEED))) {
5151 		NFSVOPUNLOCK(vp);
5152 		if (NFSISSET_ATTRBIT(&hints, NFSV4IOHINT_WILLNEED)) {
5153 			ret = VOP_ADVISE(vp, offset, len, POSIX_FADV_WILLNEED);
5154 			NFSZERO_ATTRBIT(&hints);
5155 			if (ret == 0)
5156 				NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_WILLNEED);
5157 			else
5158 				NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_NORMAL);
5159 		} else {
5160 			ret = VOP_ADVISE(vp, offset, len, POSIX_FADV_DONTNEED);
5161 			NFSZERO_ATTRBIT(&hints);
5162 			if (ret == 0)
5163 				NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_DONTNEED);
5164 			else
5165 				NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_NORMAL);
5166 		}
5167 		vrele(vp);
5168 	} else {
5169 		NFSZERO_ATTRBIT(&hints);
5170 		NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_NORMAL);
5171 		vput(vp);
5172 	}
5173 	nfsrv_putattrbit(nd, &hints);
5174 	NFSEXITCODE2(error, nd);
5175 	return (error);
5176 nfsmout:
5177 	vput(vp);
5178 	NFSEXITCODE2(error, nd);
5179 	return (error);
5180 }
5181 
5182 /*
5183  * nfsv4 getdeviceinfo service
5184  */
5185 int
5186 nfsrvd_getdevinfo(struct nfsrv_descript *nd, __unused int isdgram,
5187     __unused vnode_t vp, __unused struct nfsexstuff *exp)
5188 {
5189 	uint32_t *tl, maxcnt, notify[NFSV4_NOTIFYBITMAP];
5190 	int cnt, devaddrlen, error = 0, i, layouttype;
5191 	char devid[NFSX_V4DEVICEID], *devaddr;
5192 	time_t dev_time;
5193 
5194 	NFSM_DISSECT(tl, uint32_t *, 3 * NFSX_UNSIGNED + NFSX_V4DEVICEID);
5195 	NFSBCOPY(tl, devid, NFSX_V4DEVICEID);
5196 	tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
5197 	layouttype = fxdr_unsigned(int, *tl++);
5198 	maxcnt = fxdr_unsigned(uint32_t, *tl++);
5199 	cnt = fxdr_unsigned(int, *tl);
5200 	NFSD_DEBUG(4, "getdevinfo ltyp=%d maxcnt=%u bitcnt=%d\n", layouttype,
5201 	    maxcnt, cnt);
5202 	if (cnt > NFSV4_NOTIFYBITMAP || cnt < 0) {
5203 		nd->nd_repstat = NFSERR_INVAL;
5204 		goto nfsmout;
5205 	}
5206 	if (cnt > 0) {
5207 		NFSM_DISSECT(tl, uint32_t *, cnt * NFSX_UNSIGNED);
5208 		for (i = 0; i < cnt; i++)
5209 			notify[i] = fxdr_unsigned(uint32_t, *tl++);
5210 	}
5211 	for (i = cnt; i < NFSV4_NOTIFYBITMAP; i++)
5212 		notify[i] = 0;
5213 
5214 	/*
5215 	 * Check that the device id is not stale.  Device ids are recreated
5216 	 * each time the nfsd threads are restarted.
5217 	 */
5218 	NFSBCOPY(devid, &dev_time, sizeof(dev_time));
5219 	if (dev_time != nfsdev_time) {
5220 		nd->nd_repstat = NFSERR_NOENT;
5221 		goto nfsmout;
5222 	}
5223 
5224 	/* Look for the device id. */
5225 	nd->nd_repstat = nfsrv_getdevinfo(devid, layouttype, &maxcnt,
5226 	    notify, &devaddrlen, &devaddr);
5227 	NFSD_DEBUG(4, "nfsrv_getdevinfo stat=%u\n", nd->nd_repstat);
5228 	if (nd->nd_repstat == 0) {
5229 		NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
5230 		*tl = txdr_unsigned(layouttype);
5231 		nfsm_strtom(nd, devaddr, devaddrlen);
5232 		cnt = 0;
5233 		for (i = 0; i < NFSV4_NOTIFYBITMAP; i++) {
5234 			if (notify[i] != 0)
5235 				cnt = i + 1;
5236 		}
5237 		NFSM_BUILD(tl, uint32_t *, (cnt + 1) * NFSX_UNSIGNED);
5238 		*tl++ = txdr_unsigned(cnt);
5239 		for (i = 0; i < cnt; i++)
5240 			*tl++ = txdr_unsigned(notify[i]);
5241 	} else if (nd->nd_repstat == NFSERR_TOOSMALL) {
5242 		NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
5243 		*tl = txdr_unsigned(maxcnt);
5244 	}
5245 nfsmout:
5246 	NFSEXITCODE2(error, nd);
5247 	return (error);
5248 }
5249 
5250 /*
5251  * nfsv4 test stateid service
5252  */
5253 int
5254 nfsrvd_teststateid(struct nfsrv_descript *nd, __unused int isdgram,
5255     __unused vnode_t vp, __unused struct nfsexstuff *exp)
5256 {
5257 	uint32_t *tl;
5258 	nfsv4stateid_t *stateidp = NULL, *tstateidp;
5259 	int cnt, error = 0, i, ret;
5260 	struct thread *p = curthread;
5261 
5262 	NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
5263 	cnt = fxdr_unsigned(int, *tl);
5264 	if (cnt <= 0 || cnt > 1024) {
5265 		nd->nd_repstat = NFSERR_BADXDR;
5266 		goto nfsmout;
5267 	}
5268 	stateidp = mallocarray(cnt, sizeof(nfsv4stateid_t), M_TEMP, M_WAITOK);
5269 	tstateidp = stateidp;
5270 	for (i = 0; i < cnt; i++) {
5271 		NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID);
5272 		tstateidp->seqid = fxdr_unsigned(uint32_t, *tl++);
5273 		NFSBCOPY(tl, tstateidp->other, NFSX_STATEIDOTHER);
5274 		tstateidp++;
5275 	}
5276 	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
5277 	*tl = txdr_unsigned(cnt);
5278 	tstateidp = stateidp;
5279 	for (i = 0; i < cnt; i++) {
5280 		ret = nfsrv_teststateid(nd, tstateidp, p);
5281 		NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
5282 		*tl = txdr_unsigned(ret);
5283 		tstateidp++;
5284 	}
5285 nfsmout:
5286 	free(stateidp, M_TEMP);
5287 	NFSEXITCODE2(error, nd);
5288 	return (error);
5289 }
5290 
5291 /*
5292  * nfs allocate service
5293  */
5294 int
5295 nfsrvd_allocate(struct nfsrv_descript *nd, __unused int isdgram,
5296     vnode_t vp, struct nfsexstuff *exp)
5297 {
5298 	uint32_t *tl;
5299 	struct nfsvattr forat;
5300 	int error = 0, forat_ret = 1, gotproxystateid;
5301 	off_t off, len;
5302 	struct nfsstate st, *stp = &st;
5303 	struct nfslock lo, *lop = &lo;
5304 	nfsv4stateid_t stateid;
5305 	nfsquad_t clientid;
5306 	nfsattrbit_t attrbits;
5307 
5308 	gotproxystateid = 0;
5309 	NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID + 2 * NFSX_HYPER);
5310 	stp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS);
5311 	lop->lo_flags = NFSLCK_WRITE;
5312 	stp->ls_ownerlen = 0;
5313 	stp->ls_op = NULL;
5314 	stp->ls_uid = nd->nd_cred->cr_uid;
5315 	stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
5316 	clientid.lval[0] = stp->ls_stateid.other[0] = *tl++;
5317 	clientid.lval[1] = stp->ls_stateid.other[1] = *tl++;
5318 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
5319 		if ((nd->nd_flag & ND_NFSV41) != 0)
5320 			clientid.qval = nd->nd_clientid.qval;
5321 		else if (nd->nd_clientid.qval != clientid.qval)
5322 			printf("EEK2 multiple clids\n");
5323 	} else {
5324 		if ((nd->nd_flag & ND_NFSV41) != 0)
5325 			printf("EEK! no clientid from session\n");
5326 		nd->nd_flag |= ND_IMPLIEDCLID;
5327 		nd->nd_clientid.qval = clientid.qval;
5328 	}
5329 	stp->ls_stateid.other[2] = *tl++;
5330 	/*
5331 	 * Don't allow this to be done for a DS.
5332 	 */
5333 	if ((nd->nd_flag & ND_DSSERVER) != 0)
5334 		nd->nd_repstat = NFSERR_NOTSUPP;
5335 	/* However, allow the proxy stateid. */
5336 	if (stp->ls_stateid.seqid == 0xffffffff &&
5337 	    stp->ls_stateid.other[0] == 0x55555555 &&
5338 	    stp->ls_stateid.other[1] == 0x55555555 &&
5339 	    stp->ls_stateid.other[2] == 0x55555555)
5340 		gotproxystateid = 1;
5341 	off = fxdr_hyper(tl); tl += 2;
5342 	lop->lo_first = off;
5343 	len = fxdr_hyper(tl);
5344 	lop->lo_end = off + len;
5345 	/*
5346 	 * Paranoia, just in case it wraps around, which shouldn't
5347 	 * ever happen anyhow.
5348 	 */
5349 	if (nd->nd_repstat == 0 && (lop->lo_end < lop->lo_first || len <= 0))
5350 		nd->nd_repstat = NFSERR_INVAL;
5351 
5352 	if (nd->nd_repstat == 0 && vnode_vtype(vp) != VREG)
5353 		nd->nd_repstat = NFSERR_WRONGTYPE;
5354 	NFSZERO_ATTRBIT(&attrbits);
5355 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNER);
5356 	forat_ret = nfsvno_getattr(vp, &forat, nd, curthread, 1, &attrbits);
5357 	if (nd->nd_repstat == 0)
5358 		nd->nd_repstat = forat_ret;
5359 	if (nd->nd_repstat == 0 && (forat.na_uid != nd->nd_cred->cr_uid ||
5360 	     NFSVNO_EXSTRICTACCESS(exp)))
5361 		nd->nd_repstat = nfsvno_accchk(vp, VWRITE, nd->nd_cred, exp,
5362 		    curthread, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED,
5363 		    NULL);
5364 	if (nd->nd_repstat == 0 && gotproxystateid == 0)
5365 		nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid,
5366 		    &stateid, exp, nd, curthread);
5367 
5368 	if (nd->nd_repstat == 0)
5369 		nd->nd_repstat = nfsvno_allocate(vp, off, len, nd->nd_cred,
5370 		    curthread);
5371 	vput(vp);
5372 	NFSEXITCODE2(0, nd);
5373 	return (0);
5374 nfsmout:
5375 	vput(vp);
5376 	NFSEXITCODE2(error, nd);
5377 	return (error);
5378 }
5379 
5380 /*
5381  * nfs copy service
5382  */
5383 int
5384 nfsrvd_copy_file_range(struct nfsrv_descript *nd, __unused int isdgram,
5385     vnode_t vp, vnode_t tovp, struct nfsexstuff *exp, struct nfsexstuff *toexp)
5386 {
5387 	uint32_t *tl;
5388 	struct nfsvattr at;
5389 	int cnt, error = 0, ret;
5390 	off_t inoff, outoff;
5391 	uint64_t len;
5392 	size_t xfer;
5393 	struct nfsstate inst, outst, *instp = &inst, *outstp = &outst;
5394 	struct nfslock inlo, outlo, *inlop = &inlo, *outlop = &outlo;
5395 	nfsquad_t clientid;
5396 	nfsv4stateid_t stateid;
5397 	nfsattrbit_t attrbits;
5398 	void *rl_rcookie, *rl_wcookie;
5399 
5400 	rl_rcookie = rl_wcookie = NULL;
5401 	if (nfsrv_devidcnt > 0) {
5402 		/*
5403 		 * For a pNFS server, reply NFSERR_NOTSUPP so that the client
5404 		 * will do the copy via I/O on the DS(s).
5405 		 */
5406 		nd->nd_repstat = NFSERR_NOTSUPP;
5407 		goto nfsmout;
5408 	}
5409 	if (vp == tovp) {
5410 		/* Copying a byte range within the same file is not allowed. */
5411 		nd->nd_repstat = NFSERR_INVAL;
5412 		goto nfsmout;
5413 	}
5414 	NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_STATEID + 3 * NFSX_HYPER +
5415 	    3 * NFSX_UNSIGNED);
5416 	instp->ls_flags = (NFSLCK_CHECK | NFSLCK_READACCESS);
5417 	inlop->lo_flags = NFSLCK_READ;
5418 	instp->ls_ownerlen = 0;
5419 	instp->ls_op = NULL;
5420 	instp->ls_uid = nd->nd_cred->cr_uid;
5421 	instp->ls_stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
5422 	clientid.lval[0] = instp->ls_stateid.other[0] = *tl++;
5423 	clientid.lval[1] = instp->ls_stateid.other[1] = *tl++;
5424 	if ((nd->nd_flag & ND_IMPLIEDCLID) != 0)
5425 		clientid.qval = nd->nd_clientid.qval;
5426 	instp->ls_stateid.other[2] = *tl++;
5427 	outstp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS);
5428 	outlop->lo_flags = NFSLCK_WRITE;
5429 	outstp->ls_ownerlen = 0;
5430 	outstp->ls_op = NULL;
5431 	outstp->ls_uid = nd->nd_cred->cr_uid;
5432 	outstp->ls_stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
5433 	outstp->ls_stateid.other[0] = *tl++;
5434 	outstp->ls_stateid.other[1] = *tl++;
5435 	outstp->ls_stateid.other[2] = *tl++;
5436 	inoff = fxdr_hyper(tl); tl += 2;
5437 	inlop->lo_first = inoff;
5438 	outoff = fxdr_hyper(tl); tl += 2;
5439 	outlop->lo_first = outoff;
5440 	len = fxdr_hyper(tl); tl += 2;
5441 	if (len == 0) {
5442 		/* len == 0 means to EOF. */
5443 		inlop->lo_end = OFF_MAX;
5444 		outlop->lo_end = OFF_MAX;
5445 	} else {
5446 		inlop->lo_end = inlop->lo_first + len;
5447 		outlop->lo_end = outlop->lo_first + len;
5448 	}
5449 
5450 	/*
5451 	 * At this time only consecutive, synchronous copy is supported,
5452 	 * so ca_consecutive and ca_synchronous can be ignored.
5453 	 */
5454 	tl += 2;
5455 
5456 	cnt = fxdr_unsigned(int, *tl);
5457 	if ((nd->nd_flag & ND_DSSERVER) != 0 || cnt != 0)
5458 		nd->nd_repstat = NFSERR_NOTSUPP;
5459 	if (nd->nd_repstat == 0 && (inoff > OFF_MAX || outoff > OFF_MAX ||
5460 	    inlop->lo_end > OFF_MAX || outlop->lo_end > OFF_MAX ||
5461 	    inlop->lo_end < inlop->lo_first || outlop->lo_end <
5462 	    outlop->lo_first))
5463 		nd->nd_repstat = NFSERR_INVAL;
5464 
5465 	if (nd->nd_repstat == 0 && vnode_vtype(vp) != VREG)
5466 		nd->nd_repstat = NFSERR_WRONGTYPE;
5467 
5468 	/* Check permissions for the input file. */
5469 	NFSZERO_ATTRBIT(&attrbits);
5470 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNER);
5471 	ret = nfsvno_getattr(vp, &at, nd, curthread, 1, &attrbits);
5472 	if (nd->nd_repstat == 0)
5473 		nd->nd_repstat = ret;
5474 	if (nd->nd_repstat == 0 && (at.na_uid != nd->nd_cred->cr_uid ||
5475 	     NFSVNO_EXSTRICTACCESS(exp)))
5476 		nd->nd_repstat = nfsvno_accchk(vp, VREAD, nd->nd_cred, exp,
5477 		    curthread, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED,
5478 		    NULL);
5479 	if (nd->nd_repstat == 0)
5480 		nd->nd_repstat = nfsrv_lockctrl(vp, &instp, &inlop, NULL,
5481 		    clientid, &stateid, exp, nd, curthread);
5482 	NFSVOPUNLOCK(vp);
5483 	if (nd->nd_repstat != 0)
5484 		goto out;
5485 
5486 	error = NFSVOPLOCK(tovp, LK_SHARED);
5487 	if (error != 0)
5488 		goto out;
5489 	if (vnode_vtype(tovp) != VREG)
5490 		nd->nd_repstat = NFSERR_WRONGTYPE;
5491 
5492 	/* For the output file, we only need the Owner attribute. */
5493 	ret = nfsvno_getattr(tovp, &at, nd, curthread, 1, &attrbits);
5494 	if (nd->nd_repstat == 0)
5495 		nd->nd_repstat = ret;
5496 	if (nd->nd_repstat == 0 && (at.na_uid != nd->nd_cred->cr_uid ||
5497 	     NFSVNO_EXSTRICTACCESS(exp)))
5498 		nd->nd_repstat = nfsvno_accchk(tovp, VWRITE, nd->nd_cred, toexp,
5499 		    curthread, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED,
5500 		    NULL);
5501 	if (nd->nd_repstat == 0)
5502 		nd->nd_repstat = nfsrv_lockctrl(tovp, &outstp, &outlop, NULL,
5503 		    clientid, &stateid, toexp, nd, curthread);
5504 	NFSVOPUNLOCK(tovp);
5505 
5506 	/* Range lock the byte ranges for both invp and outvp. */
5507 	if (nd->nd_repstat == 0) {
5508 		for (;;) {
5509 			if (len == 0) {
5510 				rl_wcookie = vn_rangelock_wlock(tovp, outoff,
5511 				    OFF_MAX);
5512 				rl_rcookie = vn_rangelock_tryrlock(vp, inoff,
5513 				    OFF_MAX);
5514 			} else {
5515 				rl_wcookie = vn_rangelock_wlock(tovp, outoff,
5516 				    outoff + len);
5517 				rl_rcookie = vn_rangelock_tryrlock(vp, inoff,
5518 				    inoff + len);
5519 			}
5520 			if (rl_rcookie != NULL)
5521 				break;
5522 			vn_rangelock_unlock(tovp, rl_wcookie);
5523 			if (len == 0)
5524 				rl_rcookie = vn_rangelock_rlock(vp, inoff,
5525 				    OFF_MAX);
5526 			else
5527 				rl_rcookie = vn_rangelock_rlock(vp, inoff,
5528 				    inoff + len);
5529 			vn_rangelock_unlock(vp, rl_rcookie);
5530 		}
5531 
5532 		error = NFSVOPLOCK(vp, LK_SHARED);
5533 		if (error == 0) {
5534 			ret = nfsvno_getattr(vp, &at, nd, curthread, 1, NULL);
5535 			if (ret == 0) {
5536 				/*
5537 				 * Since invp is range locked, na_size should
5538 				 * not change.
5539 				 */
5540 				if (len == 0 && at.na_size > inoff) {
5541 					/*
5542 					 * If len == 0, set it based on invp's
5543 					 * size. If offset is past EOF, just
5544 					 * leave len == 0.
5545 					 */
5546 					len = at.na_size - inoff;
5547 				} else if (nfsrv_linux42server == 0 &&
5548 				    inoff + len > at.na_size) {
5549 					/*
5550 					 * RFC-7862 says that NFSERR_INVAL must
5551 					 * be returned when inoff + len exceeds
5552 					 * the file size, however the NFSv4.2
5553 					 * Linux client likes to do this, so
5554 					 * only check if nfsrv_linux42server
5555 					 * is not set.
5556 					 */
5557 					nd->nd_repstat = NFSERR_INVAL;
5558 				}
5559 			}
5560 			NFSVOPUNLOCK(vp);
5561 			if (ret != 0 && nd->nd_repstat == 0)
5562 				nd->nd_repstat = ret;
5563 		} else if (nd->nd_repstat == 0)
5564 			nd->nd_repstat = error;
5565 	}
5566 
5567 	/*
5568 	 * Do the actual copy to an upper limit of vfs.nfs.maxcopyrange.
5569 	 * This limit is applied to ensure that the RPC replies in a
5570 	 * reasonable time.
5571 	 */
5572 	if (len > nfs_maxcopyrange)
5573 		xfer = nfs_maxcopyrange;
5574 	else
5575 		xfer = len;
5576 	if (nd->nd_repstat == 0) {
5577 		nd->nd_repstat = vn_copy_file_range(vp, &inoff, tovp, &outoff,
5578 		    &xfer, 0, nd->nd_cred, nd->nd_cred, NULL);
5579 		if (nd->nd_repstat == 0)
5580 			len = xfer;
5581 	}
5582 
5583 	/* Unlock the ranges. */
5584 	if (rl_rcookie != NULL)
5585 		vn_rangelock_unlock(vp, rl_rcookie);
5586 	if (rl_wcookie != NULL)
5587 		vn_rangelock_unlock(tovp, rl_wcookie);
5588 
5589 	if (nd->nd_repstat == 0) {
5590 		NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED + NFSX_HYPER +
5591 		    NFSX_VERF);
5592 		*tl++ = txdr_unsigned(0);	/* No callback ids. */
5593 		txdr_hyper(len, tl); tl += 2;
5594 		*tl++ = txdr_unsigned(NFSWRITE_UNSTABLE);
5595 		*tl++ = txdr_unsigned(nfsboottime.tv_sec);
5596 		*tl++ = txdr_unsigned(nfsboottime.tv_usec);
5597 		*tl++ = newnfs_true;
5598 		*tl = newnfs_true;
5599 	}
5600 out:
5601 	vrele(vp);
5602 	vrele(tovp);
5603 	NFSEXITCODE2(error, nd);
5604 	return (error);
5605 nfsmout:
5606 	vput(vp);
5607 	vrele(tovp);
5608 	NFSEXITCODE2(error, nd);
5609 	return (error);
5610 }
5611 
5612 /*
5613  * nfs seek service
5614  */
5615 int
5616 nfsrvd_seek(struct nfsrv_descript *nd, __unused int isdgram,
5617     vnode_t vp, struct nfsexstuff *exp)
5618 {
5619 	uint32_t *tl;
5620 	struct nfsvattr at;
5621 	int content, error = 0;
5622 	off_t off;
5623 	u_long cmd;
5624 	nfsattrbit_t attrbits;
5625 	bool eof;
5626 
5627 	NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID + NFSX_HYPER + NFSX_UNSIGNED);
5628 	/* Ignore the stateid for now. */
5629 	tl += (NFSX_STATEID / NFSX_UNSIGNED);
5630 	off = fxdr_hyper(tl); tl += 2;
5631 	content = fxdr_unsigned(int, *tl);
5632 	if (content == NFSV4CONTENT_DATA)
5633 		cmd = FIOSEEKDATA;
5634 	else if (content == NFSV4CONTENT_HOLE)
5635 		cmd = FIOSEEKHOLE;
5636 	else
5637 		nd->nd_repstat = NFSERR_BADXDR;
5638 	if (nd->nd_repstat == 0 && vnode_vtype(vp) == VDIR)
5639 		nd->nd_repstat = NFSERR_ISDIR;
5640 	if (nd->nd_repstat == 0 && vnode_vtype(vp) != VREG)
5641 		nd->nd_repstat = NFSERR_WRONGTYPE;
5642 	if (nd->nd_repstat == 0 && off < 0)
5643 		nd->nd_repstat = NFSERR_NXIO;
5644 	if (nd->nd_repstat == 0) {
5645 		/* Check permissions for the input file. */
5646 		NFSZERO_ATTRBIT(&attrbits);
5647 		NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNER);
5648 		nd->nd_repstat = nfsvno_getattr(vp, &at, nd, curthread, 1,
5649 		    &attrbits);
5650 	}
5651 	if (nd->nd_repstat == 0 && (at.na_uid != nd->nd_cred->cr_uid ||
5652 	     NFSVNO_EXSTRICTACCESS(exp)))
5653 		nd->nd_repstat = nfsvno_accchk(vp, VREAD, nd->nd_cred, exp,
5654 		    curthread, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED,
5655 		    NULL);
5656 	if (nd->nd_repstat != 0)
5657 		goto nfsmout;
5658 
5659 	/* nfsvno_seek() unlocks and vrele()s the vp. */
5660 	nd->nd_repstat = nfsvno_seek(nd, vp, cmd, &off, content, &eof,
5661 	    nd->nd_cred, curthread);
5662 	if (nd->nd_repstat == 0 && eof && content == NFSV4CONTENT_DATA &&
5663 	    nfsrv_linux42server != 0)
5664 		nd->nd_repstat = NFSERR_NXIO;
5665 	if (nd->nd_repstat == 0) {
5666 		NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED + NFSX_HYPER);
5667 		if (eof)
5668 			*tl++ = newnfs_true;
5669 		else
5670 			*tl++ = newnfs_false;
5671 		txdr_hyper(off, tl);
5672 	}
5673 	NFSEXITCODE2(error, nd);
5674 	return (error);
5675 nfsmout:
5676 	vput(vp);
5677 	NFSEXITCODE2(error, nd);
5678 	return (error);
5679 }
5680 
5681 /*
5682  * nfs get extended attribute service
5683  */
5684 int
5685 nfsrvd_getxattr(struct nfsrv_descript *nd, __unused int isdgram,
5686     vnode_t vp, __unused struct nfsexstuff *exp)
5687 {
5688 	uint32_t *tl;
5689 	struct mbuf *mp = NULL, *mpend = NULL;
5690 	int error, len;
5691 	char *name;
5692 	struct thread *p = curthread;
5693 	uint16_t off;
5694 
5695 	error = 0;
5696 	NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
5697 	len = fxdr_unsigned(int, *tl);
5698 	if (len <= 0) {
5699 		nd->nd_repstat = NFSERR_BADXDR;
5700 		goto nfsmout;
5701 	}
5702 	if (len > EXTATTR_MAXNAMELEN) {
5703 		nd->nd_repstat = NFSERR_NOXATTR;
5704 		goto nfsmout;
5705 	}
5706 	name = malloc(len + 1, M_TEMP, M_WAITOK);
5707 	nd->nd_repstat = nfsrv_mtostr(nd, name, len);
5708 	if (nd->nd_repstat == 0)
5709 		nd->nd_repstat = nfsvno_getxattr(vp, name,
5710 		    nd->nd_maxresp, nd->nd_cred, nd->nd_flag,
5711 		    nd->nd_maxextsiz, p, &mp, &mpend, &len);
5712 	if (nd->nd_repstat == ENOATTR)
5713 		nd->nd_repstat = NFSERR_NOXATTR;
5714 	else if (nd->nd_repstat == EOPNOTSUPP)
5715 		nd->nd_repstat = NFSERR_NOTSUPP;
5716 	if (nd->nd_repstat == 0) {
5717 		NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
5718 		*tl = txdr_unsigned(len);
5719 		if (len > 0) {
5720 			nd->nd_mb->m_next = mp;
5721 			nd->nd_mb = mpend;
5722 			if ((mpend->m_flags & M_EXTPG) != 0) {
5723 				nd->nd_flag |= ND_EXTPG;
5724 				nd->nd_bextpg = mpend->m_epg_npgs - 1;
5725 				nd->nd_bpos = (char *)(void *)
5726 				   PHYS_TO_DMAP(mpend->m_epg_pa[nd->nd_bextpg]);
5727 				off = (nd->nd_bextpg == 0) ?
5728 				    mpend->m_epg_1st_off : 0;
5729 				nd->nd_bpos += off + mpend->m_epg_last_len;
5730 				nd->nd_bextpgsiz = PAGE_SIZE -
5731 				    mpend->m_epg_last_len - off;
5732 			} else
5733 				nd->nd_bpos = mtod(mpend, char *) +
5734 				    mpend->m_len;
5735 		}
5736 	}
5737 	free(name, M_TEMP);
5738 
5739 nfsmout:
5740 	if (nd->nd_repstat == 0)
5741 		nd->nd_repstat = error;
5742 	vput(vp);
5743 	NFSEXITCODE2(0, nd);
5744 	return (0);
5745 }
5746 
5747 /*
5748  * nfs set extended attribute service
5749  */
5750 int
5751 nfsrvd_setxattr(struct nfsrv_descript *nd, __unused int isdgram,
5752     vnode_t vp, __unused struct nfsexstuff *exp)
5753 {
5754 	uint32_t *tl;
5755 	struct nfsvattr ova, nva;
5756 	nfsattrbit_t attrbits;
5757 	int error, len, opt;
5758 	char *name;
5759 	size_t siz;
5760 	struct thread *p = curthread;
5761 
5762 	error = 0;
5763 	name = NULL;
5764 	NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
5765 	opt = fxdr_unsigned(int, *tl++);
5766 	len = fxdr_unsigned(int, *tl);
5767 	if (len <= 0) {
5768 		nd->nd_repstat = NFSERR_BADXDR;
5769 		goto nfsmout;
5770 	}
5771 	if (len > EXTATTR_MAXNAMELEN) {
5772 		nd->nd_repstat = NFSERR_NOXATTR;
5773 		goto nfsmout;
5774 	}
5775 	name = malloc(len + 1, M_TEMP, M_WAITOK);
5776 	error = nfsrv_mtostr(nd, name, len);
5777 	if (error != 0)
5778 		goto nfsmout;
5779 	NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
5780 	len = fxdr_unsigned(int, *tl);
5781 	if (len < 0 || len > IOSIZE_MAX) {
5782 		nd->nd_repstat = NFSERR_XATTR2BIG;
5783 		goto nfsmout;
5784 	}
5785 	switch (opt) {
5786 	case NFSV4SXATTR_CREATE:
5787 		error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, NULL,
5788 		    &siz, nd->nd_cred, p);
5789 		if (error != ENOATTR)
5790 			nd->nd_repstat = NFSERR_EXIST;
5791 		error = 0;
5792 		break;
5793 	case NFSV4SXATTR_REPLACE:
5794 		error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, NULL,
5795 		    &siz, nd->nd_cred, p);
5796 		if (error != 0)
5797 			nd->nd_repstat = NFSERR_NOXATTR;
5798 		break;
5799 	case NFSV4SXATTR_EITHER:
5800 		break;
5801 	default:
5802 		nd->nd_repstat = NFSERR_BADXDR;
5803 	}
5804 	if (nd->nd_repstat != 0)
5805 		goto nfsmout;
5806 
5807 	/* Now, do the Set Extended attribute, with Change before and after. */
5808 	NFSZERO_ATTRBIT(&attrbits);
5809 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE);
5810 	nd->nd_repstat = nfsvno_getattr(vp, &ova, nd, p, 1, &attrbits);
5811 	if (nd->nd_repstat == 0) {
5812 		nd->nd_repstat = nfsvno_setxattr(vp, name, len, nd->nd_md,
5813 		    nd->nd_dpos, nd->nd_cred, p);
5814 		if (nd->nd_repstat == ENXIO)
5815 			nd->nd_repstat = NFSERR_XATTR2BIG;
5816 	}
5817 	if (nd->nd_repstat == 0 && len > 0)
5818 		nd->nd_repstat = nfsm_advance(nd, NFSM_RNDUP(len), -1);
5819 	if (nd->nd_repstat == 0)
5820 		nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, &attrbits);
5821 	if (nd->nd_repstat == 0) {
5822 		NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_UNSIGNED);
5823 		*tl++ = newnfs_true;
5824 		txdr_hyper(ova.na_filerev, tl); tl += 2;
5825 		txdr_hyper(nva.na_filerev, tl);
5826 	}
5827 
5828 nfsmout:
5829 	free(name, M_TEMP);
5830 	if (nd->nd_repstat == 0)
5831 		nd->nd_repstat = error;
5832 	vput(vp);
5833 	NFSEXITCODE2(0, nd);
5834 	return (0);
5835 }
5836 
5837 /*
5838  * nfs remove extended attribute service
5839  */
5840 int
5841 nfsrvd_rmxattr(struct nfsrv_descript *nd, __unused int isdgram,
5842     vnode_t vp, __unused struct nfsexstuff *exp)
5843 {
5844 	uint32_t *tl;
5845 	struct nfsvattr ova, nva;
5846 	nfsattrbit_t attrbits;
5847 	int error, len;
5848 	char *name;
5849 	struct thread *p = curthread;
5850 
5851 	error = 0;
5852 	name = NULL;
5853 	NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
5854 	len = fxdr_unsigned(int, *tl);
5855 	if (len <= 0) {
5856 		nd->nd_repstat = NFSERR_BADXDR;
5857 		goto nfsmout;
5858 	}
5859 	if (len > EXTATTR_MAXNAMELEN) {
5860 		nd->nd_repstat = NFSERR_NOXATTR;
5861 		goto nfsmout;
5862 	}
5863 	name = malloc(len + 1, M_TEMP, M_WAITOK);
5864 	error = nfsrv_mtostr(nd, name, len);
5865 	if (error != 0)
5866 		goto nfsmout;
5867 
5868 	if ((nd->nd_flag & ND_IMPLIEDCLID) == 0) {
5869 		printf("EEK! nfsrvd_rmxattr: no implied clientid\n");
5870 		error = NFSERR_NOXATTR;
5871 		goto nfsmout;
5872 	}
5873 	/*
5874 	 * Now, do the Remove Extended attribute, with Change before and
5875 	 * after.
5876 	*/
5877 	NFSZERO_ATTRBIT(&attrbits);
5878 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE);
5879 	nd->nd_repstat = nfsvno_getattr(vp, &ova, nd, p, 1, &attrbits);
5880 	if (nd->nd_repstat == 0) {
5881 		nd->nd_repstat = nfsvno_rmxattr(nd, vp, name, nd->nd_cred, p);
5882 		if (nd->nd_repstat == ENOATTR)
5883 			nd->nd_repstat = NFSERR_NOXATTR;
5884 	}
5885 	if (nd->nd_repstat == 0)
5886 		nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, &attrbits);
5887 	if (nd->nd_repstat == 0) {
5888 		NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_UNSIGNED);
5889 		*tl++ = newnfs_true;
5890 		txdr_hyper(ova.na_filerev, tl); tl += 2;
5891 		txdr_hyper(nva.na_filerev, tl);
5892 	}
5893 
5894 nfsmout:
5895 	free(name, M_TEMP);
5896 	if (nd->nd_repstat == 0)
5897 		nd->nd_repstat = error;
5898 	vput(vp);
5899 	NFSEXITCODE2(0, nd);
5900 	return (0);
5901 }
5902 
5903 /*
5904  * nfs list extended attribute service
5905  */
5906 int
5907 nfsrvd_listxattr(struct nfsrv_descript *nd, __unused int isdgram,
5908     vnode_t vp, __unused struct nfsexstuff *exp)
5909 {
5910 	uint32_t cnt, *tl, len, len2, i, pos, retlen;
5911 	int error;
5912 	uint64_t cookie, cookie2;
5913 	u_char *buf;
5914 	bool eof;
5915 	struct thread *p = curthread;
5916 
5917 	error = 0;
5918 	buf = NULL;
5919 	NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + NFSX_UNSIGNED);
5920 	/*
5921 	 * The cookie doesn't need to be in net byte order, but FreeBSD
5922 	 * does so to make it more readable in packet traces.
5923 	 */
5924 	cookie = fxdr_hyper(tl); tl += 2;
5925 	len = fxdr_unsigned(uint32_t, *tl);
5926 	if (len == 0 || cookie >= IOSIZE_MAX) {
5927 		nd->nd_repstat = NFSERR_BADXDR;
5928 		goto nfsmout;
5929 	}
5930 	if (len > nd->nd_maxresp - NFS_MAXXDR)
5931 		len = nd->nd_maxresp - NFS_MAXXDR;
5932 	len2 = len;
5933 	nd->nd_repstat = nfsvno_listxattr(vp, cookie, nd->nd_cred, p, &buf,
5934 	    &len, &eof);
5935 	if (nd->nd_repstat == EOPNOTSUPP)
5936 		nd->nd_repstat = NFSERR_NOTSUPP;
5937 	if (nd->nd_repstat == 0) {
5938 		cookie2 = cookie + len;
5939 		if (cookie2 < cookie)
5940 			nd->nd_repstat = NFSERR_BADXDR;
5941 	}
5942 	if (nd->nd_repstat == 0) {
5943 		/* Now copy the entries out. */
5944 		retlen = NFSX_HYPER + 2 * NFSX_UNSIGNED;
5945 		if (len == 0 && retlen <= len2) {
5946 			/* The cookie was at eof. */
5947 			NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + 2 *
5948 			    NFSX_UNSIGNED);
5949 			txdr_hyper(cookie2, tl); tl += 2;
5950 			*tl++ = txdr_unsigned(0);
5951 			*tl = newnfs_true;
5952 			goto nfsmout;
5953 		}
5954 
5955 		/* Sanity check the cookie. */
5956 		for (pos = 0; pos < len; pos += (i + 1)) {
5957 			if (pos == cookie)
5958 				break;
5959 			i = buf[pos];
5960 		}
5961 		if (pos != cookie) {
5962 			nd->nd_repstat = NFSERR_INVAL;
5963 			goto nfsmout;
5964 		}
5965 
5966 		/* Loop around copying the entrie(s) out. */
5967 		cnt = 0;
5968 		len -= cookie;
5969 		i = buf[pos];
5970 		while (i < len && len2 >= retlen + NFSM_RNDUP(i) +
5971 		    NFSX_UNSIGNED) {
5972 			if (cnt == 0) {
5973 				NFSM_BUILD(tl, uint32_t *, NFSX_HYPER +
5974 				    NFSX_UNSIGNED);
5975 				txdr_hyper(cookie2, tl); tl += 2;
5976 			}
5977 			retlen += nfsm_strtom(nd, &buf[pos + 1], i);
5978 			len -= (i + 1);
5979 			pos += (i + 1);
5980 			i = buf[pos];
5981 			cnt++;
5982 		}
5983 		/*
5984 		 * eof is set true/false by nfsvno_listxattr(), but if we
5985 		 * can't copy all entries returned by nfsvno_listxattr(),
5986 		 * we are not at eof.
5987 		 */
5988 		if (len > 0)
5989 			eof = false;
5990 		if (cnt > 0) {
5991 			/* *tl is set above. */
5992 			*tl = txdr_unsigned(cnt);
5993 			NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
5994 			if (eof)
5995 				*tl = newnfs_true;
5996 			else
5997 				*tl = newnfs_false;
5998 		} else
5999 			nd->nd_repstat = NFSERR_TOOSMALL;
6000 	}
6001 
6002 nfsmout:
6003 	free(buf, M_TEMP);
6004 	if (nd->nd_repstat == 0)
6005 		nd->nd_repstat = error;
6006 	vput(vp);
6007 	NFSEXITCODE2(0, nd);
6008 	return (0);
6009 }
6010 
6011 /*
6012  * nfsv4 service not supported
6013  */
6014 int
6015 nfsrvd_notsupp(struct nfsrv_descript *nd, __unused int isdgram,
6016     __unused vnode_t vp, __unused struct nfsexstuff *exp)
6017 {
6018 
6019 	nd->nd_repstat = NFSERR_NOTSUPP;
6020 	NFSEXITCODE2(0, nd);
6021 	return (0);
6022 }
6023