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