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