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