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