xref: /freebsd/sys/fs/nfs/nfs_commonsubs.c (revision 77013d11e6483b970af25e13c9b892075742f7e5)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1989, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Rick Macklem at The University of Guelph.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  */
35 
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38 
39 /*
40  * These functions support the macros and help fiddle mbuf chains for
41  * the nfs op functions. They do things like create the rpc header and
42  * copy data between mbuf chains and uio lists.
43  */
44 #include "opt_inet.h"
45 #include "opt_inet6.h"
46 
47 #include <fs/nfs/nfsport.h>
48 
49 #include <sys/extattr.h>
50 
51 #include <security/mac/mac_framework.h>
52 
53 #include <vm/vm_param.h>
54 
55 /*
56  * Data items converted to xdr at startup, since they are constant
57  * This is kinda hokey, but may save a little time doing byte swaps
58  */
59 u_int32_t newnfs_true, newnfs_false, newnfs_xdrneg1;
60 
61 /* And other global data */
62 nfstype nfsv34_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK,
63 		      NFFIFO, NFNON };
64 enum vtype newnv2tov_type[8] = { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON, VNON };
65 enum vtype nv34tov_type[8]={ VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO };
66 struct timeval nfsboottime;	/* Copy boottime once, so it never changes */
67 int nfscl_ticks;
68 int nfsrv_useacl = 1;
69 struct nfssockreq nfsrv_nfsuserdsock;
70 nfsuserd_state nfsrv_nfsuserd = NOTRUNNING;
71 static int nfsrv_userdupcalls = 0;
72 struct nfsreqhead nfsd_reqq;
73 uid_t nfsrv_defaultuid = UID_NOBODY;
74 gid_t nfsrv_defaultgid = GID_NOGROUP;
75 int nfsrv_lease = NFSRV_LEASE;
76 int ncl_mbuf_mlen = MLEN;
77 int nfsd_enable_stringtouid = 0;
78 int nfsrv_doflexfile = 0;
79 static int nfs_enable_uidtostring = 0;
80 NFSNAMEIDMUTEX;
81 NFSSOCKMUTEX;
82 extern int nfsrv_lughashsize;
83 extern struct mtx nfsrv_dslock_mtx;
84 extern volatile int nfsrv_devidcnt;
85 extern int nfscl_debuglevel;
86 extern struct nfsdevicehead nfsrv_devidhead;
87 extern struct nfsstatsv1 nfsstatsv1;
88 extern uint32_t nfs_srvmaxio;
89 
90 SYSCTL_DECL(_vfs_nfs);
91 SYSCTL_INT(_vfs_nfs, OID_AUTO, enable_uidtostring, CTLFLAG_RW,
92     &nfs_enable_uidtostring, 0, "Make nfs always send numeric owner_names");
93 
94 int nfsrv_maxpnfsmirror = 1;
95 SYSCTL_INT(_vfs_nfs, OID_AUTO, pnfsmirror, CTLFLAG_RD,
96     &nfsrv_maxpnfsmirror, 0, "Mirror level for pNFS service");
97 
98 int nfs_maxcopyrange = 10 * 1024 * 1024;
99 SYSCTL_INT(_vfs_nfs, OID_AUTO, maxcopyrange, CTLFLAG_RW,
100     &nfs_maxcopyrange, 0, "Max size of a Copy so RPC times reasonable");
101 
102 /*
103  * This array of structures indicates, for V4:
104  * retfh - which of 3 types of calling args are used
105  *	0 - doesn't change cfh or use a sfh
106  *	1 - replaces cfh with a new one (unless it returns an error status)
107  *	2 - uses cfh and sfh
108  * needscfh - if the op wants a cfh and premtime
109  *	0 - doesn't use a cfh
110  *	1 - uses a cfh, but doesn't want pre-op attributes
111  *	2 - uses a cfh and wants pre-op attributes
112  * savereply - indicates a non-idempotent Op
113  *	0 - not non-idempotent
114  *	1 - non-idempotent
115  * Ops that are ordered via seqid# are handled separately from these
116  * non-idempotent Ops.
117  * Define it here, since it is used by both the client and server.
118  */
119 struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS] = {
120 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* undef */
121 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* undef */
122 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* undef */
123 	{ 0, 1, 0, 0, LK_SHARED, 1, 1 },		/* Access */
124 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1, 0 },		/* Close */
125 	{ 0, 2, 0, 1, LK_EXCLUSIVE, 1, 1 },		/* Commit */
126 	{ 1, 2, 1, 1, LK_EXCLUSIVE, 1, 1 },		/* Create */
127 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 0 },		/* Delegpurge */
128 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1, 0 },		/* Delegreturn */
129 	{ 0, 1, 0, 0, LK_SHARED, 1, 1 },		/* Getattr */
130 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* GetFH */
131 	{ 2, 1, 1, 1, LK_EXCLUSIVE, 1, 1 },		/* Link */
132 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1, 0 },		/* Lock */
133 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1, 0 },		/* LockT */
134 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1, 0 },		/* LockU */
135 	{ 1, 2, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Lookup */
136 	{ 1, 2, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Lookupp */
137 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* NVerify */
138 	{ 1, 1, 0, 1, LK_EXCLUSIVE, 1, 0 },		/* Open */
139 	{ 1, 1, 0, 0, LK_EXCLUSIVE, 1, 0 },		/* OpenAttr */
140 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1, 0 },		/* OpenConfirm */
141 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1, 0 },		/* OpenDowngrade */
142 	{ 1, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* PutFH */
143 	{ 1, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* PutPubFH */
144 	{ 1, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* PutRootFH */
145 	{ 0, 1, 0, 0, LK_SHARED, 1, 0 },		/* Read */
146 	{ 0, 1, 0, 0, LK_SHARED, 1, 1 },		/* Readdir */
147 	{ 0, 1, 0, 0, LK_SHARED, 1, 1 },		/* ReadLink */
148 	{ 0, 2, 1, 1, LK_EXCLUSIVE, 1, 1 },		/* Remove */
149 	{ 2, 1, 1, 1, LK_EXCLUSIVE, 1, 1 },		/* Rename */
150 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 0 },		/* Renew */
151 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* RestoreFH */
152 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* SaveFH */
153 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* SecInfo */
154 	{ 0, 2, 1, 1, LK_EXCLUSIVE, 1, 0 },		/* Setattr */
155 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* SetClientID */
156 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* SetClientIDConfirm */
157 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Verify */
158 	{ 0, 2, 1, 1, LK_EXCLUSIVE, 1, 0 },		/* Write */
159 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 0 },		/* ReleaseLockOwner */
160 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Backchannel Ctrl */
161 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 0, 0 },		/* Bind Conn to Sess */
162 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 0, 0 },		/* Exchange ID */
163 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 0, 0 },		/* Create Session */
164 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 0, 0 },		/* Destroy Session */
165 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 0 },		/* Free StateID */
166 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Get Dir Deleg */
167 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Get Device Info */
168 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Get Device List */
169 	{ 0, 1, 0, 1, LK_EXCLUSIVE, 1, 1 },		/* Layout Commit */
170 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Layout Get */
171 	{ 0, 1, 0, 1, LK_EXCLUSIVE, 1, 0 },		/* Layout Return */
172 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Secinfo No name */
173 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 0 },		/* Sequence */
174 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Set SSV */
175 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Test StateID */
176 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Want Delegation */
177 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 0, 0 },		/* Destroy ClientID */
178 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 0 },		/* Reclaim Complete */
179 	{ 0, 1, 1, 1, LK_EXCLUSIVE, 1, 0 },		/* Allocate */
180 	{ 2, 1, 1, 0, LK_SHARED, 1, 0 },		/* Copy */
181 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Copy Notify */
182 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Deallocate */
183 	{ 0, 1, 0, 0, LK_SHARED, 1, 0 },		/* IO Advise */
184 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1, 0 },		/* Layout Error */
185 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1, 0 },		/* Layout Stats */
186 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Offload Cancel */
187 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Offload Status */
188 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Read Plus */
189 	{ 0, 1, 0, 0, LK_SHARED, 1, 0 },		/* Seek */
190 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Write Same */
191 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* Clone */
192 	{ 0, 1, 0, 0, LK_SHARED, 1, 1 },		/* Getxattr */
193 	{ 0, 1, 1, 1, LK_EXCLUSIVE, 1, 1 },		/* Setxattr */
194 	{ 0, 1, 0, 0, LK_SHARED, 1, 1 },		/* Listxattrs */
195 	{ 0, 1, 1, 1, LK_EXCLUSIVE, 1, 1 },		/* Removexattr */
196 };
197 
198 static int ncl_mbuf_mhlen = MHLEN;
199 static int nfsrv_usercnt = 0;
200 static int nfsrv_dnsnamelen;
201 static u_char *nfsrv_dnsname = NULL;
202 static int nfsrv_usermax = 999999999;
203 struct nfsrv_lughash {
204 	struct mtx		mtx;
205 	struct nfsuserhashhead	lughead;
206 };
207 static struct nfsrv_lughash	*nfsuserhash;
208 static struct nfsrv_lughash	*nfsusernamehash;
209 static struct nfsrv_lughash	*nfsgrouphash;
210 static struct nfsrv_lughash	*nfsgroupnamehash;
211 
212 /*
213  * This static array indicates whether or not the RPC generates a large
214  * reply. This is used by nfs_reply() to decide whether or not an mbuf
215  * cluster should be allocated. (If a cluster is required by an RPC
216  * marked 0 in this array, the code will still work, just not quite as
217  * efficiently.)
218  */
219 static int nfs_bigreply[NFSV42_NPROCS] = { 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0,
220     0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
221     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
222     1, 0, 0, 1, 0 };
223 
224 /* local functions */
225 static int nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep);
226 static void nfsv4_wanted(struct nfsv4lock *lp);
227 static int nfsrv_cmpmixedcase(u_char *cp, u_char *cp2, int len);
228 static int nfsrv_getuser(int procnum, uid_t uid, gid_t gid, char *name);
229 static void nfsrv_removeuser(struct nfsusrgrp *usrp, int isuser);
230 static int nfsrv_getrefstr(struct nfsrv_descript *, u_char **, u_char **,
231     int *, int *);
232 static void nfsrv_refstrbigenough(int, u_char **, u_char **, int *);
233 
234 static struct {
235 	int	op;
236 	int	opcnt;
237 	const u_char *tag;
238 	int	taglen;
239 } nfsv4_opmap[NFSV42_NPROCS] = {
240 	{ 0, 1, "Null", 4 },
241 	{ NFSV4OP_GETATTR, 1, "Getattr", 7, },
242 	{ NFSV4OP_SETATTR, 2, "Setattr", 7, },
243 	{ NFSV4OP_LOOKUP, 3, "Lookup", 6, },
244 	{ NFSV4OP_ACCESS, 2, "Access", 6, },
245 	{ NFSV4OP_READLINK, 2, "Readlink", 8, },
246 	{ NFSV4OP_READ, 1, "Read", 4, },
247 	{ NFSV4OP_WRITE, 2, "Write", 5, },
248 	{ NFSV4OP_OPEN, 5, "Open", 4, },
249 	{ NFSV4OP_CREATE, 5, "Create", 6, },
250 	{ NFSV4OP_CREATE, 1, "Create", 6, },
251 	{ NFSV4OP_CREATE, 3, "Create", 6, },
252 	{ NFSV4OP_REMOVE, 1, "Remove", 6, },
253 	{ NFSV4OP_REMOVE, 1, "Remove", 6, },
254 	{ NFSV4OP_SAVEFH, 5, "Rename", 6, },
255 	{ NFSV4OP_SAVEFH, 4, "Link", 4, },
256 	{ NFSV4OP_READDIR, 2, "Readdir", 7, },
257 	{ NFSV4OP_READDIR, 2, "Readdir", 7, },
258 	{ NFSV4OP_GETATTR, 1, "Getattr", 7, },
259 	{ NFSV4OP_GETATTR, 1, "Getattr", 7, },
260 	{ NFSV4OP_GETATTR, 1, "Getattr", 7, },
261 	{ NFSV4OP_COMMIT, 2, "Commit", 6, },
262 	{ NFSV4OP_LOOKUPP, 3, "Lookupp", 7, },
263 	{ NFSV4OP_SETCLIENTID, 1, "SetClientID", 11, },
264 	{ NFSV4OP_SETCLIENTIDCFRM, 1, "SetClientIDConfirm", 18, },
265 	{ NFSV4OP_LOCK, 1, "Lock", 4, },
266 	{ NFSV4OP_LOCKU, 1, "LockU", 5, },
267 	{ NFSV4OP_OPEN, 2, "Open", 4, },
268 	{ NFSV4OP_CLOSE, 1, "Close", 5, },
269 	{ NFSV4OP_OPENCONFIRM, 1, "Openconfirm", 11, },
270 	{ NFSV4OP_LOCKT, 1, "LockT", 5, },
271 	{ NFSV4OP_OPENDOWNGRADE, 1, "Opendowngrade", 13, },
272 	{ NFSV4OP_RENEW, 1, "Renew", 5, },
273 	{ NFSV4OP_PUTROOTFH, 1, "Dirpath", 7, },
274 	{ NFSV4OP_RELEASELCKOWN, 1, "Rellckown", 9, },
275 	{ NFSV4OP_DELEGRETURN, 1, "Delegret", 8, },
276 	{ NFSV4OP_DELEGRETURN, 3, "DelegRemove", 11, },
277 	{ NFSV4OP_DELEGRETURN, 7, "DelegRename1", 12, },
278 	{ NFSV4OP_DELEGRETURN, 9, "DelegRename2", 12, },
279 	{ NFSV4OP_GETATTR, 1, "Getacl", 6, },
280 	{ NFSV4OP_SETATTR, 1, "Setacl", 6, },
281 	{ NFSV4OP_EXCHANGEID, 1, "ExchangeID", 10, },
282 	{ NFSV4OP_CREATESESSION, 1, "CreateSession", 13, },
283 	{ NFSV4OP_DESTROYSESSION, 1, "DestroySession", 14, },
284 	{ NFSV4OP_DESTROYCLIENTID, 1, "DestroyClient", 13, },
285 	{ NFSV4OP_FREESTATEID, 1, "FreeStateID", 11, },
286 	{ NFSV4OP_LAYOUTGET, 1, "LayoutGet", 9, },
287 	{ NFSV4OP_GETDEVINFO, 1, "GetDeviceInfo", 13, },
288 	{ NFSV4OP_LAYOUTCOMMIT, 1, "LayoutCommit", 12, },
289 	{ NFSV4OP_LAYOUTRETURN, 1, "LayoutReturn", 12, },
290 	{ NFSV4OP_RECLAIMCOMPL, 1, "ReclaimComplete", 15, },
291 	{ NFSV4OP_WRITE, 1, "WriteDS", 7, },
292 	{ NFSV4OP_READ, 1, "ReadDS", 6, },
293 	{ NFSV4OP_COMMIT, 1, "CommitDS", 8, },
294 	{ NFSV4OP_OPEN, 3, "OpenLayoutGet", 13, },
295 	{ NFSV4OP_OPEN, 8, "CreateLayGet", 12, },
296 	{ NFSV4OP_IOADVISE, 1, "Advise", 6, },
297 	{ NFSV4OP_ALLOCATE, 2, "Allocate", 8, },
298 	{ NFSV4OP_SAVEFH, 5, "Copy", 4, },
299 	{ NFSV4OP_SEEK, 2, "Seek", 4, },
300 	{ NFSV4OP_SEEK, 1, "SeekDS", 6, },
301 	{ NFSV4OP_GETXATTR, 2, "Getxattr", 8, },
302 	{ NFSV4OP_SETXATTR, 2, "Setxattr", 8, },
303 	{ NFSV4OP_REMOVEXATTR, 2, "Rmxattr", 7, },
304 	{ NFSV4OP_LISTXATTRS, 2, "Listxattr", 9, },
305 	{ NFSV4OP_BINDCONNTOSESS, 1, "BindConSess", 11, },
306 };
307 
308 /*
309  * NFS RPCS that have large request message size.
310  */
311 static int nfs_bigrequest[NFSV42_NPROCS] = {
312 	0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
313 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
314 	0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0
315 };
316 
317 /*
318  * Start building a request. Mostly just put the first file handle in
319  * place.
320  */
321 void
322 nfscl_reqstart(struct nfsrv_descript *nd, int procnum, struct nfsmount *nmp,
323     u_int8_t *nfhp, int fhlen, u_int32_t **opcntpp, struct nfsclsession *sep,
324     int vers, int minorvers)
325 {
326 	struct mbuf *mb;
327 	u_int32_t *tl;
328 	int opcnt;
329 	nfsattrbit_t attrbits;
330 
331 	/*
332 	 * First, fill in some of the fields of nd.
333 	 */
334 	nd->nd_slotseq = NULL;
335 	if (vers == NFS_VER4) {
336 		nd->nd_flag = ND_NFSV4 | ND_NFSCL;
337 		if (minorvers == NFSV41_MINORVERSION)
338 			nd->nd_flag |= ND_NFSV41;
339 		else if (minorvers == NFSV42_MINORVERSION)
340 			nd->nd_flag |= (ND_NFSV41 | ND_NFSV42);
341 	} else if (vers == NFS_VER3)
342 		nd->nd_flag = ND_NFSV3 | ND_NFSCL;
343 	else {
344 		if (NFSHASNFSV4(nmp)) {
345 			nd->nd_flag = ND_NFSV4 | ND_NFSCL;
346 			if (nmp->nm_minorvers == 1)
347 				nd->nd_flag |= ND_NFSV41;
348 			else if (nmp->nm_minorvers == 2)
349 				nd->nd_flag |= (ND_NFSV41 | ND_NFSV42);
350 		} else if (NFSHASNFSV3(nmp))
351 			nd->nd_flag = ND_NFSV3 | ND_NFSCL;
352 		else
353 			nd->nd_flag = ND_NFSV2 | ND_NFSCL;
354 	}
355 	nd->nd_procnum = procnum;
356 	nd->nd_repstat = 0;
357 	nd->nd_maxextsiz = 0;
358 
359 	/*
360 	 * Get the first mbuf for the request.
361 	 */
362 	if (nfs_bigrequest[procnum])
363 		NFSMCLGET(mb, M_WAITOK);
364 	else
365 		NFSMGET(mb);
366 	mb->m_len = 0;
367 	nd->nd_mreq = nd->nd_mb = mb;
368 	nd->nd_bpos = mtod(mb, char *);
369 
370 	/*
371 	 * And fill the first file handle into the request.
372 	 */
373 	if (nd->nd_flag & ND_NFSV4) {
374 		opcnt = nfsv4_opmap[procnum].opcnt +
375 		    nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh;
376 		if ((nd->nd_flag & ND_NFSV41) != 0) {
377 			opcnt += nfsv4_opflag[nfsv4_opmap[procnum].op].needsseq;
378 			if (procnum == NFSPROC_RENEW)
379 				/*
380 				 * For the special case of Renew, just do a
381 				 * Sequence Op.
382 				 */
383 				opcnt = 1;
384 			else if (procnum == NFSPROC_WRITEDS ||
385 			    procnum == NFSPROC_COMMITDS)
386 				/*
387 				 * For the special case of a Writeor Commit to
388 				 * a DS, the opcnt == 3, for Sequence, PutFH,
389 				 * Write/Commit.
390 				 */
391 				opcnt = 3;
392 		}
393 		/*
394 		 * What should the tag really be?
395 		 */
396 		(void) nfsm_strtom(nd, nfsv4_opmap[procnum].tag,
397 			nfsv4_opmap[procnum].taglen);
398 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
399 		if ((nd->nd_flag & ND_NFSV42) != 0)
400 			*tl++ = txdr_unsigned(NFSV42_MINORVERSION);
401 		else if ((nd->nd_flag & ND_NFSV41) != 0)
402 			*tl++ = txdr_unsigned(NFSV41_MINORVERSION);
403 		else
404 			*tl++ = txdr_unsigned(NFSV4_MINORVERSION);
405 		if (opcntpp != NULL)
406 			*opcntpp = tl;
407 		*tl = txdr_unsigned(opcnt);
408 		if ((nd->nd_flag & ND_NFSV41) != 0 &&
409 		    nfsv4_opflag[nfsv4_opmap[procnum].op].needsseq > 0) {
410 			if (nfsv4_opflag[nfsv4_opmap[procnum].op].loopbadsess >
411 			    0)
412 				nd->nd_flag |= ND_LOOPBADSESS;
413 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
414 			*tl = txdr_unsigned(NFSV4OP_SEQUENCE);
415 			if (sep == NULL) {
416 				sep = nfsmnt_mdssession(nmp);
417 				nfsv4_setsequence(nmp, nd, sep,
418 				    nfs_bigreply[procnum]);
419 			} else
420 				nfsv4_setsequence(nmp, nd, sep,
421 				    nfs_bigreply[procnum]);
422 		}
423 		if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh > 0) {
424 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
425 			*tl = txdr_unsigned(NFSV4OP_PUTFH);
426 			(void) nfsm_fhtom(nd, nfhp, fhlen, 0);
427 			if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh
428 			    == 2 && procnum != NFSPROC_WRITEDS &&
429 			    procnum != NFSPROC_COMMITDS) {
430 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
431 				*tl = txdr_unsigned(NFSV4OP_GETATTR);
432 				/*
433 				 * For Lookup Ops, we want all the directory
434 				 * attributes, so we can load the name cache.
435 				 */
436 				if (procnum == NFSPROC_LOOKUP ||
437 				    procnum == NFSPROC_LOOKUPP)
438 					NFSGETATTR_ATTRBIT(&attrbits);
439 				else {
440 					NFSWCCATTR_ATTRBIT(&attrbits);
441 					nd->nd_flag |= ND_V4WCCATTR;
442 				}
443 				(void) nfsrv_putattrbit(nd, &attrbits);
444 			}
445 		}
446 		if (procnum != NFSPROC_RENEW ||
447 		    (nd->nd_flag & ND_NFSV41) == 0) {
448 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
449 			*tl = txdr_unsigned(nfsv4_opmap[procnum].op);
450 		}
451 	} else {
452 		(void) nfsm_fhtom(nd, nfhp, fhlen, 0);
453 	}
454 	if (procnum < NFSV42_NPROCS)
455 		NFSINCRGLOBAL(nfsstatsv1.rpccnt[procnum]);
456 }
457 
458 /*
459  * Put a state Id in the mbuf list.
460  */
461 void
462 nfsm_stateidtom(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp, int flag)
463 {
464 	nfsv4stateid_t *st;
465 
466 	NFSM_BUILD(st, nfsv4stateid_t *, NFSX_STATEID);
467 	if (flag == NFSSTATEID_PUTALLZERO) {
468 		st->seqid = 0;
469 		st->other[0] = 0;
470 		st->other[1] = 0;
471 		st->other[2] = 0;
472 	} else if (flag == NFSSTATEID_PUTALLONE) {
473 		st->seqid = 0xffffffff;
474 		st->other[0] = 0xffffffff;
475 		st->other[1] = 0xffffffff;
476 		st->other[2] = 0xffffffff;
477 	} else if (flag == NFSSTATEID_PUTSEQIDZERO) {
478 		st->seqid = 0;
479 		st->other[0] = stateidp->other[0];
480 		st->other[1] = stateidp->other[1];
481 		st->other[2] = stateidp->other[2];
482 	} else {
483 		st->seqid = stateidp->seqid;
484 		st->other[0] = stateidp->other[0];
485 		st->other[1] = stateidp->other[1];
486 		st->other[2] = stateidp->other[2];
487 	}
488 }
489 
490 /*
491  * Fill in the setable attributes. The full argument indicates whether
492  * to fill in them all or just mode and time.
493  */
494 void
495 nfscl_fillsattr(struct nfsrv_descript *nd, struct vattr *vap,
496     struct vnode *vp, int flags, u_int32_t rdev)
497 {
498 	u_int32_t *tl;
499 	struct nfsv2_sattr *sp;
500 	nfsattrbit_t attrbits;
501 	struct nfsnode *np;
502 
503 	switch (nd->nd_flag & (ND_NFSV2 | ND_NFSV3 | ND_NFSV4)) {
504 	case ND_NFSV2:
505 		NFSM_BUILD(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
506 		if (vap->va_mode == (mode_t)VNOVAL)
507 			sp->sa_mode = newnfs_xdrneg1;
508 		else
509 			sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
510 		if (vap->va_uid == (uid_t)VNOVAL)
511 			sp->sa_uid = newnfs_xdrneg1;
512 		else
513 			sp->sa_uid = txdr_unsigned(vap->va_uid);
514 		if (vap->va_gid == (gid_t)VNOVAL)
515 			sp->sa_gid = newnfs_xdrneg1;
516 		else
517 			sp->sa_gid = txdr_unsigned(vap->va_gid);
518 		if (flags & NFSSATTR_SIZE0)
519 			sp->sa_size = 0;
520 		else if (flags & NFSSATTR_SIZENEG1)
521 			sp->sa_size = newnfs_xdrneg1;
522 		else if (flags & NFSSATTR_SIZERDEV)
523 			sp->sa_size = txdr_unsigned(rdev);
524 		else
525 			sp->sa_size = txdr_unsigned(vap->va_size);
526 		txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
527 		txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
528 		break;
529 	case ND_NFSV3:
530 		if (vap->va_mode != (mode_t)VNOVAL) {
531 			NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
532 			*tl++ = newnfs_true;
533 			*tl = txdr_unsigned(vap->va_mode);
534 		} else {
535 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
536 			*tl = newnfs_false;
537 		}
538 		if ((flags & NFSSATTR_FULL) && vap->va_uid != (uid_t)VNOVAL) {
539 			NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
540 			*tl++ = newnfs_true;
541 			*tl = txdr_unsigned(vap->va_uid);
542 		} else {
543 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
544 			*tl = newnfs_false;
545 		}
546 		if ((flags & NFSSATTR_FULL) && vap->va_gid != (gid_t)VNOVAL) {
547 			NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
548 			*tl++ = newnfs_true;
549 			*tl = txdr_unsigned(vap->va_gid);
550 		} else {
551 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
552 			*tl = newnfs_false;
553 		}
554 		if ((flags & NFSSATTR_FULL) && vap->va_size != VNOVAL) {
555 			NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
556 			*tl++ = newnfs_true;
557 			txdr_hyper(vap->va_size, tl);
558 		} else {
559 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
560 			*tl = newnfs_false;
561 		}
562 		if (vap->va_atime.tv_sec != VNOVAL) {
563 			if ((vap->va_vaflags & VA_UTIMES_NULL) == 0) {
564 				NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
565 				*tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
566 				txdr_nfsv3time(&vap->va_atime, tl);
567 			} else {
568 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
569 				*tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER);
570 			}
571 		} else {
572 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
573 			*tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
574 		}
575 		if (vap->va_mtime.tv_sec != VNOVAL) {
576 			if ((vap->va_vaflags & VA_UTIMES_NULL) == 0) {
577 				NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
578 				*tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
579 				txdr_nfsv3time(&vap->va_mtime, tl);
580 			} else {
581 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
582 				*tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER);
583 			}
584 		} else {
585 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
586 			*tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
587 		}
588 		break;
589 	case ND_NFSV4:
590 		NFSZERO_ATTRBIT(&attrbits);
591 		if (vap->va_mode != (mode_t)VNOVAL)
592 			NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_MODE);
593 		if ((flags & NFSSATTR_FULL) && vap->va_uid != (uid_t)VNOVAL)
594 			NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNER);
595 		if ((flags & NFSSATTR_FULL) && vap->va_gid != (gid_t)VNOVAL)
596 			NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNERGROUP);
597 		if ((flags & NFSSATTR_FULL) && vap->va_size != VNOVAL)
598 			NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SIZE);
599 		if (vap->va_atime.tv_sec != VNOVAL)
600 			NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESSSET);
601 		if (vap->va_mtime.tv_sec != VNOVAL)
602 			NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFYSET);
603 		if (vap->va_birthtime.tv_sec != VNOVAL &&
604 		    strcmp(vp->v_mount->mnt_vfc->vfc_name, "nfs") == 0) {
605 			/*
606 			 * We can only test for support of TimeCreate if
607 			 * the "vp" argument is for an NFS vnode.
608 			 */
609 			np = VTONFS(vp);
610 			if (NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr,
611 			    NFSATTRBIT_TIMECREATE))
612 				NFSSETBIT_ATTRBIT(&attrbits,
613 				    NFSATTRBIT_TIMECREATE);
614 		}
615 		(void) nfsv4_fillattr(nd, vp->v_mount, vp, NULL, vap, NULL, 0,
616 		    &attrbits, NULL, NULL, 0, 0, 0, 0, (uint64_t)0, NULL);
617 		break;
618 	}
619 }
620 
621 #ifndef APPLE
622 /*
623  * copies mbuf chain to the uio scatter/gather list
624  */
625 int
626 nfsm_mbufuio(struct nfsrv_descript *nd, struct uio *uiop, int siz)
627 {
628 	char *mbufcp, *uiocp;
629 	int xfer, left, len;
630 	struct mbuf *mp;
631 	long uiosiz, rem;
632 	int error = 0;
633 
634 	mp = nd->nd_md;
635 	mbufcp = nd->nd_dpos;
636 	len = mtod(mp, caddr_t) + mp->m_len - mbufcp;
637 	rem = NFSM_RNDUP(siz) - siz;
638 	while (siz > 0) {
639 		if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) {
640 			error = EBADRPC;
641 			goto out;
642 		}
643 		left = uiop->uio_iov->iov_len;
644 		uiocp = uiop->uio_iov->iov_base;
645 		if (left > siz)
646 			left = siz;
647 		uiosiz = left;
648 		while (left > 0) {
649 			while (len == 0) {
650 				mp = mp->m_next;
651 				if (mp == NULL) {
652 					error = EBADRPC;
653 					goto out;
654 				}
655 				mbufcp = mtod(mp, caddr_t);
656 				len = mp->m_len;
657 				KASSERT(len >= 0,
658 				    ("len %d, corrupted mbuf?", len));
659 			}
660 			xfer = (left > len) ? len : left;
661 #ifdef notdef
662 			/* Not Yet.. */
663 			if (uiop->uio_iov->iov_op != NULL)
664 				(*(uiop->uio_iov->iov_op))
665 				(mbufcp, uiocp, xfer);
666 			else
667 #endif
668 			if (uiop->uio_segflg == UIO_SYSSPACE)
669 				NFSBCOPY(mbufcp, uiocp, xfer);
670 			else
671 				copyout(mbufcp, uiocp, xfer);
672 			left -= xfer;
673 			len -= xfer;
674 			mbufcp += xfer;
675 			uiocp += xfer;
676 			uiop->uio_offset += xfer;
677 			uiop->uio_resid -= xfer;
678 		}
679 		if (uiop->uio_iov->iov_len <= siz) {
680 			uiop->uio_iovcnt--;
681 			uiop->uio_iov++;
682 		} else {
683 			uiop->uio_iov->iov_base = (void *)
684 				((char *)uiop->uio_iov->iov_base + uiosiz);
685 			uiop->uio_iov->iov_len -= uiosiz;
686 		}
687 		siz -= uiosiz;
688 	}
689 	nd->nd_dpos = mbufcp;
690 	nd->nd_md = mp;
691 	if (rem > 0) {
692 		if (len < rem)
693 			error = nfsm_advance(nd, rem, len);
694 		else
695 			nd->nd_dpos += rem;
696 	}
697 
698 out:
699 	NFSEXITCODE2(error, nd);
700 	return (error);
701 }
702 #endif	/* !APPLE */
703 
704 /*
705  * Help break down an mbuf chain by setting the first siz bytes contiguous
706  * pointed to by returned val.
707  * This is used by the macro NFSM_DISSECT for tough
708  * cases.
709  */
710 void *
711 nfsm_dissct(struct nfsrv_descript *nd, int siz, int how)
712 {
713 	struct mbuf *mp2;
714 	int siz2, xfer;
715 	caddr_t p;
716 	int left;
717 	caddr_t retp;
718 
719 	retp = NULL;
720 	left = mtod(nd->nd_md, caddr_t) + nd->nd_md->m_len - nd->nd_dpos;
721 	while (left == 0) {
722 		nd->nd_md = nd->nd_md->m_next;
723 		if (nd->nd_md == NULL)
724 			return (retp);
725 		left = nd->nd_md->m_len;
726 		nd->nd_dpos = mtod(nd->nd_md, caddr_t);
727 	}
728 	if (left >= siz) {
729 		retp = nd->nd_dpos;
730 		nd->nd_dpos += siz;
731 	} else if (nd->nd_md->m_next == NULL) {
732 		return (retp);
733 	} else if (siz > ncl_mbuf_mhlen) {
734 		panic("nfs S too big");
735 	} else {
736 		MGET(mp2, MT_DATA, how);
737 		if (mp2 == NULL)
738 			return (NULL);
739 		mp2->m_next = nd->nd_md->m_next;
740 		nd->nd_md->m_next = mp2;
741 		nd->nd_md->m_len -= left;
742 		nd->nd_md = mp2;
743 		retp = p = mtod(mp2, caddr_t);
744 		NFSBCOPY(nd->nd_dpos, p, left);	/* Copy what was left */
745 		siz2 = siz - left;
746 		p += left;
747 		mp2 = mp2->m_next;
748 		/* Loop around copying up the siz2 bytes */
749 		while (siz2 > 0) {
750 			if (mp2 == NULL)
751 				return (NULL);
752 			xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
753 			if (xfer > 0) {
754 				NFSBCOPY(mtod(mp2, caddr_t), p, xfer);
755 				mp2->m_data += xfer;
756 				mp2->m_len -= xfer;
757 				p += xfer;
758 				siz2 -= xfer;
759 			}
760 			if (siz2 > 0)
761 				mp2 = mp2->m_next;
762 		}
763 		nd->nd_md->m_len = siz;
764 		nd->nd_md = mp2;
765 		nd->nd_dpos = mtod(mp2, caddr_t);
766 	}
767 	return (retp);
768 }
769 
770 /*
771  * Advance the position in the mbuf chain.
772  * If offs == 0, this is a no-op, but it is simpler to just return from
773  * here than check for offs > 0 for all calls to nfsm_advance.
774  * If left == -1, it should be calculated here.
775  */
776 int
777 nfsm_advance(struct nfsrv_descript *nd, int offs, int left)
778 {
779 	int error = 0;
780 
781 	if (offs == 0)
782 		goto out;
783 	/*
784 	 * A negative offs might indicate a corrupted mbuf chain and,
785 	 * as such, a printf is logged.
786 	 */
787 	if (offs < 0) {
788 		printf("nfsrv_advance: negative offs\n");
789 		error = EBADRPC;
790 		goto out;
791 	}
792 
793 	/*
794 	 * If left == -1, calculate it here.
795 	 */
796 	if (left == -1)
797 		left = mtod(nd->nd_md, caddr_t) + nd->nd_md->m_len -
798 		    nd->nd_dpos;
799 
800 	/*
801 	 * Loop around, advancing over the mbuf data.
802 	 */
803 	while (offs > left) {
804 		offs -= left;
805 		nd->nd_md = nd->nd_md->m_next;
806 		if (nd->nd_md == NULL) {
807 			error = EBADRPC;
808 			goto out;
809 		}
810 		left = nd->nd_md->m_len;
811 		nd->nd_dpos = mtod(nd->nd_md, caddr_t);
812 	}
813 	nd->nd_dpos += offs;
814 
815 out:
816 	NFSEXITCODE(error);
817 	return (error);
818 }
819 
820 /*
821  * Copy a string into mbuf(s).
822  * Return the number of bytes output, including XDR overheads.
823  */
824 int
825 nfsm_strtom(struct nfsrv_descript *nd, const char *cp, int siz)
826 {
827 	struct mbuf *m2;
828 	int xfer, left;
829 	struct mbuf *m1;
830 	int rem, bytesize;
831 	u_int32_t *tl;
832 	char *cp2;
833 
834 	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
835 	*tl = txdr_unsigned(siz);
836 	rem = NFSM_RNDUP(siz) - siz;
837 	bytesize = NFSX_UNSIGNED + siz + rem;
838 	m2 = nd->nd_mb;
839 	cp2 = nd->nd_bpos;
840 	if ((nd->nd_flag & ND_EXTPG) != 0)
841 		left = nd->nd_bextpgsiz;
842 	else
843 		left = M_TRAILINGSPACE(m2);
844 
845 	KASSERT(((m2->m_flags & (M_EXT | M_EXTPG)) ==
846 	    (M_EXT | M_EXTPG) && (nd->nd_flag & ND_EXTPG) != 0) ||
847 	    ((m2->m_flags & (M_EXT | M_EXTPG)) !=
848 	    (M_EXT | M_EXTPG) && (nd->nd_flag & ND_EXTPG) == 0),
849 	    ("nfsm_strtom: ext_pgs and non-ext_pgs mbufs mixed"));
850 	/*
851 	 * Loop around copying the string to mbuf(s).
852 	 */
853 	while (siz > 0) {
854 		if (left == 0) {
855 			if ((nd->nd_flag & ND_EXTPG) != 0) {
856 				m2 = nfsm_add_ext_pgs(m2,
857 				    nd->nd_maxextsiz, &nd->nd_bextpg);
858 				cp2 = (char *)(void *)PHYS_TO_DMAP(
859 				    m2->m_epg_pa[nd->nd_bextpg]);
860 				nd->nd_bextpgsiz = left = PAGE_SIZE;
861 			} else {
862 				if (siz > ncl_mbuf_mlen)
863 					NFSMCLGET(m1, M_WAITOK);
864 				else
865 					NFSMGET(m1);
866 				m1->m_len = 0;
867 				cp2 = mtod(m1, char *);
868 				left = M_TRAILINGSPACE(m1);
869 				m2->m_next = m1;
870 				m2 = m1;
871 			}
872 		}
873 		if (left >= siz)
874 			xfer = siz;
875 		else
876 			xfer = left;
877 		NFSBCOPY(cp, cp2, xfer);
878 		cp += xfer;
879 		cp2 += xfer;
880 		m2->m_len += xfer;
881 		siz -= xfer;
882 		left -= xfer;
883 		if ((nd->nd_flag & ND_EXTPG) != 0) {
884 			nd->nd_bextpgsiz -= xfer;
885 			m2->m_epg_last_len += xfer;
886 		}
887 		if (siz == 0 && rem) {
888 			if (left < rem)
889 				panic("nfsm_strtom");
890 			NFSBZERO(cp2, rem);
891 			m2->m_len += rem;
892 			cp2 += rem;
893 			if ((nd->nd_flag & ND_EXTPG) != 0) {
894 				nd->nd_bextpgsiz -= rem;
895 				m2->m_epg_last_len += rem;
896 			}
897 		}
898 	}
899 	nd->nd_mb = m2;
900 	if ((nd->nd_flag & ND_EXTPG) != 0)
901 		nd->nd_bpos = cp2;
902 	else
903 		nd->nd_bpos = mtod(m2, char *) + m2->m_len;
904 	return (bytesize);
905 }
906 
907 /*
908  * Called once to initialize data structures...
909  */
910 void
911 newnfs_init(void)
912 {
913 	static int nfs_inited = 0;
914 
915 	if (nfs_inited)
916 		return;
917 	nfs_inited = 1;
918 
919 	newnfs_true = txdr_unsigned(TRUE);
920 	newnfs_false = txdr_unsigned(FALSE);
921 	newnfs_xdrneg1 = txdr_unsigned(-1);
922 	nfscl_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
923 	if (nfscl_ticks < 1)
924 		nfscl_ticks = 1;
925 	NFSSETBOOTTIME(nfsboottime);
926 
927 	/*
928 	 * Initialize reply list and start timer
929 	 */
930 	TAILQ_INIT(&nfsd_reqq);
931 	NFS_TIMERINIT;
932 }
933 
934 /*
935  * Put a file handle in an mbuf list.
936  * If the size argument == 0, just use the default size.
937  * set_true == 1 if there should be an newnfs_true prepended on the file handle.
938  * Return the number of bytes output, including XDR overhead.
939  */
940 int
941 nfsm_fhtom(struct nfsrv_descript *nd, u_int8_t *fhp, int size, int set_true)
942 {
943 	u_int32_t *tl;
944 	u_int8_t *cp;
945 	int fullsiz, rem, bytesize = 0;
946 
947 	if (size == 0)
948 		size = NFSX_MYFH;
949 	switch (nd->nd_flag & (ND_NFSV2 | ND_NFSV3 | ND_NFSV4)) {
950 	case ND_NFSV2:
951 		if (size > NFSX_V2FH)
952 			panic("fh size > NFSX_V2FH for NFSv2");
953 		NFSM_BUILD(cp, u_int8_t *, NFSX_V2FH);
954 		NFSBCOPY(fhp, cp, size);
955 		if (size < NFSX_V2FH)
956 			NFSBZERO(cp + size, NFSX_V2FH - size);
957 		bytesize = NFSX_V2FH;
958 		break;
959 	case ND_NFSV3:
960 	case ND_NFSV4:
961 		fullsiz = NFSM_RNDUP(size);
962 		rem = fullsiz - size;
963 		if (set_true) {
964 		    bytesize = 2 * NFSX_UNSIGNED + fullsiz;
965 		    NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
966 		    *tl = newnfs_true;
967 		} else {
968 		    bytesize = NFSX_UNSIGNED + fullsiz;
969 		}
970 		(void) nfsm_strtom(nd, fhp, size);
971 		break;
972 	}
973 	return (bytesize);
974 }
975 
976 /*
977  * This function compares two net addresses by family and returns TRUE
978  * if they are the same host.
979  * If there is any doubt, return FALSE.
980  * The AF_INET family is handled as a special case so that address mbufs
981  * don't need to be saved to store "struct in_addr", which is only 4 bytes.
982  */
983 int
984 nfsaddr_match(int family, union nethostaddr *haddr, NFSSOCKADDR_T nam)
985 {
986 #ifdef INET
987 	struct sockaddr_in *inetaddr;
988 #endif
989 
990 	switch (family) {
991 #ifdef INET
992 	case AF_INET:
993 		inetaddr = NFSSOCKADDR(nam, struct sockaddr_in *);
994 		if (inetaddr->sin_family == AF_INET &&
995 		    inetaddr->sin_addr.s_addr == haddr->had_inet.s_addr)
996 			return (1);
997 		break;
998 #endif
999 #ifdef INET6
1000 	case AF_INET6:
1001 		{
1002 		struct sockaddr_in6 *inetaddr6;
1003 
1004 		inetaddr6 = NFSSOCKADDR(nam, struct sockaddr_in6 *);
1005 		/* XXX - should test sin6_scope_id ? */
1006 		if (inetaddr6->sin6_family == AF_INET6 &&
1007 		    IN6_ARE_ADDR_EQUAL(&inetaddr6->sin6_addr,
1008 			  &haddr->had_inet6))
1009 			return (1);
1010 		}
1011 		break;
1012 #endif
1013 	}
1014 	return (0);
1015 }
1016 
1017 /*
1018  * Similar to the above, but takes to NFSSOCKADDR_T args.
1019  */
1020 int
1021 nfsaddr2_match(NFSSOCKADDR_T nam1, NFSSOCKADDR_T nam2)
1022 {
1023 	struct sockaddr_in *addr1, *addr2;
1024 	struct sockaddr *inaddr;
1025 
1026 	inaddr = NFSSOCKADDR(nam1, struct sockaddr *);
1027 	switch (inaddr->sa_family) {
1028 	case AF_INET:
1029 		addr1 = NFSSOCKADDR(nam1, struct sockaddr_in *);
1030 		addr2 = NFSSOCKADDR(nam2, struct sockaddr_in *);
1031 		if (addr2->sin_family == AF_INET &&
1032 		    addr1->sin_addr.s_addr == addr2->sin_addr.s_addr)
1033 			return (1);
1034 		break;
1035 #ifdef INET6
1036 	case AF_INET6:
1037 		{
1038 		struct sockaddr_in6 *inet6addr1, *inet6addr2;
1039 
1040 		inet6addr1 = NFSSOCKADDR(nam1, struct sockaddr_in6 *);
1041 		inet6addr2 = NFSSOCKADDR(nam2, struct sockaddr_in6 *);
1042 		/* XXX - should test sin6_scope_id ? */
1043 		if (inet6addr2->sin6_family == AF_INET6 &&
1044 		    IN6_ARE_ADDR_EQUAL(&inet6addr1->sin6_addr,
1045 			  &inet6addr2->sin6_addr))
1046 			return (1);
1047 		}
1048 		break;
1049 #endif
1050 	}
1051 	return (0);
1052 }
1053 
1054 /*
1055  * Dissect a file handle on the client.
1056  */
1057 int
1058 nfsm_getfh(struct nfsrv_descript *nd, struct nfsfh **nfhpp)
1059 {
1060 	u_int32_t *tl;
1061 	struct nfsfh *nfhp;
1062 	int error, len;
1063 
1064 	*nfhpp = NULL;
1065 	if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
1066 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1067 		if ((len = fxdr_unsigned(int, *tl)) <= 0 ||
1068 			len > NFSX_FHMAX) {
1069 			error = EBADRPC;
1070 			goto nfsmout;
1071 		}
1072 	} else
1073 		len = NFSX_V2FH;
1074 	nfhp = malloc(sizeof (struct nfsfh) + len,
1075 	    M_NFSFH, M_WAITOK);
1076 	error = nfsrv_mtostr(nd, nfhp->nfh_fh, len);
1077 	if (error) {
1078 		free(nfhp, M_NFSFH);
1079 		goto nfsmout;
1080 	}
1081 	nfhp->nfh_len = len;
1082 	*nfhpp = nfhp;
1083 nfsmout:
1084 	NFSEXITCODE2(error, nd);
1085 	return (error);
1086 }
1087 
1088 /*
1089  * Break down the nfsv4 acl.
1090  * If the aclp == NULL or won't fit in an acl, just discard the acl info.
1091  */
1092 int
1093 nfsrv_dissectacl(struct nfsrv_descript *nd, NFSACL_T *aclp, int *aclerrp,
1094     int *aclsizep, __unused NFSPROC_T *p)
1095 {
1096 	u_int32_t *tl;
1097 	int i, aclsize;
1098 	int acecnt, error = 0, aceerr = 0, acesize;
1099 
1100 	*aclerrp = 0;
1101 	if (aclp)
1102 		aclp->acl_cnt = 0;
1103 	/*
1104 	 * Parse out the ace entries and expect them to conform to
1105 	 * what can be supported by R/W/X bits.
1106 	 */
1107 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1108 	aclsize = NFSX_UNSIGNED;
1109 	acecnt = fxdr_unsigned(int, *tl);
1110 	if (acecnt > ACL_MAX_ENTRIES)
1111 		aceerr = NFSERR_ATTRNOTSUPP;
1112 	if (nfsrv_useacl == 0)
1113 		aceerr = NFSERR_ATTRNOTSUPP;
1114 	for (i = 0; i < acecnt; i++) {
1115 		if (aclp && !aceerr)
1116 			error = nfsrv_dissectace(nd, &aclp->acl_entry[i],
1117 			    &aceerr, &acesize, p);
1118 		else
1119 			error = nfsrv_skipace(nd, &acesize);
1120 		if (error)
1121 			goto nfsmout;
1122 		aclsize += acesize;
1123 	}
1124 	if (aclp && !aceerr)
1125 		aclp->acl_cnt = acecnt;
1126 	if (aceerr)
1127 		*aclerrp = aceerr;
1128 	if (aclsizep)
1129 		*aclsizep = aclsize;
1130 nfsmout:
1131 	NFSEXITCODE2(error, nd);
1132 	return (error);
1133 }
1134 
1135 /*
1136  * Skip over an NFSv4 ace entry. Just dissect the xdr and discard it.
1137  */
1138 static int
1139 nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep)
1140 {
1141 	u_int32_t *tl;
1142 	int error, len = 0;
1143 
1144 	NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1145 	len = fxdr_unsigned(int, *(tl + 3));
1146 	error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
1147 nfsmout:
1148 	*acesizep = NFSM_RNDUP(len) + (4 * NFSX_UNSIGNED);
1149 	NFSEXITCODE2(error, nd);
1150 	return (error);
1151 }
1152 
1153 /*
1154  * Get attribute bits from an mbuf list.
1155  * Returns EBADRPC for a parsing error, 0 otherwise.
1156  * If the clearinvalid flag is set, clear the bits not supported.
1157  */
1158 int
1159 nfsrv_getattrbits(struct nfsrv_descript *nd, nfsattrbit_t *attrbitp, int *cntp,
1160     int *retnotsupp)
1161 {
1162 	u_int32_t *tl;
1163 	int cnt, i, outcnt;
1164 	int error = 0;
1165 
1166 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1167 	cnt = fxdr_unsigned(int, *tl);
1168 	if (cnt < 0) {
1169 		error = NFSERR_BADXDR;
1170 		goto nfsmout;
1171 	}
1172 	if (cnt > NFSATTRBIT_MAXWORDS)
1173 		outcnt = NFSATTRBIT_MAXWORDS;
1174 	else
1175 		outcnt = cnt;
1176 	NFSZERO_ATTRBIT(attrbitp);
1177 	if (outcnt > 0) {
1178 		NFSM_DISSECT(tl, u_int32_t *, outcnt * NFSX_UNSIGNED);
1179 		for (i = 0; i < outcnt; i++)
1180 			attrbitp->bits[i] = fxdr_unsigned(u_int32_t, *tl++);
1181 	}
1182 	for (i = 0; i < (cnt - outcnt); i++) {
1183 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1184 		if (retnotsupp != NULL && *tl != 0)
1185 			*retnotsupp = NFSERR_ATTRNOTSUPP;
1186 	}
1187 	if (cntp)
1188 		*cntp = NFSX_UNSIGNED + (cnt * NFSX_UNSIGNED);
1189 nfsmout:
1190 	NFSEXITCODE2(error, nd);
1191 	return (error);
1192 }
1193 
1194 /*
1195  * Get the attributes for V4.
1196  * If the compare flag is true, test for any attribute changes,
1197  * otherwise return the attribute values.
1198  * These attributes cover fields in "struct vattr", "struct statfs",
1199  * "struct nfsfsinfo", the file handle and the lease duration.
1200  * The value of retcmpp is set to 1 if all attributes are the same,
1201  * and 0 otherwise.
1202  * Returns EBADRPC if it can't be parsed, 0 otherwise.
1203  */
1204 int
1205 nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
1206     struct nfsvattr *nap, struct nfsfh **nfhpp, fhandle_t *fhp, int fhsize,
1207     struct nfsv3_pathconf *pc, struct statfs *sbp, struct nfsstatfs *sfp,
1208     struct nfsfsinfo *fsp, NFSACL_T *aclp, int compare, int *retcmpp,
1209     u_int32_t *leasep, u_int32_t *rderrp, NFSPROC_T *p, struct ucred *cred)
1210 {
1211 	u_int32_t *tl;
1212 	int i = 0, j, k, l = 0, m, bitpos, attrsum = 0;
1213 	int error, tfhsize, aceerr, attrsize, cnt, retnotsup;
1214 	u_char *cp, *cp2, namestr[NFSV4_SMALLSTR + 1];
1215 	nfsattrbit_t attrbits, retattrbits, checkattrbits;
1216 	struct nfsfh *tnfhp;
1217 	struct nfsreferral *refp;
1218 	u_quad_t tquad;
1219 	nfsquad_t tnfsquad;
1220 	struct timespec temptime;
1221 	uid_t uid;
1222 	gid_t gid;
1223 	u_int32_t freenum = 0, tuint;
1224 	u_int64_t uquad = 0, thyp, thyp2;
1225 #ifdef QUOTA
1226 	struct dqblk dqb;
1227 	uid_t savuid;
1228 #endif
1229 
1230 	CTASSERT(sizeof(ino_t) == sizeof(uint64_t));
1231 	if (compare) {
1232 		retnotsup = 0;
1233 		error = nfsrv_getattrbits(nd, &attrbits, NULL, &retnotsup);
1234 	} else {
1235 		error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
1236 	}
1237 	if (error)
1238 		goto nfsmout;
1239 
1240 	if (compare) {
1241 		*retcmpp = retnotsup;
1242 	} else {
1243 		/*
1244 		 * Just set default values to some of the important ones.
1245 		 */
1246 		if (nap != NULL) {
1247 			nap->na_type = VREG;
1248 			nap->na_mode = 0;
1249 			nap->na_rdev = (NFSDEV_T)0;
1250 			nap->na_mtime.tv_sec = 0;
1251 			nap->na_mtime.tv_nsec = 0;
1252 			nap->na_btime.tv_sec = -1;
1253 			nap->na_btime.tv_nsec = 0;
1254 			nap->na_gen = 0;
1255 			nap->na_flags = 0;
1256 			nap->na_blocksize = NFS_FABLKSIZE;
1257 		}
1258 		if (sbp != NULL) {
1259 			sbp->f_bsize = NFS_FABLKSIZE;
1260 			sbp->f_blocks = 0;
1261 			sbp->f_bfree = 0;
1262 			sbp->f_bavail = 0;
1263 			sbp->f_files = 0;
1264 			sbp->f_ffree = 0;
1265 		}
1266 		if (fsp != NULL) {
1267 			fsp->fs_rtmax = 8192;
1268 			fsp->fs_rtpref = 8192;
1269 			fsp->fs_maxname = NFS_MAXNAMLEN;
1270 			fsp->fs_wtmax = 8192;
1271 			fsp->fs_wtpref = 8192;
1272 			fsp->fs_wtmult = NFS_FABLKSIZE;
1273 			fsp->fs_dtpref = 8192;
1274 			fsp->fs_maxfilesize = 0xffffffffffffffffull;
1275 			fsp->fs_timedelta.tv_sec = 0;
1276 			fsp->fs_timedelta.tv_nsec = 1;
1277 			fsp->fs_properties = (NFSV3_FSFLINK | NFSV3_FSFSYMLINK |
1278 				NFSV3_FSFHOMOGENEOUS | NFSV3_FSFCANSETTIME);
1279 		}
1280 		if (pc != NULL) {
1281 			pc->pc_linkmax = NFS_LINK_MAX;
1282 			pc->pc_namemax = NAME_MAX;
1283 			pc->pc_notrunc = 0;
1284 			pc->pc_chownrestricted = 0;
1285 			pc->pc_caseinsensitive = 0;
1286 			pc->pc_casepreserving = 1;
1287 		}
1288 		if (sfp != NULL) {
1289 			sfp->sf_ffiles = UINT64_MAX;
1290 			sfp->sf_tfiles = UINT64_MAX;
1291 			sfp->sf_afiles = UINT64_MAX;
1292 			sfp->sf_fbytes = UINT64_MAX;
1293 			sfp->sf_tbytes = UINT64_MAX;
1294 			sfp->sf_abytes = UINT64_MAX;
1295 		}
1296 	}
1297 
1298 	/*
1299 	 * Loop around getting the attributes.
1300 	 */
1301 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1302 	attrsize = fxdr_unsigned(int, *tl);
1303 	for (bitpos = 0; bitpos < NFSATTRBIT_MAX; bitpos++) {
1304 	    if (attrsum > attrsize) {
1305 		error = NFSERR_BADXDR;
1306 		goto nfsmout;
1307 	    }
1308 	    if (NFSISSET_ATTRBIT(&attrbits, bitpos))
1309 		switch (bitpos) {
1310 		case NFSATTRBIT_SUPPORTEDATTRS:
1311 			retnotsup = 0;
1312 			if (compare || nap == NULL)
1313 			    error = nfsrv_getattrbits(nd, &retattrbits,
1314 				&cnt, &retnotsup);
1315 			else
1316 			    error = nfsrv_getattrbits(nd, &nap->na_suppattr,
1317 				&cnt, &retnotsup);
1318 			if (error)
1319 			    goto nfsmout;
1320 			if (compare && !(*retcmpp)) {
1321 			   NFSSETSUPP_ATTRBIT(&checkattrbits, nd);
1322 
1323 			   /* Some filesystem do not support NFSv4ACL   */
1324 			   if (nfsrv_useacl == 0 || nfs_supportsnfsv4acls(vp) == 0) {
1325 				NFSCLRBIT_ATTRBIT(&checkattrbits, NFSATTRBIT_ACL);
1326 				NFSCLRBIT_ATTRBIT(&checkattrbits, NFSATTRBIT_ACLSUPPORT);
1327 		   	   }
1328 			   if (!NFSEQUAL_ATTRBIT(&retattrbits, &checkattrbits)
1329 			       || retnotsup)
1330 				*retcmpp = NFSERR_NOTSAME;
1331 			}
1332 			attrsum += cnt;
1333 			break;
1334 		case NFSATTRBIT_TYPE:
1335 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1336 			if (compare) {
1337 				if (!(*retcmpp)) {
1338 				    if (nap->na_type != nfsv34tov_type(*tl))
1339 					*retcmpp = NFSERR_NOTSAME;
1340 				}
1341 			} else if (nap != NULL) {
1342 				nap->na_type = nfsv34tov_type(*tl);
1343 			}
1344 			attrsum += NFSX_UNSIGNED;
1345 			break;
1346 		case NFSATTRBIT_FHEXPIRETYPE:
1347 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1348 			if (compare && !(*retcmpp)) {
1349 				if (fxdr_unsigned(int, *tl) !=
1350 					NFSV4FHTYPE_PERSISTENT)
1351 					*retcmpp = NFSERR_NOTSAME;
1352 			}
1353 			attrsum += NFSX_UNSIGNED;
1354 			break;
1355 		case NFSATTRBIT_CHANGE:
1356 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1357 			if (compare) {
1358 				if (!(*retcmpp)) {
1359 				    if (nap->na_filerev != fxdr_hyper(tl))
1360 					*retcmpp = NFSERR_NOTSAME;
1361 				}
1362 			} else if (nap != NULL) {
1363 				nap->na_filerev = fxdr_hyper(tl);
1364 			}
1365 			attrsum += NFSX_HYPER;
1366 			break;
1367 		case NFSATTRBIT_SIZE:
1368 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1369 			if (compare) {
1370 				if (!(*retcmpp)) {
1371 				    if (nap->na_size != fxdr_hyper(tl))
1372 					*retcmpp = NFSERR_NOTSAME;
1373 				}
1374 			} else if (nap != NULL) {
1375 				nap->na_size = fxdr_hyper(tl);
1376 			}
1377 			attrsum += NFSX_HYPER;
1378 			break;
1379 		case NFSATTRBIT_LINKSUPPORT:
1380 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1381 			if (compare) {
1382 				if (!(*retcmpp)) {
1383 				    if (fsp->fs_properties & NFSV3_FSFLINK) {
1384 					if (*tl == newnfs_false)
1385 						*retcmpp = NFSERR_NOTSAME;
1386 				    } else {
1387 					if (*tl == newnfs_true)
1388 						*retcmpp = NFSERR_NOTSAME;
1389 				    }
1390 				}
1391 			} else if (fsp != NULL) {
1392 				if (*tl == newnfs_true)
1393 					fsp->fs_properties |= NFSV3_FSFLINK;
1394 				else
1395 					fsp->fs_properties &= ~NFSV3_FSFLINK;
1396 			}
1397 			attrsum += NFSX_UNSIGNED;
1398 			break;
1399 		case NFSATTRBIT_SYMLINKSUPPORT:
1400 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1401 			if (compare) {
1402 				if (!(*retcmpp)) {
1403 				    if (fsp->fs_properties & NFSV3_FSFSYMLINK) {
1404 					if (*tl == newnfs_false)
1405 						*retcmpp = NFSERR_NOTSAME;
1406 				    } else {
1407 					if (*tl == newnfs_true)
1408 						*retcmpp = NFSERR_NOTSAME;
1409 				    }
1410 				}
1411 			} else if (fsp != NULL) {
1412 				if (*tl == newnfs_true)
1413 					fsp->fs_properties |= NFSV3_FSFSYMLINK;
1414 				else
1415 					fsp->fs_properties &= ~NFSV3_FSFSYMLINK;
1416 			}
1417 			attrsum += NFSX_UNSIGNED;
1418 			break;
1419 		case NFSATTRBIT_NAMEDATTR:
1420 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1421 			if (compare && !(*retcmpp)) {
1422 				if (*tl != newnfs_false)
1423 					*retcmpp = NFSERR_NOTSAME;
1424 			}
1425 			attrsum += NFSX_UNSIGNED;
1426 			break;
1427 		case NFSATTRBIT_FSID:
1428 			NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1429 			thyp = fxdr_hyper(tl);
1430 			tl += 2;
1431 			thyp2 = fxdr_hyper(tl);
1432 			if (compare) {
1433 			    if (*retcmpp == 0) {
1434 				if (thyp != (u_int64_t)
1435 				    vp->v_mount->mnt_stat.f_fsid.val[0] ||
1436 				    thyp2 != (u_int64_t)
1437 				    vp->v_mount->mnt_stat.f_fsid.val[1])
1438 					*retcmpp = NFSERR_NOTSAME;
1439 			    }
1440 			} else if (nap != NULL) {
1441 				nap->na_filesid[0] = thyp;
1442 				nap->na_filesid[1] = thyp2;
1443 			}
1444 			attrsum += (4 * NFSX_UNSIGNED);
1445 			break;
1446 		case NFSATTRBIT_UNIQUEHANDLES:
1447 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1448 			if (compare && !(*retcmpp)) {
1449 				if (*tl != newnfs_true)
1450 					*retcmpp = NFSERR_NOTSAME;
1451 			}
1452 			attrsum += NFSX_UNSIGNED;
1453 			break;
1454 		case NFSATTRBIT_LEASETIME:
1455 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1456 			if (compare) {
1457 				if (fxdr_unsigned(int, *tl) != nfsrv_lease &&
1458 				    !(*retcmpp))
1459 					*retcmpp = NFSERR_NOTSAME;
1460 			} else if (leasep != NULL) {
1461 				*leasep = fxdr_unsigned(u_int32_t, *tl);
1462 			}
1463 			attrsum += NFSX_UNSIGNED;
1464 			break;
1465 		case NFSATTRBIT_RDATTRERROR:
1466 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1467 			if (compare) {
1468 				 if (!(*retcmpp))
1469 					*retcmpp = NFSERR_INVAL;
1470 			} else if (rderrp != NULL) {
1471 				*rderrp = fxdr_unsigned(u_int32_t, *tl);
1472 			}
1473 			attrsum += NFSX_UNSIGNED;
1474 			break;
1475 		case NFSATTRBIT_ACL:
1476 			if (compare) {
1477 			  if (!(*retcmpp)) {
1478 			    if (nfsrv_useacl && nfs_supportsnfsv4acls(vp)) {
1479 				NFSACL_T *naclp;
1480 
1481 				naclp = acl_alloc(M_WAITOK);
1482 				error = nfsrv_dissectacl(nd, naclp, &aceerr,
1483 				    &cnt, p);
1484 				if (error) {
1485 				    acl_free(naclp);
1486 				    goto nfsmout;
1487 				}
1488 				if (aceerr || aclp == NULL ||
1489 				    nfsrv_compareacl(aclp, naclp))
1490 				    *retcmpp = NFSERR_NOTSAME;
1491 				acl_free(naclp);
1492 			    } else {
1493 				error = nfsrv_dissectacl(nd, NULL, &aceerr,
1494 				    &cnt, p);
1495 				*retcmpp = NFSERR_ATTRNOTSUPP;
1496 			    }
1497 			  }
1498 			} else {
1499 				if (vp != NULL && aclp != NULL)
1500 				    error = nfsrv_dissectacl(nd, aclp, &aceerr,
1501 					&cnt, p);
1502 				else
1503 				    error = nfsrv_dissectacl(nd, NULL, &aceerr,
1504 					&cnt, p);
1505 				if (error)
1506 				    goto nfsmout;
1507 			}
1508 
1509 			attrsum += cnt;
1510 			break;
1511 		case NFSATTRBIT_ACLSUPPORT:
1512 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1513 			if (compare && !(*retcmpp)) {
1514 				if (nfsrv_useacl && nfs_supportsnfsv4acls(vp)) {
1515 					if (fxdr_unsigned(u_int32_t, *tl) !=
1516 					    NFSV4ACE_SUPTYPES)
1517 						*retcmpp = NFSERR_NOTSAME;
1518 				} else {
1519 					*retcmpp = NFSERR_ATTRNOTSUPP;
1520 				}
1521 			}
1522 			attrsum += NFSX_UNSIGNED;
1523 			break;
1524 		case NFSATTRBIT_ARCHIVE:
1525 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1526 			if (compare && !(*retcmpp))
1527 				*retcmpp = NFSERR_ATTRNOTSUPP;
1528 			attrsum += NFSX_UNSIGNED;
1529 			break;
1530 		case NFSATTRBIT_CANSETTIME:
1531 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1532 			if (compare) {
1533 				if (!(*retcmpp)) {
1534 				    if (fsp->fs_properties & NFSV3_FSFCANSETTIME) {
1535 					if (*tl == newnfs_false)
1536 						*retcmpp = NFSERR_NOTSAME;
1537 				    } else {
1538 					if (*tl == newnfs_true)
1539 						*retcmpp = NFSERR_NOTSAME;
1540 				    }
1541 				}
1542 			} else if (fsp != NULL) {
1543 				if (*tl == newnfs_true)
1544 					fsp->fs_properties |= NFSV3_FSFCANSETTIME;
1545 				else
1546 					fsp->fs_properties &= ~NFSV3_FSFCANSETTIME;
1547 			}
1548 			attrsum += NFSX_UNSIGNED;
1549 			break;
1550 		case NFSATTRBIT_CASEINSENSITIVE:
1551 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1552 			if (compare) {
1553 				if (!(*retcmpp)) {
1554 				    if (*tl != newnfs_false)
1555 					*retcmpp = NFSERR_NOTSAME;
1556 				}
1557 			} else if (pc != NULL) {
1558 				pc->pc_caseinsensitive =
1559 				    fxdr_unsigned(u_int32_t, *tl);
1560 			}
1561 			attrsum += NFSX_UNSIGNED;
1562 			break;
1563 		case NFSATTRBIT_CASEPRESERVING:
1564 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1565 			if (compare) {
1566 				if (!(*retcmpp)) {
1567 				    if (*tl != newnfs_true)
1568 					*retcmpp = NFSERR_NOTSAME;
1569 				}
1570 			} else if (pc != NULL) {
1571 				pc->pc_casepreserving =
1572 				    fxdr_unsigned(u_int32_t, *tl);
1573 			}
1574 			attrsum += NFSX_UNSIGNED;
1575 			break;
1576 		case NFSATTRBIT_CHOWNRESTRICTED:
1577 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1578 			if (compare) {
1579 				if (!(*retcmpp)) {
1580 				    if (*tl != newnfs_true)
1581 					*retcmpp = NFSERR_NOTSAME;
1582 				}
1583 			} else if (pc != NULL) {
1584 				pc->pc_chownrestricted =
1585 				    fxdr_unsigned(u_int32_t, *tl);
1586 			}
1587 			attrsum += NFSX_UNSIGNED;
1588 			break;
1589 		case NFSATTRBIT_FILEHANDLE:
1590 			error = nfsm_getfh(nd, &tnfhp);
1591 			if (error)
1592 				goto nfsmout;
1593 			tfhsize = tnfhp->nfh_len;
1594 			if (compare) {
1595 				if (!(*retcmpp) &&
1596 				    !NFSRV_CMPFH(tnfhp->nfh_fh, tfhsize,
1597 				     fhp, fhsize))
1598 					*retcmpp = NFSERR_NOTSAME;
1599 				free(tnfhp, M_NFSFH);
1600 			} else if (nfhpp != NULL) {
1601 				*nfhpp = tnfhp;
1602 			} else {
1603 				free(tnfhp, M_NFSFH);
1604 			}
1605 			attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(tfhsize));
1606 			break;
1607 		case NFSATTRBIT_FILEID:
1608 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1609 			thyp = fxdr_hyper(tl);
1610 			if (compare) {
1611 				if (!(*retcmpp)) {
1612 					if (nap->na_fileid != thyp)
1613 						*retcmpp = NFSERR_NOTSAME;
1614 				}
1615 			} else if (nap != NULL)
1616 				nap->na_fileid = thyp;
1617 			attrsum += NFSX_HYPER;
1618 			break;
1619 		case NFSATTRBIT_FILESAVAIL:
1620 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1621 			if (compare) {
1622 				if (!(*retcmpp) &&
1623 				    sfp->sf_afiles != fxdr_hyper(tl))
1624 					*retcmpp = NFSERR_NOTSAME;
1625 			} else if (sfp != NULL) {
1626 				sfp->sf_afiles = fxdr_hyper(tl);
1627 			}
1628 			attrsum += NFSX_HYPER;
1629 			break;
1630 		case NFSATTRBIT_FILESFREE:
1631 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1632 			if (compare) {
1633 				if (!(*retcmpp) &&
1634 				    sfp->sf_ffiles != fxdr_hyper(tl))
1635 					*retcmpp = NFSERR_NOTSAME;
1636 			} else if (sfp != NULL) {
1637 				sfp->sf_ffiles = fxdr_hyper(tl);
1638 			}
1639 			attrsum += NFSX_HYPER;
1640 			break;
1641 		case NFSATTRBIT_FILESTOTAL:
1642 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1643 			if (compare) {
1644 				if (!(*retcmpp) &&
1645 				    sfp->sf_tfiles != fxdr_hyper(tl))
1646 					*retcmpp = NFSERR_NOTSAME;
1647 			} else if (sfp != NULL) {
1648 				sfp->sf_tfiles = fxdr_hyper(tl);
1649 			}
1650 			attrsum += NFSX_HYPER;
1651 			break;
1652 		case NFSATTRBIT_FSLOCATIONS:
1653 			error = nfsrv_getrefstr(nd, &cp, &cp2, &l, &m);
1654 			if (error)
1655 				goto nfsmout;
1656 			attrsum += l;
1657 			if (compare && !(*retcmpp)) {
1658 				refp = nfsv4root_getreferral(vp, NULL, 0);
1659 				if (refp != NULL) {
1660 					if (cp == NULL || cp2 == NULL ||
1661 					    strcmp(cp, "/") ||
1662 					    strcmp(cp2, refp->nfr_srvlist))
1663 						*retcmpp = NFSERR_NOTSAME;
1664 				} else if (m == 0) {
1665 					*retcmpp = NFSERR_NOTSAME;
1666 				}
1667 			}
1668 			if (cp != NULL)
1669 				free(cp, M_NFSSTRING);
1670 			if (cp2 != NULL)
1671 				free(cp2, M_NFSSTRING);
1672 			break;
1673 		case NFSATTRBIT_HIDDEN:
1674 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1675 			if (compare && !(*retcmpp))
1676 				*retcmpp = NFSERR_ATTRNOTSUPP;
1677 			attrsum += NFSX_UNSIGNED;
1678 			break;
1679 		case NFSATTRBIT_HOMOGENEOUS:
1680 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1681 			if (compare) {
1682 				if (!(*retcmpp)) {
1683 				    if (fsp->fs_properties &
1684 					NFSV3_FSFHOMOGENEOUS) {
1685 					if (*tl == newnfs_false)
1686 						*retcmpp = NFSERR_NOTSAME;
1687 				    } else {
1688 					if (*tl == newnfs_true)
1689 						*retcmpp = NFSERR_NOTSAME;
1690 				    }
1691 				}
1692 			} else if (fsp != NULL) {
1693 				if (*tl == newnfs_true)
1694 				    fsp->fs_properties |= NFSV3_FSFHOMOGENEOUS;
1695 				else
1696 				    fsp->fs_properties &= ~NFSV3_FSFHOMOGENEOUS;
1697 			}
1698 			attrsum += NFSX_UNSIGNED;
1699 			break;
1700 		case NFSATTRBIT_MAXFILESIZE:
1701 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1702 			tnfsquad.qval = fxdr_hyper(tl);
1703 			if (compare) {
1704 				if (!(*retcmpp)) {
1705 					tquad = NFSRV_MAXFILESIZE;
1706 					if (tquad != tnfsquad.qval)
1707 						*retcmpp = NFSERR_NOTSAME;
1708 				}
1709 			} else if (fsp != NULL) {
1710 				fsp->fs_maxfilesize = tnfsquad.qval;
1711 			}
1712 			attrsum += NFSX_HYPER;
1713 			break;
1714 		case NFSATTRBIT_MAXLINK:
1715 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1716 			if (compare) {
1717 				if (!(*retcmpp)) {
1718 				    if (fxdr_unsigned(int, *tl) != NFS_LINK_MAX)
1719 					*retcmpp = NFSERR_NOTSAME;
1720 				}
1721 			} else if (pc != NULL) {
1722 				pc->pc_linkmax = fxdr_unsigned(u_int32_t, *tl);
1723 			}
1724 			attrsum += NFSX_UNSIGNED;
1725 			break;
1726 		case NFSATTRBIT_MAXNAME:
1727 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1728 			if (compare) {
1729 				if (!(*retcmpp)) {
1730 				    if (fsp->fs_maxname !=
1731 					fxdr_unsigned(u_int32_t, *tl))
1732 						*retcmpp = NFSERR_NOTSAME;
1733 				}
1734 			} else {
1735 				tuint = fxdr_unsigned(u_int32_t, *tl);
1736 				/*
1737 				 * Some Linux NFSv4 servers report this
1738 				 * as 0 or 4billion, so I'll set it to
1739 				 * NFS_MAXNAMLEN. If a server actually creates
1740 				 * a name longer than NFS_MAXNAMLEN, it will
1741 				 * get an error back.
1742 				 */
1743 				if (tuint == 0 || tuint > NFS_MAXNAMLEN)
1744 					tuint = NFS_MAXNAMLEN;
1745 				if (fsp != NULL)
1746 					fsp->fs_maxname = tuint;
1747 				if (pc != NULL)
1748 					pc->pc_namemax = tuint;
1749 			}
1750 			attrsum += NFSX_UNSIGNED;
1751 			break;
1752 		case NFSATTRBIT_MAXREAD:
1753 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1754 			if (compare) {
1755 				if (!(*retcmpp)) {
1756 				    if (fsp->fs_rtmax != fxdr_unsigned(u_int32_t,
1757 					*(tl + 1)) || *tl != 0)
1758 					*retcmpp = NFSERR_NOTSAME;
1759 				}
1760 			} else if (fsp != NULL) {
1761 				fsp->fs_rtmax = fxdr_unsigned(u_int32_t, *++tl);
1762 				fsp->fs_rtpref = fsp->fs_rtmax;
1763 				fsp->fs_dtpref = fsp->fs_rtpref;
1764 			}
1765 			attrsum += NFSX_HYPER;
1766 			break;
1767 		case NFSATTRBIT_MAXWRITE:
1768 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1769 			if (compare) {
1770 				if (!(*retcmpp)) {
1771 				    if (fsp->fs_wtmax != fxdr_unsigned(u_int32_t,
1772 					*(tl + 1)) || *tl != 0)
1773 					*retcmpp = NFSERR_NOTSAME;
1774 				}
1775 			} else if (fsp != NULL) {
1776 				fsp->fs_wtmax = fxdr_unsigned(int, *++tl);
1777 				fsp->fs_wtpref = fsp->fs_wtmax;
1778 			}
1779 			attrsum += NFSX_HYPER;
1780 			break;
1781 		case NFSATTRBIT_MIMETYPE:
1782 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1783 			i = fxdr_unsigned(int, *tl);
1784 			attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(i));
1785 			error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
1786 			if (error)
1787 				goto nfsmout;
1788 			if (compare && !(*retcmpp))
1789 				*retcmpp = NFSERR_ATTRNOTSUPP;
1790 			break;
1791 		case NFSATTRBIT_MODE:
1792 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1793 			if (compare) {
1794 				if (!(*retcmpp)) {
1795 				    if (nap->na_mode != nfstov_mode(*tl))
1796 					*retcmpp = NFSERR_NOTSAME;
1797 				}
1798 			} else if (nap != NULL) {
1799 				nap->na_mode = nfstov_mode(*tl);
1800 			}
1801 			attrsum += NFSX_UNSIGNED;
1802 			break;
1803 		case NFSATTRBIT_NOTRUNC:
1804 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1805 			if (compare) {
1806 				if (!(*retcmpp)) {
1807 				    if (*tl != newnfs_true)
1808 					*retcmpp = NFSERR_NOTSAME;
1809 				}
1810 			} else if (pc != NULL) {
1811 				pc->pc_notrunc = fxdr_unsigned(u_int32_t, *tl);
1812 			}
1813 			attrsum += NFSX_UNSIGNED;
1814 			break;
1815 		case NFSATTRBIT_NUMLINKS:
1816 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1817 			tuint = fxdr_unsigned(u_int32_t, *tl);
1818 			if (compare) {
1819 			    if (!(*retcmpp)) {
1820 				if ((u_int32_t)nap->na_nlink != tuint)
1821 					*retcmpp = NFSERR_NOTSAME;
1822 			    }
1823 			} else if (nap != NULL) {
1824 				nap->na_nlink = tuint;
1825 			}
1826 			attrsum += NFSX_UNSIGNED;
1827 			break;
1828 		case NFSATTRBIT_OWNER:
1829 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1830 			j = fxdr_unsigned(int, *tl);
1831 			if (j < 0) {
1832 				error = NFSERR_BADXDR;
1833 				goto nfsmout;
1834 			}
1835 			attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(j));
1836 			if (j > NFSV4_SMALLSTR)
1837 				cp = malloc(j + 1, M_NFSSTRING, M_WAITOK);
1838 			else
1839 				cp = namestr;
1840 			error = nfsrv_mtostr(nd, cp, j);
1841 			if (error) {
1842 				if (j > NFSV4_SMALLSTR)
1843 					free(cp, M_NFSSTRING);
1844 				goto nfsmout;
1845 			}
1846 			if (compare) {
1847 			    if (!(*retcmpp)) {
1848 				if (nfsv4_strtouid(nd, cp, j, &uid) ||
1849 				    nap->na_uid != uid)
1850 				    *retcmpp = NFSERR_NOTSAME;
1851 			    }
1852 			} else if (nap != NULL) {
1853 				if (nfsv4_strtouid(nd, cp, j, &uid))
1854 					nap->na_uid = nfsrv_defaultuid;
1855 				else
1856 					nap->na_uid = uid;
1857 			}
1858 			if (j > NFSV4_SMALLSTR)
1859 				free(cp, M_NFSSTRING);
1860 			break;
1861 		case NFSATTRBIT_OWNERGROUP:
1862 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1863 			j = fxdr_unsigned(int, *tl);
1864 			if (j < 0) {
1865 				error =  NFSERR_BADXDR;
1866 				goto nfsmout;
1867 			}
1868 			attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(j));
1869 			if (j > NFSV4_SMALLSTR)
1870 				cp = malloc(j + 1, M_NFSSTRING, M_WAITOK);
1871 			else
1872 				cp = namestr;
1873 			error = nfsrv_mtostr(nd, cp, j);
1874 			if (error) {
1875 				if (j > NFSV4_SMALLSTR)
1876 					free(cp, M_NFSSTRING);
1877 				goto nfsmout;
1878 			}
1879 			if (compare) {
1880 			    if (!(*retcmpp)) {
1881 				if (nfsv4_strtogid(nd, cp, j, &gid) ||
1882 				    nap->na_gid != gid)
1883 				    *retcmpp = NFSERR_NOTSAME;
1884 			    }
1885 			} else if (nap != NULL) {
1886 				if (nfsv4_strtogid(nd, cp, j, &gid))
1887 					nap->na_gid = nfsrv_defaultgid;
1888 				else
1889 					nap->na_gid = gid;
1890 			}
1891 			if (j > NFSV4_SMALLSTR)
1892 				free(cp, M_NFSSTRING);
1893 			break;
1894 		case NFSATTRBIT_QUOTAHARD:
1895 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1896 			if (sbp != NULL) {
1897 			    if (priv_check_cred(cred, PRIV_VFS_EXCEEDQUOTA))
1898 				freenum = sbp->f_bfree;
1899 			    else
1900 				freenum = sbp->f_bavail;
1901 #ifdef QUOTA
1902 			    /*
1903 			     * ufs_quotactl() insists that the uid argument
1904 			     * equal p_ruid for non-root quota access, so
1905 			     * we'll just make sure that's the case.
1906 			     */
1907 			    savuid = p->p_cred->p_ruid;
1908 			    p->p_cred->p_ruid = cred->cr_uid;
1909 			    if (!VFS_QUOTACTL(vp->v_mount,QCMD(Q_GETQUOTA,
1910 				USRQUOTA), cred->cr_uid, &dqb))
1911 				freenum = min(dqb.dqb_bhardlimit, freenum);
1912 			    p->p_cred->p_ruid = savuid;
1913 #endif	/* QUOTA */
1914 			    uquad = (u_int64_t)freenum;
1915 			    NFSQUOTABLKTOBYTE(uquad, sbp->f_bsize);
1916 			}
1917 			if (compare && !(*retcmpp)) {
1918 				if (uquad != fxdr_hyper(tl))
1919 					*retcmpp = NFSERR_NOTSAME;
1920 			}
1921 			attrsum += NFSX_HYPER;
1922 			break;
1923 		case NFSATTRBIT_QUOTASOFT:
1924 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1925 			if (sbp != NULL) {
1926 			    if (priv_check_cred(cred, PRIV_VFS_EXCEEDQUOTA))
1927 				freenum = sbp->f_bfree;
1928 			    else
1929 				freenum = sbp->f_bavail;
1930 #ifdef QUOTA
1931 			    /*
1932 			     * ufs_quotactl() insists that the uid argument
1933 			     * equal p_ruid for non-root quota access, so
1934 			     * we'll just make sure that's the case.
1935 			     */
1936 			    savuid = p->p_cred->p_ruid;
1937 			    p->p_cred->p_ruid = cred->cr_uid;
1938 			    if (!VFS_QUOTACTL(vp->v_mount,QCMD(Q_GETQUOTA,
1939 				USRQUOTA), cred->cr_uid, &dqb))
1940 				freenum = min(dqb.dqb_bsoftlimit, freenum);
1941 			    p->p_cred->p_ruid = savuid;
1942 #endif	/* QUOTA */
1943 			    uquad = (u_int64_t)freenum;
1944 			    NFSQUOTABLKTOBYTE(uquad, sbp->f_bsize);
1945 			}
1946 			if (compare && !(*retcmpp)) {
1947 				if (uquad != fxdr_hyper(tl))
1948 					*retcmpp = NFSERR_NOTSAME;
1949 			}
1950 			attrsum += NFSX_HYPER;
1951 			break;
1952 		case NFSATTRBIT_QUOTAUSED:
1953 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1954 			if (sbp != NULL) {
1955 			    freenum = 0;
1956 #ifdef QUOTA
1957 			    /*
1958 			     * ufs_quotactl() insists that the uid argument
1959 			     * equal p_ruid for non-root quota access, so
1960 			     * we'll just make sure that's the case.
1961 			     */
1962 			    savuid = p->p_cred->p_ruid;
1963 			    p->p_cred->p_ruid = cred->cr_uid;
1964 			    if (!VFS_QUOTACTL(vp->v_mount,QCMD(Q_GETQUOTA,
1965 				USRQUOTA), cred->cr_uid, &dqb))
1966 				freenum = dqb.dqb_curblocks;
1967 			    p->p_cred->p_ruid = savuid;
1968 #endif	/* QUOTA */
1969 			    uquad = (u_int64_t)freenum;
1970 			    NFSQUOTABLKTOBYTE(uquad, sbp->f_bsize);
1971 			}
1972 			if (compare && !(*retcmpp)) {
1973 				if (uquad != fxdr_hyper(tl))
1974 					*retcmpp = NFSERR_NOTSAME;
1975 			}
1976 			attrsum += NFSX_HYPER;
1977 			break;
1978 		case NFSATTRBIT_RAWDEV:
1979 			NFSM_DISSECT(tl, u_int32_t *, NFSX_V4SPECDATA);
1980 			j = fxdr_unsigned(int, *tl++);
1981 			k = fxdr_unsigned(int, *tl);
1982 			if (compare) {
1983 			    if (!(*retcmpp)) {
1984 				if (nap->na_rdev != NFSMAKEDEV(j, k))
1985 					*retcmpp = NFSERR_NOTSAME;
1986 			    }
1987 			} else if (nap != NULL) {
1988 				nap->na_rdev = NFSMAKEDEV(j, k);
1989 			}
1990 			attrsum += NFSX_V4SPECDATA;
1991 			break;
1992 		case NFSATTRBIT_SPACEAVAIL:
1993 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1994 			if (compare) {
1995 				if (!(*retcmpp) &&
1996 				    sfp->sf_abytes != fxdr_hyper(tl))
1997 					*retcmpp = NFSERR_NOTSAME;
1998 			} else if (sfp != NULL) {
1999 				sfp->sf_abytes = fxdr_hyper(tl);
2000 			}
2001 			attrsum += NFSX_HYPER;
2002 			break;
2003 		case NFSATTRBIT_SPACEFREE:
2004 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
2005 			if (compare) {
2006 				if (!(*retcmpp) &&
2007 				    sfp->sf_fbytes != fxdr_hyper(tl))
2008 					*retcmpp = NFSERR_NOTSAME;
2009 			} else if (sfp != NULL) {
2010 				sfp->sf_fbytes = fxdr_hyper(tl);
2011 			}
2012 			attrsum += NFSX_HYPER;
2013 			break;
2014 		case NFSATTRBIT_SPACETOTAL:
2015 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
2016 			if (compare) {
2017 				if (!(*retcmpp) &&
2018 				    sfp->sf_tbytes != fxdr_hyper(tl))
2019 					*retcmpp = NFSERR_NOTSAME;
2020 			} else if (sfp != NULL) {
2021 				sfp->sf_tbytes = fxdr_hyper(tl);
2022 			}
2023 			attrsum += NFSX_HYPER;
2024 			break;
2025 		case NFSATTRBIT_SPACEUSED:
2026 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
2027 			thyp = fxdr_hyper(tl);
2028 			if (compare) {
2029 			    if (!(*retcmpp)) {
2030 				if ((u_int64_t)nap->na_bytes != thyp)
2031 					*retcmpp = NFSERR_NOTSAME;
2032 			    }
2033 			} else if (nap != NULL) {
2034 				nap->na_bytes = thyp;
2035 			}
2036 			attrsum += NFSX_HYPER;
2037 			break;
2038 		case NFSATTRBIT_SYSTEM:
2039 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2040 			if (compare && !(*retcmpp))
2041 				*retcmpp = NFSERR_ATTRNOTSUPP;
2042 			attrsum += NFSX_UNSIGNED;
2043 			break;
2044 		case NFSATTRBIT_TIMEACCESS:
2045 			NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
2046 			fxdr_nfsv4time(tl, &temptime);
2047 			if (compare) {
2048 			    if (!(*retcmpp)) {
2049 				if (!NFS_CMPTIME(temptime, nap->na_atime))
2050 					*retcmpp = NFSERR_NOTSAME;
2051 			    }
2052 			} else if (nap != NULL) {
2053 				nap->na_atime = temptime;
2054 			}
2055 			attrsum += NFSX_V4TIME;
2056 			break;
2057 		case NFSATTRBIT_TIMEACCESSSET:
2058 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2059 			attrsum += NFSX_UNSIGNED;
2060 			i = fxdr_unsigned(int, *tl);
2061 			if (i == NFSV4SATTRTIME_TOCLIENT) {
2062 				NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
2063 				attrsum += NFSX_V4TIME;
2064 			}
2065 			if (compare && !(*retcmpp))
2066 				*retcmpp = NFSERR_INVAL;
2067 			break;
2068 		case NFSATTRBIT_TIMEBACKUP:
2069 			NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
2070 			if (compare && !(*retcmpp))
2071 				*retcmpp = NFSERR_ATTRNOTSUPP;
2072 			attrsum += NFSX_V4TIME;
2073 			break;
2074 		case NFSATTRBIT_TIMECREATE:
2075 			NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
2076 			fxdr_nfsv4time(tl, &temptime);
2077 			if (compare) {
2078 			    if (!(*retcmpp)) {
2079 				if (!NFS_CMPTIME(temptime, nap->na_btime))
2080 					*retcmpp = NFSERR_NOTSAME;
2081 			    }
2082 			} else if (nap != NULL) {
2083 				nap->na_btime = temptime;
2084 			}
2085 			attrsum += NFSX_V4TIME;
2086 			break;
2087 		case NFSATTRBIT_TIMEDELTA:
2088 			NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
2089 			if (fsp != NULL) {
2090 			    if (compare) {
2091 				if (!(*retcmpp)) {
2092 				    if ((u_int32_t)fsp->fs_timedelta.tv_sec !=
2093 					fxdr_unsigned(u_int32_t, *(tl + 1)) ||
2094 				        (u_int32_t)fsp->fs_timedelta.tv_nsec !=
2095 					(fxdr_unsigned(u_int32_t, *(tl + 2)) %
2096 					 1000000000) ||
2097 					*tl != 0)
2098 					    *retcmpp = NFSERR_NOTSAME;
2099 				}
2100 			    } else {
2101 				fxdr_nfsv4time(tl, &fsp->fs_timedelta);
2102 			    }
2103 			}
2104 			attrsum += NFSX_V4TIME;
2105 			break;
2106 		case NFSATTRBIT_TIMEMETADATA:
2107 			NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
2108 			fxdr_nfsv4time(tl, &temptime);
2109 			if (compare) {
2110 			    if (!(*retcmpp)) {
2111 				if (!NFS_CMPTIME(temptime, nap->na_ctime))
2112 					*retcmpp = NFSERR_NOTSAME;
2113 			    }
2114 			} else if (nap != NULL) {
2115 				nap->na_ctime = temptime;
2116 			}
2117 			attrsum += NFSX_V4TIME;
2118 			break;
2119 		case NFSATTRBIT_TIMEMODIFY:
2120 			NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
2121 			fxdr_nfsv4time(tl, &temptime);
2122 			if (compare) {
2123 			    if (!(*retcmpp)) {
2124 				if (!NFS_CMPTIME(temptime, nap->na_mtime))
2125 					*retcmpp = NFSERR_NOTSAME;
2126 			    }
2127 			} else if (nap != NULL) {
2128 				nap->na_mtime = temptime;
2129 			}
2130 			attrsum += NFSX_V4TIME;
2131 			break;
2132 		case NFSATTRBIT_TIMEMODIFYSET:
2133 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2134 			attrsum += NFSX_UNSIGNED;
2135 			i = fxdr_unsigned(int, *tl);
2136 			if (i == NFSV4SATTRTIME_TOCLIENT) {
2137 				NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
2138 				attrsum += NFSX_V4TIME;
2139 			}
2140 			if (compare && !(*retcmpp))
2141 				*retcmpp = NFSERR_INVAL;
2142 			break;
2143 		case NFSATTRBIT_MOUNTEDONFILEID:
2144 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
2145 			thyp = fxdr_hyper(tl);
2146 			if (compare) {
2147 				if (!(*retcmpp)) {
2148 					if (!vp || !nfsrv_atroot(vp, &thyp2))
2149 						thyp2 = nap->na_fileid;
2150 					if (thyp2 != thyp)
2151 						*retcmpp = NFSERR_NOTSAME;
2152 				}
2153 			} else if (nap != NULL)
2154 				nap->na_mntonfileno = thyp;
2155 			attrsum += NFSX_HYPER;
2156 			break;
2157 		case NFSATTRBIT_SUPPATTREXCLCREAT:
2158 			retnotsup = 0;
2159 			error = nfsrv_getattrbits(nd, &retattrbits,
2160 			    &cnt, &retnotsup);
2161 			if (error)
2162 			    goto nfsmout;
2163 			if (compare && !(*retcmpp)) {
2164 			   NFSSETSUPP_ATTRBIT(&checkattrbits, nd);
2165 			   NFSCLRNOTSETABLE_ATTRBIT(&checkattrbits, nd);
2166 			   NFSCLRBIT_ATTRBIT(&checkattrbits,
2167 				NFSATTRBIT_TIMEACCESSSET);
2168 			   if (!NFSEQUAL_ATTRBIT(&retattrbits, &checkattrbits)
2169 			       || retnotsup)
2170 				*retcmpp = NFSERR_NOTSAME;
2171 			}
2172 			attrsum += cnt;
2173 			break;
2174 		case NFSATTRBIT_FSLAYOUTTYPE:
2175 		case NFSATTRBIT_LAYOUTTYPE:
2176 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2177 			attrsum += NFSX_UNSIGNED;
2178 			i = fxdr_unsigned(int, *tl);
2179 			if (i > 0) {
2180 				NFSM_DISSECT(tl, u_int32_t *, i *
2181 				    NFSX_UNSIGNED);
2182 				attrsum += i * NFSX_UNSIGNED;
2183 				j = fxdr_unsigned(int, *tl);
2184 				if (i == 1 && compare && !(*retcmpp) &&
2185 				    (((nfsrv_doflexfile != 0 ||
2186 				       nfsrv_maxpnfsmirror > 1) &&
2187 				      j != NFSLAYOUT_FLEXFILE) ||
2188 				    (nfsrv_doflexfile == 0 &&
2189 				     j != NFSLAYOUT_NFSV4_1_FILES)))
2190 					*retcmpp = NFSERR_NOTSAME;
2191 			}
2192 			if (nfsrv_devidcnt == 0) {
2193 				if (compare && !(*retcmpp) && i > 0)
2194 					*retcmpp = NFSERR_NOTSAME;
2195 			} else {
2196 				if (compare && !(*retcmpp) && i != 1)
2197 					*retcmpp = NFSERR_NOTSAME;
2198 			}
2199 			break;
2200 		case NFSATTRBIT_LAYOUTALIGNMENT:
2201 		case NFSATTRBIT_LAYOUTBLKSIZE:
2202 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2203 			attrsum += NFSX_UNSIGNED;
2204 			i = fxdr_unsigned(int, *tl);
2205 			if (compare && !(*retcmpp) && i != nfs_srvmaxio)
2206 				*retcmpp = NFSERR_NOTSAME;
2207 			break;
2208 		default:
2209 			printf("EEK! nfsv4_loadattr unknown attr=%d\n",
2210 				bitpos);
2211 			if (compare && !(*retcmpp))
2212 				*retcmpp = NFSERR_ATTRNOTSUPP;
2213 			/*
2214 			 * and get out of the loop, since we can't parse
2215 			 * the unknown attrbute data.
2216 			 */
2217 			bitpos = NFSATTRBIT_MAX;
2218 			break;
2219 		}
2220 	}
2221 
2222 	/*
2223 	 * some clients pad the attrlist, so we need to skip over the
2224 	 * padding.
2225 	 */
2226 	if (attrsum > attrsize) {
2227 		error = NFSERR_BADXDR;
2228 	} else {
2229 		attrsize = NFSM_RNDUP(attrsize);
2230 		if (attrsum < attrsize)
2231 			error = nfsm_advance(nd, attrsize - attrsum, -1);
2232 	}
2233 nfsmout:
2234 	NFSEXITCODE2(error, nd);
2235 	return (error);
2236 }
2237 
2238 /*
2239  * Implement sleep locks for newnfs. The nfslock_usecnt allows for a
2240  * shared lock and the NFSXXX_LOCK flag permits an exclusive lock.
2241  * The first argument is a pointer to an nfsv4lock structure.
2242  * The second argument is 1 iff a blocking lock is wanted.
2243  * If this argument is 0, the call waits until no thread either wants nor
2244  * holds an exclusive lock.
2245  * It returns 1 if the lock was acquired, 0 otherwise.
2246  * If several processes call this function concurrently wanting the exclusive
2247  * lock, one will get the lock and the rest will return without getting the
2248  * lock. (If the caller must have the lock, it simply calls this function in a
2249  *  loop until the function returns 1 to indicate the lock was acquired.)
2250  * Any usecnt must be decremented by calling nfsv4_relref() before
2251  * calling nfsv4_lock(). It was done this way, so nfsv4_lock() could
2252  * be called in a loop.
2253  * The isleptp argument is set to indicate if the call slept, iff not NULL
2254  * and the mp argument indicates to check for a forced dismount, iff not
2255  * NULL.
2256  */
2257 int
2258 nfsv4_lock(struct nfsv4lock *lp, int iwantlock, int *isleptp,
2259     struct mtx *mutex, struct mount *mp)
2260 {
2261 
2262 	if (isleptp)
2263 		*isleptp = 0;
2264 	/*
2265 	 * If a lock is wanted, loop around until the lock is acquired by
2266 	 * someone and then released. If I want the lock, try to acquire it.
2267 	 * For a lock to be issued, no lock must be in force and the usecnt
2268 	 * must be zero.
2269 	 */
2270 	if (iwantlock) {
2271 	    if (!(lp->nfslock_lock & NFSV4LOCK_LOCK) &&
2272 		lp->nfslock_usecnt == 0) {
2273 		lp->nfslock_lock &= ~NFSV4LOCK_LOCKWANTED;
2274 		lp->nfslock_lock |= NFSV4LOCK_LOCK;
2275 		return (1);
2276 	    }
2277 	    lp->nfslock_lock |= NFSV4LOCK_LOCKWANTED;
2278 	}
2279 	while (lp->nfslock_lock & (NFSV4LOCK_LOCK | NFSV4LOCK_LOCKWANTED)) {
2280 		if (mp != NULL && NFSCL_FORCEDISM(mp)) {
2281 			lp->nfslock_lock &= ~NFSV4LOCK_LOCKWANTED;
2282 			return (0);
2283 		}
2284 		lp->nfslock_lock |= NFSV4LOCK_WANTED;
2285 		if (isleptp)
2286 			*isleptp = 1;
2287 		msleep(&lp->nfslock_lock, mutex, PVFS, "nfsv4lck", hz);
2288 		if (iwantlock && !(lp->nfslock_lock & NFSV4LOCK_LOCK) &&
2289 		    lp->nfslock_usecnt == 0) {
2290 			lp->nfslock_lock &= ~NFSV4LOCK_LOCKWANTED;
2291 			lp->nfslock_lock |= NFSV4LOCK_LOCK;
2292 			return (1);
2293 		}
2294 	}
2295 	return (0);
2296 }
2297 
2298 /*
2299  * Release the lock acquired by nfsv4_lock().
2300  * The second argument is set to 1 to indicate the nfslock_usecnt should be
2301  * incremented, as well.
2302  */
2303 void
2304 nfsv4_unlock(struct nfsv4lock *lp, int incref)
2305 {
2306 
2307 	lp->nfslock_lock &= ~NFSV4LOCK_LOCK;
2308 	if (incref)
2309 		lp->nfslock_usecnt++;
2310 	nfsv4_wanted(lp);
2311 }
2312 
2313 /*
2314  * Release a reference cnt.
2315  */
2316 void
2317 nfsv4_relref(struct nfsv4lock *lp)
2318 {
2319 
2320 	if (lp->nfslock_usecnt <= 0)
2321 		panic("nfsv4root ref cnt");
2322 	lp->nfslock_usecnt--;
2323 	if (lp->nfslock_usecnt == 0)
2324 		nfsv4_wanted(lp);
2325 }
2326 
2327 /*
2328  * Get a reference cnt.
2329  * This function will wait for any exclusive lock to be released, but will
2330  * not wait for threads that want the exclusive lock. If priority needs
2331  * to be given to threads that need the exclusive lock, a call to nfsv4_lock()
2332  * with the 2nd argument == 0 should be done before calling nfsv4_getref().
2333  * If the mp argument is not NULL, check for NFSCL_FORCEDISM() being set and
2334  * return without getting a refcnt for that case.
2335  */
2336 void
2337 nfsv4_getref(struct nfsv4lock *lp, int *isleptp, struct mtx *mutex,
2338     struct mount *mp)
2339 {
2340 
2341 	if (isleptp)
2342 		*isleptp = 0;
2343 
2344 	/*
2345 	 * Wait for a lock held.
2346 	 */
2347 	while (lp->nfslock_lock & NFSV4LOCK_LOCK) {
2348 		if (mp != NULL && NFSCL_FORCEDISM(mp))
2349 			return;
2350 		lp->nfslock_lock |= NFSV4LOCK_WANTED;
2351 		if (isleptp)
2352 			*isleptp = 1;
2353 		msleep(&lp->nfslock_lock, mutex, PVFS, "nfsv4gr", hz);
2354 	}
2355 	if (mp != NULL && NFSCL_FORCEDISM(mp))
2356 		return;
2357 
2358 	lp->nfslock_usecnt++;
2359 }
2360 
2361 /*
2362  * Get a reference as above, but return failure instead of sleeping if
2363  * an exclusive lock is held.
2364  */
2365 int
2366 nfsv4_getref_nonblock(struct nfsv4lock *lp)
2367 {
2368 
2369 	if ((lp->nfslock_lock & NFSV4LOCK_LOCK) != 0)
2370 		return (0);
2371 
2372 	lp->nfslock_usecnt++;
2373 	return (1);
2374 }
2375 
2376 /*
2377  * Test for a lock. Return 1 if locked, 0 otherwise.
2378  */
2379 int
2380 nfsv4_testlock(struct nfsv4lock *lp)
2381 {
2382 
2383 	if ((lp->nfslock_lock & NFSV4LOCK_LOCK) == 0 &&
2384 	    lp->nfslock_usecnt == 0)
2385 		return (0);
2386 	return (1);
2387 }
2388 
2389 /*
2390  * Wake up anyone sleeping, waiting for this lock.
2391  */
2392 static void
2393 nfsv4_wanted(struct nfsv4lock *lp)
2394 {
2395 
2396 	if (lp->nfslock_lock & NFSV4LOCK_WANTED) {
2397 		lp->nfslock_lock &= ~NFSV4LOCK_WANTED;
2398 		wakeup((caddr_t)&lp->nfslock_lock);
2399 	}
2400 }
2401 
2402 /*
2403  * Copy a string from an mbuf list into a character array.
2404  * Return EBADRPC if there is an mbuf error,
2405  * 0 otherwise.
2406  */
2407 int
2408 nfsrv_mtostr(struct nfsrv_descript *nd, char *str, int siz)
2409 {
2410 	char *cp;
2411 	int xfer, len;
2412 	struct mbuf *mp;
2413 	int rem, error = 0;
2414 
2415 	mp = nd->nd_md;
2416 	cp = nd->nd_dpos;
2417 	len = mtod(mp, caddr_t) + mp->m_len - cp;
2418 	rem = NFSM_RNDUP(siz) - siz;
2419 	while (siz > 0) {
2420 		if (len > siz)
2421 			xfer = siz;
2422 		else
2423 			xfer = len;
2424 		NFSBCOPY(cp, str, xfer);
2425 		str += xfer;
2426 		siz -= xfer;
2427 		if (siz > 0) {
2428 			mp = mp->m_next;
2429 			if (mp == NULL) {
2430 				error = EBADRPC;
2431 				goto out;
2432 			}
2433 			cp = mtod(mp, caddr_t);
2434 			len = mp->m_len;
2435 		} else {
2436 			cp += xfer;
2437 			len -= xfer;
2438 		}
2439 	}
2440 	*str = '\0';
2441 	nd->nd_dpos = cp;
2442 	nd->nd_md = mp;
2443 	if (rem > 0) {
2444 		if (len < rem)
2445 			error = nfsm_advance(nd, rem, len);
2446 		else
2447 			nd->nd_dpos += rem;
2448 	}
2449 
2450 out:
2451 	NFSEXITCODE2(error, nd);
2452 	return (error);
2453 }
2454 
2455 /*
2456  * Fill in the attributes as marked by the bitmap (V4).
2457  */
2458 int
2459 nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
2460     NFSACL_T *saclp, struct vattr *vap, fhandle_t *fhp, int rderror,
2461     nfsattrbit_t *attrbitp, struct ucred *cred, NFSPROC_T *p, int isdgram,
2462     int reterr, int supports_nfsv4acls, int at_root, uint64_t mounted_on_fileno,
2463     struct statfs *pnfssf)
2464 {
2465 	int bitpos, retnum = 0;
2466 	u_int32_t *tl;
2467 	int siz, prefixnum, error;
2468 	u_char *cp, namestr[NFSV4_SMALLSTR];
2469 	nfsattrbit_t attrbits, retbits;
2470 	nfsattrbit_t *retbitp = &retbits;
2471 	u_int32_t freenum, *retnump;
2472 	u_int64_t uquad;
2473 	struct statfs *fs;
2474 	struct nfsfsinfo fsinf;
2475 	struct timespec temptime;
2476 	NFSACL_T *aclp, *naclp = NULL;
2477 	size_t atsiz;
2478 	bool xattrsupp;
2479 #ifdef QUOTA
2480 	struct dqblk dqb;
2481 	uid_t savuid;
2482 #endif
2483 
2484 	/*
2485 	 * First, set the bits that can be filled and get fsinfo.
2486 	 */
2487 	NFSSET_ATTRBIT(retbitp, attrbitp);
2488 	/*
2489 	 * If both p and cred are NULL, it is a client side setattr call.
2490 	 * If both p and cred are not NULL, it is a server side reply call.
2491 	 * If p is not NULL and cred is NULL, it is a client side callback
2492 	 * reply call.
2493 	 */
2494 	if (p == NULL && cred == NULL) {
2495 		NFSCLRNOTSETABLE_ATTRBIT(retbitp, nd);
2496 		aclp = saclp;
2497 	} else {
2498 		NFSCLRNOTFILLABLE_ATTRBIT(retbitp, nd);
2499 		naclp = acl_alloc(M_WAITOK);
2500 		aclp = naclp;
2501 	}
2502 	nfsvno_getfs(&fsinf, isdgram);
2503 #ifndef APPLE
2504 	/*
2505 	 * Get the VFS_STATFS(), since some attributes need them.
2506 	 */
2507 	fs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
2508 	if (NFSISSETSTATFS_ATTRBIT(retbitp)) {
2509 		error = VFS_STATFS(mp, fs);
2510 		if (error != 0) {
2511 			if (reterr) {
2512 				nd->nd_repstat = NFSERR_ACCES;
2513 				free(fs, M_STATFS);
2514 				return (0);
2515 			}
2516 			NFSCLRSTATFS_ATTRBIT(retbitp);
2517 		}
2518 	}
2519 #endif
2520 
2521 	/*
2522 	 * And the NFSv4 ACL...
2523 	 */
2524 	if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_ACLSUPPORT) &&
2525 	    (nfsrv_useacl == 0 || ((cred != NULL || p != NULL) &&
2526 		supports_nfsv4acls == 0))) {
2527 		NFSCLRBIT_ATTRBIT(retbitp, NFSATTRBIT_ACLSUPPORT);
2528 	}
2529 	if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_ACL)) {
2530 		if (nfsrv_useacl == 0 || ((cred != NULL || p != NULL) &&
2531 		    supports_nfsv4acls == 0)) {
2532 			NFSCLRBIT_ATTRBIT(retbitp, NFSATTRBIT_ACL);
2533 		} else if (naclp != NULL) {
2534 			if (NFSVOPLOCK(vp, LK_SHARED) == 0) {
2535 				error = VOP_ACCESSX(vp, VREAD_ACL, cred, p);
2536 				if (error == 0)
2537 					error = VOP_GETACL(vp, ACL_TYPE_NFS4,
2538 					    naclp, cred, p);
2539 				NFSVOPUNLOCK(vp);
2540 			} else
2541 				error = NFSERR_PERM;
2542 			if (error != 0) {
2543 				if (reterr) {
2544 					nd->nd_repstat = NFSERR_ACCES;
2545 					free(fs, M_STATFS);
2546 					return (0);
2547 				}
2548 				NFSCLRBIT_ATTRBIT(retbitp, NFSATTRBIT_ACL);
2549 			}
2550 		}
2551 	}
2552 
2553 	/* Check to see if Extended Attributes are supported. */
2554 	xattrsupp = false;
2555 	if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_XATTRSUPPORT)) {
2556 		if (NFSVOPLOCK(vp, LK_SHARED) == 0) {
2557 			error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER,
2558 			    "xxx", NULL, &atsiz, cred, p);
2559 			NFSVOPUNLOCK(vp);
2560 			if (error != EOPNOTSUPP)
2561 				xattrsupp = true;
2562 		}
2563 	}
2564 
2565 	/*
2566 	 * Put out the attribute bitmap for the ones being filled in
2567 	 * and get the field for the number of attributes returned.
2568 	 */
2569 	prefixnum = nfsrv_putattrbit(nd, retbitp);
2570 	NFSM_BUILD(retnump, u_int32_t *, NFSX_UNSIGNED);
2571 	prefixnum += NFSX_UNSIGNED;
2572 
2573 	/*
2574 	 * Now, loop around filling in the attributes for each bit set.
2575 	 */
2576 	for (bitpos = 0; bitpos < NFSATTRBIT_MAX; bitpos++) {
2577 	    if (NFSISSET_ATTRBIT(retbitp, bitpos)) {
2578 		switch (bitpos) {
2579 		case NFSATTRBIT_SUPPORTEDATTRS:
2580 			NFSSETSUPP_ATTRBIT(&attrbits, nd);
2581 			if (nfsrv_useacl == 0 || ((cred != NULL || p != NULL)
2582 			    && supports_nfsv4acls == 0)) {
2583 			    NFSCLRBIT_ATTRBIT(&attrbits,NFSATTRBIT_ACLSUPPORT);
2584 			    NFSCLRBIT_ATTRBIT(&attrbits,NFSATTRBIT_ACL);
2585 			}
2586 			retnum += nfsrv_putattrbit(nd, &attrbits);
2587 			break;
2588 		case NFSATTRBIT_TYPE:
2589 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2590 			*tl = vtonfsv34_type(vap->va_type);
2591 			retnum += NFSX_UNSIGNED;
2592 			break;
2593 		case NFSATTRBIT_FHEXPIRETYPE:
2594 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2595 			*tl = txdr_unsigned(NFSV4FHTYPE_PERSISTENT);
2596 			retnum += NFSX_UNSIGNED;
2597 			break;
2598 		case NFSATTRBIT_CHANGE:
2599 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2600 			txdr_hyper(vap->va_filerev, tl);
2601 			retnum += NFSX_HYPER;
2602 			break;
2603 		case NFSATTRBIT_SIZE:
2604 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2605 			txdr_hyper(vap->va_size, tl);
2606 			retnum += NFSX_HYPER;
2607 			break;
2608 		case NFSATTRBIT_LINKSUPPORT:
2609 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2610 			if (fsinf.fs_properties & NFSV3FSINFO_LINK)
2611 				*tl = newnfs_true;
2612 			else
2613 				*tl = newnfs_false;
2614 			retnum += NFSX_UNSIGNED;
2615 			break;
2616 		case NFSATTRBIT_SYMLINKSUPPORT:
2617 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2618 			if (fsinf.fs_properties & NFSV3FSINFO_SYMLINK)
2619 				*tl = newnfs_true;
2620 			else
2621 				*tl = newnfs_false;
2622 			retnum += NFSX_UNSIGNED;
2623 			break;
2624 		case NFSATTRBIT_NAMEDATTR:
2625 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2626 			*tl = newnfs_false;
2627 			retnum += NFSX_UNSIGNED;
2628 			break;
2629 		case NFSATTRBIT_FSID:
2630 			NFSM_BUILD(tl, u_int32_t *, NFSX_V4FSID);
2631 			*tl++ = 0;
2632 			*tl++ = txdr_unsigned(mp->mnt_stat.f_fsid.val[0]);
2633 			*tl++ = 0;
2634 			*tl = txdr_unsigned(mp->mnt_stat.f_fsid.val[1]);
2635 			retnum += NFSX_V4FSID;
2636 			break;
2637 		case NFSATTRBIT_UNIQUEHANDLES:
2638 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2639 			*tl = newnfs_true;
2640 			retnum += NFSX_UNSIGNED;
2641 			break;
2642 		case NFSATTRBIT_LEASETIME:
2643 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2644 			*tl = txdr_unsigned(nfsrv_lease);
2645 			retnum += NFSX_UNSIGNED;
2646 			break;
2647 		case NFSATTRBIT_RDATTRERROR:
2648 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2649 			*tl = txdr_unsigned(rderror);
2650 			retnum += NFSX_UNSIGNED;
2651 			break;
2652 		/*
2653 		 * Recommended Attributes. (Only the supported ones.)
2654 		 */
2655 		case NFSATTRBIT_ACL:
2656 			retnum += nfsrv_buildacl(nd, aclp, vnode_vtype(vp), p);
2657 			break;
2658 		case NFSATTRBIT_ACLSUPPORT:
2659 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2660 			*tl = txdr_unsigned(NFSV4ACE_SUPTYPES);
2661 			retnum += NFSX_UNSIGNED;
2662 			break;
2663 		case NFSATTRBIT_CANSETTIME:
2664 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2665 			if (fsinf.fs_properties & NFSV3FSINFO_CANSETTIME)
2666 				*tl = newnfs_true;
2667 			else
2668 				*tl = newnfs_false;
2669 			retnum += NFSX_UNSIGNED;
2670 			break;
2671 		case NFSATTRBIT_CASEINSENSITIVE:
2672 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2673 			*tl = newnfs_false;
2674 			retnum += NFSX_UNSIGNED;
2675 			break;
2676 		case NFSATTRBIT_CASEPRESERVING:
2677 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2678 			*tl = newnfs_true;
2679 			retnum += NFSX_UNSIGNED;
2680 			break;
2681 		case NFSATTRBIT_CHOWNRESTRICTED:
2682 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2683 			*tl = newnfs_true;
2684 			retnum += NFSX_UNSIGNED;
2685 			break;
2686 		case NFSATTRBIT_FILEHANDLE:
2687 			retnum += nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 0);
2688 			break;
2689 		case NFSATTRBIT_FILEID:
2690 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2691 			uquad = vap->va_fileid;
2692 			txdr_hyper(uquad, tl);
2693 			retnum += NFSX_HYPER;
2694 			break;
2695 		case NFSATTRBIT_FILESAVAIL:
2696 			/*
2697 			 * Check quota and use min(quota, f_ffree).
2698 			 */
2699 			freenum = fs->f_ffree;
2700 #ifdef QUOTA
2701 			/*
2702 			 * ufs_quotactl() insists that the uid argument
2703 			 * equal p_ruid for non-root quota access, so
2704 			 * we'll just make sure that's the case.
2705 			 */
2706 			savuid = p->p_cred->p_ruid;
2707 			p->p_cred->p_ruid = cred->cr_uid;
2708 			if (!VFS_QUOTACTL(mp, QCMD(Q_GETQUOTA,USRQUOTA),
2709 			    cred->cr_uid, &dqb))
2710 			    freenum = min(dqb.dqb_isoftlimit-dqb.dqb_curinodes,
2711 				freenum);
2712 			p->p_cred->p_ruid = savuid;
2713 #endif	/* QUOTA */
2714 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2715 			*tl++ = 0;
2716 			*tl = txdr_unsigned(freenum);
2717 			retnum += NFSX_HYPER;
2718 			break;
2719 		case NFSATTRBIT_FILESFREE:
2720 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2721 			*tl++ = 0;
2722 			*tl = txdr_unsigned(fs->f_ffree);
2723 			retnum += NFSX_HYPER;
2724 			break;
2725 		case NFSATTRBIT_FILESTOTAL:
2726 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2727 			*tl++ = 0;
2728 			*tl = txdr_unsigned(fs->f_files);
2729 			retnum += NFSX_HYPER;
2730 			break;
2731 		case NFSATTRBIT_FSLOCATIONS:
2732 			NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2733 			*tl++ = 0;
2734 			*tl = 0;
2735 			retnum += 2 * NFSX_UNSIGNED;
2736 			break;
2737 		case NFSATTRBIT_HOMOGENEOUS:
2738 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2739 			if (fsinf.fs_properties & NFSV3FSINFO_HOMOGENEOUS)
2740 				*tl = newnfs_true;
2741 			else
2742 				*tl = newnfs_false;
2743 			retnum += NFSX_UNSIGNED;
2744 			break;
2745 		case NFSATTRBIT_MAXFILESIZE:
2746 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2747 			uquad = NFSRV_MAXFILESIZE;
2748 			txdr_hyper(uquad, tl);
2749 			retnum += NFSX_HYPER;
2750 			break;
2751 		case NFSATTRBIT_MAXLINK:
2752 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2753 			*tl = txdr_unsigned(NFS_LINK_MAX);
2754 			retnum += NFSX_UNSIGNED;
2755 			break;
2756 		case NFSATTRBIT_MAXNAME:
2757 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2758 			*tl = txdr_unsigned(NFS_MAXNAMLEN);
2759 			retnum += NFSX_UNSIGNED;
2760 			break;
2761 		case NFSATTRBIT_MAXREAD:
2762 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2763 			*tl++ = 0;
2764 			*tl = txdr_unsigned(fsinf.fs_rtmax);
2765 			retnum += NFSX_HYPER;
2766 			break;
2767 		case NFSATTRBIT_MAXWRITE:
2768 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2769 			*tl++ = 0;
2770 			*tl = txdr_unsigned(fsinf.fs_wtmax);
2771 			retnum += NFSX_HYPER;
2772 			break;
2773 		case NFSATTRBIT_MODE:
2774 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2775 			*tl = vtonfsv34_mode(vap->va_mode);
2776 			retnum += NFSX_UNSIGNED;
2777 			break;
2778 		case NFSATTRBIT_NOTRUNC:
2779 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2780 			*tl = newnfs_true;
2781 			retnum += NFSX_UNSIGNED;
2782 			break;
2783 		case NFSATTRBIT_NUMLINKS:
2784 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2785 			*tl = txdr_unsigned(vap->va_nlink);
2786 			retnum += NFSX_UNSIGNED;
2787 			break;
2788 		case NFSATTRBIT_OWNER:
2789 			cp = namestr;
2790 			nfsv4_uidtostr(vap->va_uid, &cp, &siz);
2791 			retnum += nfsm_strtom(nd, cp, siz);
2792 			if (cp != namestr)
2793 				free(cp, M_NFSSTRING);
2794 			break;
2795 		case NFSATTRBIT_OWNERGROUP:
2796 			cp = namestr;
2797 			nfsv4_gidtostr(vap->va_gid, &cp, &siz);
2798 			retnum += nfsm_strtom(nd, cp, siz);
2799 			if (cp != namestr)
2800 				free(cp, M_NFSSTRING);
2801 			break;
2802 		case NFSATTRBIT_QUOTAHARD:
2803 			if (priv_check_cred(cred, PRIV_VFS_EXCEEDQUOTA))
2804 				freenum = fs->f_bfree;
2805 			else
2806 				freenum = fs->f_bavail;
2807 #ifdef QUOTA
2808 			/*
2809 			 * ufs_quotactl() insists that the uid argument
2810 			 * equal p_ruid for non-root quota access, so
2811 			 * we'll just make sure that's the case.
2812 			 */
2813 			savuid = p->p_cred->p_ruid;
2814 			p->p_cred->p_ruid = cred->cr_uid;
2815 			if (!VFS_QUOTACTL(mp, QCMD(Q_GETQUOTA,USRQUOTA),
2816 			    cred->cr_uid, &dqb))
2817 			    freenum = min(dqb.dqb_bhardlimit, freenum);
2818 			p->p_cred->p_ruid = savuid;
2819 #endif	/* QUOTA */
2820 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2821 			uquad = (u_int64_t)freenum;
2822 			NFSQUOTABLKTOBYTE(uquad, fs->f_bsize);
2823 			txdr_hyper(uquad, tl);
2824 			retnum += NFSX_HYPER;
2825 			break;
2826 		case NFSATTRBIT_QUOTASOFT:
2827 			if (priv_check_cred(cred, PRIV_VFS_EXCEEDQUOTA))
2828 				freenum = fs->f_bfree;
2829 			else
2830 				freenum = fs->f_bavail;
2831 #ifdef QUOTA
2832 			/*
2833 			 * ufs_quotactl() insists that the uid argument
2834 			 * equal p_ruid for non-root quota access, so
2835 			 * we'll just make sure that's the case.
2836 			 */
2837 			savuid = p->p_cred->p_ruid;
2838 			p->p_cred->p_ruid = cred->cr_uid;
2839 			if (!VFS_QUOTACTL(mp, QCMD(Q_GETQUOTA,USRQUOTA),
2840 			    cred->cr_uid, &dqb))
2841 			    freenum = min(dqb.dqb_bsoftlimit, freenum);
2842 			p->p_cred->p_ruid = savuid;
2843 #endif	/* QUOTA */
2844 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2845 			uquad = (u_int64_t)freenum;
2846 			NFSQUOTABLKTOBYTE(uquad, fs->f_bsize);
2847 			txdr_hyper(uquad, tl);
2848 			retnum += NFSX_HYPER;
2849 			break;
2850 		case NFSATTRBIT_QUOTAUSED:
2851 			freenum = 0;
2852 #ifdef QUOTA
2853 			/*
2854 			 * ufs_quotactl() insists that the uid argument
2855 			 * equal p_ruid for non-root quota access, so
2856 			 * we'll just make sure that's the case.
2857 			 */
2858 			savuid = p->p_cred->p_ruid;
2859 			p->p_cred->p_ruid = cred->cr_uid;
2860 			if (!VFS_QUOTACTL(mp, QCMD(Q_GETQUOTA,USRQUOTA),
2861 			    cred->cr_uid, &dqb))
2862 			    freenum = dqb.dqb_curblocks;
2863 			p->p_cred->p_ruid = savuid;
2864 #endif	/* QUOTA */
2865 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2866 			uquad = (u_int64_t)freenum;
2867 			NFSQUOTABLKTOBYTE(uquad, fs->f_bsize);
2868 			txdr_hyper(uquad, tl);
2869 			retnum += NFSX_HYPER;
2870 			break;
2871 		case NFSATTRBIT_RAWDEV:
2872 			NFSM_BUILD(tl, u_int32_t *, NFSX_V4SPECDATA);
2873 			*tl++ = txdr_unsigned(NFSMAJOR(vap->va_rdev));
2874 			*tl = txdr_unsigned(NFSMINOR(vap->va_rdev));
2875 			retnum += NFSX_V4SPECDATA;
2876 			break;
2877 		case NFSATTRBIT_SPACEAVAIL:
2878 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2879 			if (priv_check_cred(cred, PRIV_VFS_BLOCKRESERVE)) {
2880 				if (pnfssf != NULL)
2881 					uquad = (u_int64_t)pnfssf->f_bfree;
2882 				else
2883 					uquad = (u_int64_t)fs->f_bfree;
2884 			} else {
2885 				if (pnfssf != NULL)
2886 					uquad = (u_int64_t)pnfssf->f_bavail;
2887 				else
2888 					uquad = (u_int64_t)fs->f_bavail;
2889 			}
2890 			if (pnfssf != NULL)
2891 				uquad *= pnfssf->f_bsize;
2892 			else
2893 				uquad *= fs->f_bsize;
2894 			txdr_hyper(uquad, tl);
2895 			retnum += NFSX_HYPER;
2896 			break;
2897 		case NFSATTRBIT_SPACEFREE:
2898 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2899 			if (pnfssf != NULL) {
2900 				uquad = (u_int64_t)pnfssf->f_bfree;
2901 				uquad *= pnfssf->f_bsize;
2902 			} else {
2903 				uquad = (u_int64_t)fs->f_bfree;
2904 				uquad *= fs->f_bsize;
2905 			}
2906 			txdr_hyper(uquad, tl);
2907 			retnum += NFSX_HYPER;
2908 			break;
2909 		case NFSATTRBIT_SPACETOTAL:
2910 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2911 			if (pnfssf != NULL) {
2912 				uquad = (u_int64_t)pnfssf->f_blocks;
2913 				uquad *= pnfssf->f_bsize;
2914 			} else {
2915 				uquad = (u_int64_t)fs->f_blocks;
2916 				uquad *= fs->f_bsize;
2917 			}
2918 			txdr_hyper(uquad, tl);
2919 			retnum += NFSX_HYPER;
2920 			break;
2921 		case NFSATTRBIT_SPACEUSED:
2922 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2923 			txdr_hyper(vap->va_bytes, tl);
2924 			retnum += NFSX_HYPER;
2925 			break;
2926 		case NFSATTRBIT_TIMEACCESS:
2927 			NFSM_BUILD(tl, u_int32_t *, NFSX_V4TIME);
2928 			txdr_nfsv4time(&vap->va_atime, tl);
2929 			retnum += NFSX_V4TIME;
2930 			break;
2931 		case NFSATTRBIT_TIMEACCESSSET:
2932 			if ((vap->va_vaflags & VA_UTIMES_NULL) == 0) {
2933 				NFSM_BUILD(tl, u_int32_t *, NFSX_V4SETTIME);
2934 				*tl++ = txdr_unsigned(NFSV4SATTRTIME_TOCLIENT);
2935 				txdr_nfsv4time(&vap->va_atime, tl);
2936 				retnum += NFSX_V4SETTIME;
2937 			} else {
2938 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2939 				*tl = txdr_unsigned(NFSV4SATTRTIME_TOSERVER);
2940 				retnum += NFSX_UNSIGNED;
2941 			}
2942 			break;
2943 		case NFSATTRBIT_TIMEDELTA:
2944 			NFSM_BUILD(tl, u_int32_t *, NFSX_V4TIME);
2945 			temptime.tv_sec = 0;
2946 			temptime.tv_nsec = 1000000000 / hz;
2947 			txdr_nfsv4time(&temptime, tl);
2948 			retnum += NFSX_V4TIME;
2949 			break;
2950 		case NFSATTRBIT_TIMEMETADATA:
2951 			NFSM_BUILD(tl, u_int32_t *, NFSX_V4TIME);
2952 			txdr_nfsv4time(&vap->va_ctime, tl);
2953 			retnum += NFSX_V4TIME;
2954 			break;
2955 		case NFSATTRBIT_TIMEMODIFY:
2956 			NFSM_BUILD(tl, u_int32_t *, NFSX_V4TIME);
2957 			txdr_nfsv4time(&vap->va_mtime, tl);
2958 			retnum += NFSX_V4TIME;
2959 			break;
2960 		case NFSATTRBIT_TIMECREATE:
2961 			NFSM_BUILD(tl, u_int32_t *, NFSX_V4TIME);
2962 			txdr_nfsv4time(&vap->va_birthtime, tl);
2963 			retnum += NFSX_V4TIME;
2964 			break;
2965 		case NFSATTRBIT_TIMEMODIFYSET:
2966 			if ((vap->va_vaflags & VA_UTIMES_NULL) == 0) {
2967 				NFSM_BUILD(tl, u_int32_t *, NFSX_V4SETTIME);
2968 				*tl++ = txdr_unsigned(NFSV4SATTRTIME_TOCLIENT);
2969 				txdr_nfsv4time(&vap->va_mtime, tl);
2970 				retnum += NFSX_V4SETTIME;
2971 			} else {
2972 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2973 				*tl = txdr_unsigned(NFSV4SATTRTIME_TOSERVER);
2974 				retnum += NFSX_UNSIGNED;
2975 			}
2976 			break;
2977 		case NFSATTRBIT_MOUNTEDONFILEID:
2978 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2979 			if (at_root != 0)
2980 				uquad = mounted_on_fileno;
2981 			else
2982 				uquad = vap->va_fileid;
2983 			txdr_hyper(uquad, tl);
2984 			retnum += NFSX_HYPER;
2985 			break;
2986 		case NFSATTRBIT_SUPPATTREXCLCREAT:
2987 			NFSSETSUPP_ATTRBIT(&attrbits, nd);
2988 			NFSCLRNOTSETABLE_ATTRBIT(&attrbits, nd);
2989 			NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESSSET);
2990 			retnum += nfsrv_putattrbit(nd, &attrbits);
2991 			break;
2992 		case NFSATTRBIT_FSLAYOUTTYPE:
2993 		case NFSATTRBIT_LAYOUTTYPE:
2994 			if (nfsrv_devidcnt == 0)
2995 				siz = 1;
2996 			else
2997 				siz = 2;
2998 			if (siz == 2) {
2999 				NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
3000 				*tl++ = txdr_unsigned(1);	/* One entry. */
3001 				if (nfsrv_doflexfile != 0 ||
3002 				    nfsrv_maxpnfsmirror > 1)
3003 					*tl = txdr_unsigned(NFSLAYOUT_FLEXFILE);
3004 				else
3005 					*tl = txdr_unsigned(
3006 					    NFSLAYOUT_NFSV4_1_FILES);
3007 			} else {
3008 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3009 				*tl = 0;
3010 			}
3011 			retnum += siz * NFSX_UNSIGNED;
3012 			break;
3013 		case NFSATTRBIT_LAYOUTALIGNMENT:
3014 		case NFSATTRBIT_LAYOUTBLKSIZE:
3015 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3016 			*tl = txdr_unsigned(nfs_srvmaxio);
3017 			retnum += NFSX_UNSIGNED;
3018 			break;
3019 		case NFSATTRBIT_XATTRSUPPORT:
3020 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3021 			if (xattrsupp)
3022 				*tl = newnfs_true;
3023 			else
3024 				*tl = newnfs_false;
3025 			retnum += NFSX_UNSIGNED;
3026 			break;
3027 		default:
3028 			printf("EEK! Bad V4 attribute bitpos=%d\n", bitpos);
3029 		}
3030 	    }
3031 	}
3032 	if (naclp != NULL)
3033 		acl_free(naclp);
3034 	free(fs, M_STATFS);
3035 	*retnump = txdr_unsigned(retnum);
3036 	return (retnum + prefixnum);
3037 }
3038 
3039 /*
3040  * Put the attribute bits onto an mbuf list.
3041  * Return the number of bytes of output generated.
3042  */
3043 int
3044 nfsrv_putattrbit(struct nfsrv_descript *nd, nfsattrbit_t *attrbitp)
3045 {
3046 	u_int32_t *tl;
3047 	int cnt, i, bytesize;
3048 
3049 	for (cnt = NFSATTRBIT_MAXWORDS; cnt > 0; cnt--)
3050 		if (attrbitp->bits[cnt - 1])
3051 			break;
3052 	bytesize = (cnt + 1) * NFSX_UNSIGNED;
3053 	NFSM_BUILD(tl, u_int32_t *, bytesize);
3054 	*tl++ = txdr_unsigned(cnt);
3055 	for (i = 0; i < cnt; i++)
3056 		*tl++ = txdr_unsigned(attrbitp->bits[i]);
3057 	return (bytesize);
3058 }
3059 
3060 /*
3061  * Convert a uid to a string.
3062  * If the lookup fails, just output the digits.
3063  * uid - the user id
3064  * cpp - points to a buffer of size NFSV4_SMALLSTR
3065  *       (malloc a larger one, as required)
3066  * retlenp - pointer to length to be returned
3067  */
3068 void
3069 nfsv4_uidtostr(uid_t uid, u_char **cpp, int *retlenp)
3070 {
3071 	int i;
3072 	struct nfsusrgrp *usrp;
3073 	u_char *cp = *cpp;
3074 	uid_t tmp;
3075 	int cnt, hasampersand, len = NFSV4_SMALLSTR, ret;
3076 	struct nfsrv_lughash *hp;
3077 
3078 	cnt = 0;
3079 tryagain:
3080 	if (nfsrv_dnsnamelen > 0 && !nfs_enable_uidtostring) {
3081 		/*
3082 		 * Always map nfsrv_defaultuid to "nobody".
3083 		 */
3084 		if (uid == nfsrv_defaultuid) {
3085 			i = nfsrv_dnsnamelen + 7;
3086 			if (i > len) {
3087 				if (len > NFSV4_SMALLSTR)
3088 					free(cp, M_NFSSTRING);
3089 				cp = malloc(i, M_NFSSTRING, M_WAITOK);
3090 				*cpp = cp;
3091 				len = i;
3092 				goto tryagain;
3093 			}
3094 			*retlenp = i;
3095 			NFSBCOPY("nobody@", cp, 7);
3096 			cp += 7;
3097 			NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
3098 			return;
3099 		}
3100 		hasampersand = 0;
3101 		hp = NFSUSERHASH(uid);
3102 		mtx_lock(&hp->mtx);
3103 		TAILQ_FOREACH(usrp, &hp->lughead, lug_numhash) {
3104 			if (usrp->lug_uid == uid) {
3105 				if (usrp->lug_expiry < NFSD_MONOSEC)
3106 					break;
3107 				/*
3108 				 * If the name doesn't already have an '@'
3109 				 * in it, append @domainname to it.
3110 				 */
3111 				for (i = 0; i < usrp->lug_namelen; i++) {
3112 					if (usrp->lug_name[i] == '@') {
3113 						hasampersand = 1;
3114 						break;
3115 					}
3116 				}
3117 				if (hasampersand)
3118 					i = usrp->lug_namelen;
3119 				else
3120 					i = usrp->lug_namelen +
3121 					    nfsrv_dnsnamelen + 1;
3122 				if (i > len) {
3123 					mtx_unlock(&hp->mtx);
3124 					if (len > NFSV4_SMALLSTR)
3125 						free(cp, M_NFSSTRING);
3126 					cp = malloc(i, M_NFSSTRING, M_WAITOK);
3127 					*cpp = cp;
3128 					len = i;
3129 					goto tryagain;
3130 				}
3131 				*retlenp = i;
3132 				NFSBCOPY(usrp->lug_name, cp, usrp->lug_namelen);
3133 				if (!hasampersand) {
3134 					cp += usrp->lug_namelen;
3135 					*cp++ = '@';
3136 					NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
3137 				}
3138 				TAILQ_REMOVE(&hp->lughead, usrp, lug_numhash);
3139 				TAILQ_INSERT_TAIL(&hp->lughead, usrp,
3140 				    lug_numhash);
3141 				mtx_unlock(&hp->mtx);
3142 				return;
3143 			}
3144 		}
3145 		mtx_unlock(&hp->mtx);
3146 		cnt++;
3147 		ret = nfsrv_getuser(RPCNFSUSERD_GETUID, uid, (gid_t)0, NULL);
3148 		if (ret == 0 && cnt < 2)
3149 			goto tryagain;
3150 	}
3151 
3152 	/*
3153 	 * No match, just return a string of digits.
3154 	 */
3155 	tmp = uid;
3156 	i = 0;
3157 	while (tmp || i == 0) {
3158 		tmp /= 10;
3159 		i++;
3160 	}
3161 	len = (i > len) ? len : i;
3162 	*retlenp = len;
3163 	cp += (len - 1);
3164 	tmp = uid;
3165 	for (i = 0; i < len; i++) {
3166 		*cp-- = '0' + (tmp % 10);
3167 		tmp /= 10;
3168 	}
3169 	return;
3170 }
3171 
3172 /*
3173  * Get a credential for the uid with the server's group list.
3174  * If none is found, just return the credential passed in after
3175  * logging a warning message.
3176  */
3177 struct ucred *
3178 nfsrv_getgrpscred(struct ucred *oldcred)
3179 {
3180 	struct nfsusrgrp *usrp;
3181 	struct ucred *newcred;
3182 	int cnt, ret;
3183 	uid_t uid;
3184 	struct nfsrv_lughash *hp;
3185 
3186 	cnt = 0;
3187 	uid = oldcred->cr_uid;
3188 tryagain:
3189 	if (nfsrv_dnsnamelen > 0) {
3190 		hp = NFSUSERHASH(uid);
3191 		mtx_lock(&hp->mtx);
3192 		TAILQ_FOREACH(usrp, &hp->lughead, lug_numhash) {
3193 			if (usrp->lug_uid == uid) {
3194 				if (usrp->lug_expiry < NFSD_MONOSEC)
3195 					break;
3196 				if (usrp->lug_cred != NULL) {
3197 					newcred = crhold(usrp->lug_cred);
3198 					crfree(oldcred);
3199 				} else
3200 					newcred = oldcred;
3201 				TAILQ_REMOVE(&hp->lughead, usrp, lug_numhash);
3202 				TAILQ_INSERT_TAIL(&hp->lughead, usrp,
3203 				    lug_numhash);
3204 				mtx_unlock(&hp->mtx);
3205 				return (newcred);
3206 			}
3207 		}
3208 		mtx_unlock(&hp->mtx);
3209 		cnt++;
3210 		ret = nfsrv_getuser(RPCNFSUSERD_GETUID, uid, (gid_t)0, NULL);
3211 		if (ret == 0 && cnt < 2)
3212 			goto tryagain;
3213 	}
3214 	return (oldcred);
3215 }
3216 
3217 /*
3218  * Convert a string to a uid.
3219  * If no conversion is possible return NFSERR_BADOWNER, otherwise
3220  * return 0.
3221  * If this is called from a client side mount using AUTH_SYS and the
3222  * string is made up entirely of digits, just convert the string to
3223  * a number.
3224  */
3225 int
3226 nfsv4_strtouid(struct nfsrv_descript *nd, u_char *str, int len, uid_t *uidp)
3227 {
3228 	int i;
3229 	char *cp, *endstr, *str0;
3230 	struct nfsusrgrp *usrp;
3231 	int cnt, ret;
3232 	int error = 0;
3233 	uid_t tuid;
3234 	struct nfsrv_lughash *hp, *hp2;
3235 
3236 	if (len == 0) {
3237 		error = NFSERR_BADOWNER;
3238 		goto out;
3239 	}
3240 	/* If a string of digits and an AUTH_SYS mount, just convert it. */
3241 	str0 = str;
3242 	tuid = (uid_t)strtoul(str0, &endstr, 10);
3243 	if ((endstr - str0) == len) {
3244 		/* A numeric string. */
3245 		if ((nd->nd_flag & ND_KERBV) == 0 &&
3246 		    ((nd->nd_flag & ND_NFSCL) != 0 ||
3247 		      nfsd_enable_stringtouid != 0))
3248 			*uidp = tuid;
3249 		else
3250 			error = NFSERR_BADOWNER;
3251 		goto out;
3252 	}
3253 	/*
3254 	 * Look for an '@'.
3255 	 */
3256 	cp = strchr(str0, '@');
3257 	if (cp != NULL)
3258 		i = (int)(cp++ - str0);
3259 	else
3260 		i = len;
3261 
3262 	cnt = 0;
3263 tryagain:
3264 	if (nfsrv_dnsnamelen > 0) {
3265 		/*
3266 		 * If an '@' is found and the domain name matches, search for
3267 		 * the name with dns stripped off.
3268 		 * Mixed case alpahbetics will match for the domain name, but
3269 		 * all upper case will not.
3270 		 */
3271 		if (cnt == 0 && i < len && i > 0 &&
3272 		    (len - 1 - i) == nfsrv_dnsnamelen &&
3273 		    !nfsrv_cmpmixedcase(cp, nfsrv_dnsname, nfsrv_dnsnamelen)) {
3274 			len -= (nfsrv_dnsnamelen + 1);
3275 			*(cp - 1) = '\0';
3276 		}
3277 
3278 		/*
3279 		 * Check for the special case of "nobody".
3280 		 */
3281 		if (len == 6 && !NFSBCMP(str, "nobody", 6)) {
3282 			*uidp = nfsrv_defaultuid;
3283 			error = 0;
3284 			goto out;
3285 		}
3286 
3287 		hp = NFSUSERNAMEHASH(str, len);
3288 		mtx_lock(&hp->mtx);
3289 		TAILQ_FOREACH(usrp, &hp->lughead, lug_namehash) {
3290 			if (usrp->lug_namelen == len &&
3291 			    !NFSBCMP(usrp->lug_name, str, len)) {
3292 				if (usrp->lug_expiry < NFSD_MONOSEC)
3293 					break;
3294 				hp2 = NFSUSERHASH(usrp->lug_uid);
3295 				mtx_lock(&hp2->mtx);
3296 				TAILQ_REMOVE(&hp2->lughead, usrp, lug_numhash);
3297 				TAILQ_INSERT_TAIL(&hp2->lughead, usrp,
3298 				    lug_numhash);
3299 				*uidp = usrp->lug_uid;
3300 				mtx_unlock(&hp2->mtx);
3301 				mtx_unlock(&hp->mtx);
3302 				error = 0;
3303 				goto out;
3304 			}
3305 		}
3306 		mtx_unlock(&hp->mtx);
3307 		cnt++;
3308 		ret = nfsrv_getuser(RPCNFSUSERD_GETUSER, (uid_t)0, (gid_t)0,
3309 		    str);
3310 		if (ret == 0 && cnt < 2)
3311 			goto tryagain;
3312 	}
3313 	error = NFSERR_BADOWNER;
3314 
3315 out:
3316 	NFSEXITCODE(error);
3317 	return (error);
3318 }
3319 
3320 /*
3321  * Convert a gid to a string.
3322  * gid - the group id
3323  * cpp - points to a buffer of size NFSV4_SMALLSTR
3324  *       (malloc a larger one, as required)
3325  * retlenp - pointer to length to be returned
3326  */
3327 void
3328 nfsv4_gidtostr(gid_t gid, u_char **cpp, int *retlenp)
3329 {
3330 	int i;
3331 	struct nfsusrgrp *usrp;
3332 	u_char *cp = *cpp;
3333 	gid_t tmp;
3334 	int cnt, hasampersand, len = NFSV4_SMALLSTR, ret;
3335 	struct nfsrv_lughash *hp;
3336 
3337 	cnt = 0;
3338 tryagain:
3339 	if (nfsrv_dnsnamelen > 0 && !nfs_enable_uidtostring) {
3340 		/*
3341 		 * Always map nfsrv_defaultgid to "nogroup".
3342 		 */
3343 		if (gid == nfsrv_defaultgid) {
3344 			i = nfsrv_dnsnamelen + 8;
3345 			if (i > len) {
3346 				if (len > NFSV4_SMALLSTR)
3347 					free(cp, M_NFSSTRING);
3348 				cp = malloc(i, M_NFSSTRING, M_WAITOK);
3349 				*cpp = cp;
3350 				len = i;
3351 				goto tryagain;
3352 			}
3353 			*retlenp = i;
3354 			NFSBCOPY("nogroup@", cp, 8);
3355 			cp += 8;
3356 			NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
3357 			return;
3358 		}
3359 		hasampersand = 0;
3360 		hp = NFSGROUPHASH(gid);
3361 		mtx_lock(&hp->mtx);
3362 		TAILQ_FOREACH(usrp, &hp->lughead, lug_numhash) {
3363 			if (usrp->lug_gid == gid) {
3364 				if (usrp->lug_expiry < NFSD_MONOSEC)
3365 					break;
3366 				/*
3367 				 * If the name doesn't already have an '@'
3368 				 * in it, append @domainname to it.
3369 				 */
3370 				for (i = 0; i < usrp->lug_namelen; i++) {
3371 					if (usrp->lug_name[i] == '@') {
3372 						hasampersand = 1;
3373 						break;
3374 					}
3375 				}
3376 				if (hasampersand)
3377 					i = usrp->lug_namelen;
3378 				else
3379 					i = usrp->lug_namelen +
3380 					    nfsrv_dnsnamelen + 1;
3381 				if (i > len) {
3382 					mtx_unlock(&hp->mtx);
3383 					if (len > NFSV4_SMALLSTR)
3384 						free(cp, M_NFSSTRING);
3385 					cp = malloc(i, M_NFSSTRING, M_WAITOK);
3386 					*cpp = cp;
3387 					len = i;
3388 					goto tryagain;
3389 				}
3390 				*retlenp = i;
3391 				NFSBCOPY(usrp->lug_name, cp, usrp->lug_namelen);
3392 				if (!hasampersand) {
3393 					cp += usrp->lug_namelen;
3394 					*cp++ = '@';
3395 					NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
3396 				}
3397 				TAILQ_REMOVE(&hp->lughead, usrp, lug_numhash);
3398 				TAILQ_INSERT_TAIL(&hp->lughead, usrp,
3399 				    lug_numhash);
3400 				mtx_unlock(&hp->mtx);
3401 				return;
3402 			}
3403 		}
3404 		mtx_unlock(&hp->mtx);
3405 		cnt++;
3406 		ret = nfsrv_getuser(RPCNFSUSERD_GETGID, (uid_t)0, gid, NULL);
3407 		if (ret == 0 && cnt < 2)
3408 			goto tryagain;
3409 	}
3410 
3411 	/*
3412 	 * No match, just return a string of digits.
3413 	 */
3414 	tmp = gid;
3415 	i = 0;
3416 	while (tmp || i == 0) {
3417 		tmp /= 10;
3418 		i++;
3419 	}
3420 	len = (i > len) ? len : i;
3421 	*retlenp = len;
3422 	cp += (len - 1);
3423 	tmp = gid;
3424 	for (i = 0; i < len; i++) {
3425 		*cp-- = '0' + (tmp % 10);
3426 		tmp /= 10;
3427 	}
3428 	return;
3429 }
3430 
3431 /*
3432  * Convert a string to a gid.
3433  * If no conversion is possible return NFSERR_BADOWNER, otherwise
3434  * return 0.
3435  * If this is called from a client side mount using AUTH_SYS and the
3436  * string is made up entirely of digits, just convert the string to
3437  * a number.
3438  */
3439 int
3440 nfsv4_strtogid(struct nfsrv_descript *nd, u_char *str, int len, gid_t *gidp)
3441 {
3442 	int i;
3443 	char *cp, *endstr, *str0;
3444 	struct nfsusrgrp *usrp;
3445 	int cnt, ret;
3446 	int error = 0;
3447 	gid_t tgid;
3448 	struct nfsrv_lughash *hp, *hp2;
3449 
3450 	if (len == 0) {
3451 		error =  NFSERR_BADOWNER;
3452 		goto out;
3453 	}
3454 	/* If a string of digits and an AUTH_SYS mount, just convert it. */
3455 	str0 = str;
3456 	tgid = (gid_t)strtoul(str0, &endstr, 10);
3457 	if ((endstr - str0) == len) {
3458 		/* A numeric string. */
3459 		if ((nd->nd_flag & ND_KERBV) == 0 &&
3460 		    ((nd->nd_flag & ND_NFSCL) != 0 ||
3461 		      nfsd_enable_stringtouid != 0))
3462 			*gidp = tgid;
3463 		else
3464 			error = NFSERR_BADOWNER;
3465 		goto out;
3466 	}
3467 	/*
3468 	 * Look for an '@'.
3469 	 */
3470 	cp = strchr(str0, '@');
3471 	if (cp != NULL)
3472 		i = (int)(cp++ - str0);
3473 	else
3474 		i = len;
3475 
3476 	cnt = 0;
3477 tryagain:
3478 	if (nfsrv_dnsnamelen > 0) {
3479 		/*
3480 		 * If an '@' is found and the dns name matches, search for the
3481 		 * name with the dns stripped off.
3482 		 */
3483 		if (cnt == 0 && i < len && i > 0 &&
3484 		    (len - 1 - i) == nfsrv_dnsnamelen &&
3485 		    !nfsrv_cmpmixedcase(cp, nfsrv_dnsname, nfsrv_dnsnamelen)) {
3486 			len -= (nfsrv_dnsnamelen + 1);
3487 			*(cp - 1) = '\0';
3488 		}
3489 
3490 		/*
3491 		 * Check for the special case of "nogroup".
3492 		 */
3493 		if (len == 7 && !NFSBCMP(str, "nogroup", 7)) {
3494 			*gidp = nfsrv_defaultgid;
3495 			error = 0;
3496 			goto out;
3497 		}
3498 
3499 		hp = NFSGROUPNAMEHASH(str, len);
3500 		mtx_lock(&hp->mtx);
3501 		TAILQ_FOREACH(usrp, &hp->lughead, lug_namehash) {
3502 			if (usrp->lug_namelen == len &&
3503 			    !NFSBCMP(usrp->lug_name, str, len)) {
3504 				if (usrp->lug_expiry < NFSD_MONOSEC)
3505 					break;
3506 				hp2 = NFSGROUPHASH(usrp->lug_gid);
3507 				mtx_lock(&hp2->mtx);
3508 				TAILQ_REMOVE(&hp2->lughead, usrp, lug_numhash);
3509 				TAILQ_INSERT_TAIL(&hp2->lughead, usrp,
3510 				    lug_numhash);
3511 				*gidp = usrp->lug_gid;
3512 				mtx_unlock(&hp2->mtx);
3513 				mtx_unlock(&hp->mtx);
3514 				error = 0;
3515 				goto out;
3516 			}
3517 		}
3518 		mtx_unlock(&hp->mtx);
3519 		cnt++;
3520 		ret = nfsrv_getuser(RPCNFSUSERD_GETGROUP, (uid_t)0, (gid_t)0,
3521 		    str);
3522 		if (ret == 0 && cnt < 2)
3523 			goto tryagain;
3524 	}
3525 	error = NFSERR_BADOWNER;
3526 
3527 out:
3528 	NFSEXITCODE(error);
3529 	return (error);
3530 }
3531 
3532 /*
3533  * Cmp len chars, allowing mixed case in the first argument to match lower
3534  * case in the second, but not if the first argument is all upper case.
3535  * Return 0 for a match, 1 otherwise.
3536  */
3537 static int
3538 nfsrv_cmpmixedcase(u_char *cp, u_char *cp2, int len)
3539 {
3540 	int i;
3541 	u_char tmp;
3542 	int fndlower = 0;
3543 
3544 	for (i = 0; i < len; i++) {
3545 		if (*cp >= 'A' && *cp <= 'Z') {
3546 			tmp = *cp++ + ('a' - 'A');
3547 		} else {
3548 			tmp = *cp++;
3549 			if (tmp >= 'a' && tmp <= 'z')
3550 				fndlower = 1;
3551 		}
3552 		if (tmp != *cp2++)
3553 			return (1);
3554 	}
3555 	if (fndlower)
3556 		return (0);
3557 	else
3558 		return (1);
3559 }
3560 
3561 /*
3562  * Set the port for the nfsuserd.
3563  */
3564 int
3565 nfsrv_nfsuserdport(struct nfsuserd_args *nargs, NFSPROC_T *p)
3566 {
3567 	struct nfssockreq *rp;
3568 #ifdef INET
3569 	struct sockaddr_in *ad;
3570 #endif
3571 #ifdef INET6
3572 	struct sockaddr_in6 *ad6;
3573 	const struct in6_addr in6loopback = IN6ADDR_LOOPBACK_INIT;
3574 #endif
3575 	int error;
3576 
3577 	NFSLOCKNAMEID();
3578 	if (nfsrv_nfsuserd != NOTRUNNING) {
3579 		NFSUNLOCKNAMEID();
3580 		error = EPERM;
3581 		goto out;
3582 	}
3583 	nfsrv_nfsuserd = STARTSTOP;
3584 	/*
3585 	 * Set up the socket record and connect.
3586 	 * Set nr_client NULL before unlocking, just to ensure that no other
3587 	 * process/thread/core will use a bogus old value.  This could only
3588 	 * occur if the use of the nameid lock to protect nfsrv_nfsuserd is
3589 	 * broken.
3590 	 */
3591 	rp = &nfsrv_nfsuserdsock;
3592 	rp->nr_client = NULL;
3593 	NFSUNLOCKNAMEID();
3594 	rp->nr_sotype = SOCK_DGRAM;
3595 	rp->nr_soproto = IPPROTO_UDP;
3596 	rp->nr_lock = (NFSR_RESERVEDPORT | NFSR_LOCALHOST);
3597 	rp->nr_cred = NULL;
3598 	rp->nr_prog = RPCPROG_NFSUSERD;
3599 	error = 0;
3600 	switch (nargs->nuserd_family) {
3601 #ifdef INET
3602 	case AF_INET:
3603 		rp->nr_nam = malloc(sizeof(struct sockaddr_in), M_SONAME,
3604 		    M_WAITOK | M_ZERO);
3605  		ad = (struct sockaddr_in *)rp->nr_nam;
3606 		ad->sin_len = sizeof(struct sockaddr_in);
3607  		ad->sin_family = AF_INET;
3608 		ad->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
3609 		ad->sin_port = nargs->nuserd_port;
3610 		break;
3611 #endif
3612 #ifdef INET6
3613 	case AF_INET6:
3614 		rp->nr_nam = malloc(sizeof(struct sockaddr_in6), M_SONAME,
3615 		    M_WAITOK | M_ZERO);
3616 		ad6 = (struct sockaddr_in6 *)rp->nr_nam;
3617 		ad6->sin6_len = sizeof(struct sockaddr_in6);
3618 		ad6->sin6_family = AF_INET6;
3619 		ad6->sin6_addr = in6loopback;
3620 		ad6->sin6_port = nargs->nuserd_port;
3621 		break;
3622 #endif
3623 	default:
3624 		error = ENXIO;
3625  	}
3626 	rp->nr_vers = RPCNFSUSERD_VERS;
3627 	if (error == 0)
3628 		error = newnfs_connect(NULL, rp, NFSPROCCRED(p), p, 0, false,
3629 		    &rp->nr_client);
3630 	if (error == 0) {
3631 		NFSLOCKNAMEID();
3632 		nfsrv_nfsuserd = RUNNING;
3633 		NFSUNLOCKNAMEID();
3634 	} else {
3635 		free(rp->nr_nam, M_SONAME);
3636 		NFSLOCKNAMEID();
3637 		nfsrv_nfsuserd = NOTRUNNING;
3638 		NFSUNLOCKNAMEID();
3639 	}
3640 out:
3641 	NFSEXITCODE(error);
3642 	return (error);
3643 }
3644 
3645 /*
3646  * Delete the nfsuserd port.
3647  */
3648 void
3649 nfsrv_nfsuserddelport(void)
3650 {
3651 
3652 	NFSLOCKNAMEID();
3653 	if (nfsrv_nfsuserd != RUNNING) {
3654 		NFSUNLOCKNAMEID();
3655 		return;
3656 	}
3657 	nfsrv_nfsuserd = STARTSTOP;
3658 	/* Wait for all upcalls to complete. */
3659 	while (nfsrv_userdupcalls > 0)
3660 		msleep(&nfsrv_userdupcalls, NFSNAMEIDMUTEXPTR, PVFS,
3661 		    "nfsupcalls", 0);
3662 	NFSUNLOCKNAMEID();
3663 	newnfs_disconnect(NULL, &nfsrv_nfsuserdsock);
3664 	free(nfsrv_nfsuserdsock.nr_nam, M_SONAME);
3665 	NFSLOCKNAMEID();
3666 	nfsrv_nfsuserd = NOTRUNNING;
3667 	NFSUNLOCKNAMEID();
3668 }
3669 
3670 /*
3671  * Do upcalls to the nfsuserd, for cache misses of the owner/ownergroup
3672  * name<-->id cache.
3673  * Returns 0 upon success, non-zero otherwise.
3674  */
3675 static int
3676 nfsrv_getuser(int procnum, uid_t uid, gid_t gid, char *name)
3677 {
3678 	u_int32_t *tl;
3679 	struct nfsrv_descript *nd;
3680 	int len;
3681 	struct nfsrv_descript nfsd;
3682 	struct ucred *cred;
3683 	int error;
3684 
3685 	NFSLOCKNAMEID();
3686 	if (nfsrv_nfsuserd != RUNNING) {
3687 		NFSUNLOCKNAMEID();
3688 		error = EPERM;
3689 		goto out;
3690 	}
3691 	/*
3692 	 * Maintain a count of upcalls in progress, so that nfsrv_X()
3693 	 * can wait until no upcalls are in progress.
3694 	 */
3695 	nfsrv_userdupcalls++;
3696 	NFSUNLOCKNAMEID();
3697 	KASSERT(nfsrv_userdupcalls > 0,
3698 	    ("nfsrv_getuser: non-positive upcalls"));
3699 	nd = &nfsd;
3700 	cred = newnfs_getcred();
3701 	nd->nd_flag = ND_GSSINITREPLY;
3702 	nfsrvd_rephead(nd);
3703 
3704 	nd->nd_procnum = procnum;
3705 	if (procnum == RPCNFSUSERD_GETUID || procnum == RPCNFSUSERD_GETGID) {
3706 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3707 		if (procnum == RPCNFSUSERD_GETUID)
3708 			*tl = txdr_unsigned(uid);
3709 		else
3710 			*tl = txdr_unsigned(gid);
3711 	} else {
3712 		len = strlen(name);
3713 		(void) nfsm_strtom(nd, name, len);
3714 	}
3715 	error = newnfs_request(nd, NULL, NULL, &nfsrv_nfsuserdsock, NULL, NULL,
3716 		cred, RPCPROG_NFSUSERD, RPCNFSUSERD_VERS, NULL, 0, NULL, NULL);
3717 	NFSLOCKNAMEID();
3718 	if (--nfsrv_userdupcalls == 0 && nfsrv_nfsuserd == STARTSTOP)
3719 		wakeup(&nfsrv_userdupcalls);
3720 	NFSUNLOCKNAMEID();
3721 	NFSFREECRED(cred);
3722 	if (!error) {
3723 		m_freem(nd->nd_mrep);
3724 		error = nd->nd_repstat;
3725 	}
3726 out:
3727 	NFSEXITCODE(error);
3728 	return (error);
3729 }
3730 
3731 /*
3732  * This function is called from the nfssvc(2) system call, to update the
3733  * kernel user/group name list(s) for the V4 owner and ownergroup attributes.
3734  */
3735 int
3736 nfssvc_idname(struct nfsd_idargs *nidp)
3737 {
3738 	struct nfsusrgrp *nusrp, *usrp, *newusrp;
3739 	struct nfsrv_lughash *hp_name, *hp_idnum, *thp;
3740 	int i, group_locked, groupname_locked, user_locked, username_locked;
3741 	int error = 0;
3742 	u_char *cp;
3743 	gid_t *grps;
3744 	struct ucred *cr;
3745 	static int onethread = 0;
3746 	static time_t lasttime = 0;
3747 
3748 	if (nidp->nid_namelen <= 0 || nidp->nid_namelen > MAXHOSTNAMELEN) {
3749 		error = EINVAL;
3750 		goto out;
3751 	}
3752 	if (nidp->nid_flag & NFSID_INITIALIZE) {
3753 		cp = malloc(nidp->nid_namelen + 1, M_NFSSTRING, M_WAITOK);
3754 		error = copyin(nidp->nid_name, cp, nidp->nid_namelen);
3755 		if (error != 0) {
3756 			free(cp, M_NFSSTRING);
3757 			goto out;
3758 		}
3759 		if (atomic_cmpset_acq_int(&nfsrv_dnsnamelen, 0, 0) == 0) {
3760 			/*
3761 			 * Free up all the old stuff and reinitialize hash
3762 			 * lists.  All mutexes for both lists must be locked,
3763 			 * with the user/group name ones before the uid/gid
3764 			 * ones, to avoid a LOR.
3765 			 */
3766 			for (i = 0; i < nfsrv_lughashsize; i++)
3767 				mtx_lock(&nfsusernamehash[i].mtx);
3768 			for (i = 0; i < nfsrv_lughashsize; i++)
3769 				mtx_lock(&nfsuserhash[i].mtx);
3770 			for (i = 0; i < nfsrv_lughashsize; i++)
3771 				TAILQ_FOREACH_SAFE(usrp,
3772 				    &nfsuserhash[i].lughead, lug_numhash, nusrp)
3773 					nfsrv_removeuser(usrp, 1);
3774 			for (i = 0; i < nfsrv_lughashsize; i++)
3775 				mtx_unlock(&nfsuserhash[i].mtx);
3776 			for (i = 0; i < nfsrv_lughashsize; i++)
3777 				mtx_unlock(&nfsusernamehash[i].mtx);
3778 			for (i = 0; i < nfsrv_lughashsize; i++)
3779 				mtx_lock(&nfsgroupnamehash[i].mtx);
3780 			for (i = 0; i < nfsrv_lughashsize; i++)
3781 				mtx_lock(&nfsgrouphash[i].mtx);
3782 			for (i = 0; i < nfsrv_lughashsize; i++)
3783 				TAILQ_FOREACH_SAFE(usrp,
3784 				    &nfsgrouphash[i].lughead, lug_numhash,
3785 				    nusrp)
3786 					nfsrv_removeuser(usrp, 0);
3787 			for (i = 0; i < nfsrv_lughashsize; i++)
3788 				mtx_unlock(&nfsgrouphash[i].mtx);
3789 			for (i = 0; i < nfsrv_lughashsize; i++)
3790 				mtx_unlock(&nfsgroupnamehash[i].mtx);
3791 			free(nfsrv_dnsname, M_NFSSTRING);
3792 			nfsrv_dnsname = NULL;
3793 		}
3794 		if (nfsuserhash == NULL) {
3795 			/* Allocate the hash tables. */
3796 			nfsuserhash = malloc(sizeof(struct nfsrv_lughash) *
3797 			    nfsrv_lughashsize, M_NFSUSERGROUP, M_WAITOK |
3798 			    M_ZERO);
3799 			for (i = 0; i < nfsrv_lughashsize; i++)
3800 				mtx_init(&nfsuserhash[i].mtx, "nfsuidhash",
3801 				    NULL, MTX_DEF | MTX_DUPOK);
3802 			nfsusernamehash = malloc(sizeof(struct nfsrv_lughash) *
3803 			    nfsrv_lughashsize, M_NFSUSERGROUP, M_WAITOK |
3804 			    M_ZERO);
3805 			for (i = 0; i < nfsrv_lughashsize; i++)
3806 				mtx_init(&nfsusernamehash[i].mtx,
3807 				    "nfsusrhash", NULL, MTX_DEF |
3808 				    MTX_DUPOK);
3809 			nfsgrouphash = malloc(sizeof(struct nfsrv_lughash) *
3810 			    nfsrv_lughashsize, M_NFSUSERGROUP, M_WAITOK |
3811 			    M_ZERO);
3812 			for (i = 0; i < nfsrv_lughashsize; i++)
3813 				mtx_init(&nfsgrouphash[i].mtx, "nfsgidhash",
3814 				    NULL, MTX_DEF | MTX_DUPOK);
3815 			nfsgroupnamehash = malloc(sizeof(struct nfsrv_lughash) *
3816 			    nfsrv_lughashsize, M_NFSUSERGROUP, M_WAITOK |
3817 			    M_ZERO);
3818 			for (i = 0; i < nfsrv_lughashsize; i++)
3819 			    mtx_init(&nfsgroupnamehash[i].mtx,
3820 			    "nfsgrphash", NULL, MTX_DEF | MTX_DUPOK);
3821 		}
3822 		/* (Re)initialize the list heads. */
3823 		for (i = 0; i < nfsrv_lughashsize; i++)
3824 			TAILQ_INIT(&nfsuserhash[i].lughead);
3825 		for (i = 0; i < nfsrv_lughashsize; i++)
3826 			TAILQ_INIT(&nfsusernamehash[i].lughead);
3827 		for (i = 0; i < nfsrv_lughashsize; i++)
3828 			TAILQ_INIT(&nfsgrouphash[i].lughead);
3829 		for (i = 0; i < nfsrv_lughashsize; i++)
3830 			TAILQ_INIT(&nfsgroupnamehash[i].lughead);
3831 
3832 		/*
3833 		 * Put name in "DNS" string.
3834 		 */
3835 		nfsrv_dnsname = cp;
3836 		nfsrv_defaultuid = nidp->nid_uid;
3837 		nfsrv_defaultgid = nidp->nid_gid;
3838 		nfsrv_usercnt = 0;
3839 		nfsrv_usermax = nidp->nid_usermax;
3840 		atomic_store_rel_int(&nfsrv_dnsnamelen, nidp->nid_namelen);
3841 		goto out;
3842 	}
3843 
3844 	/*
3845 	 * malloc the new one now, so any potential sleep occurs before
3846 	 * manipulation of the lists.
3847 	 */
3848 	newusrp = malloc(sizeof(struct nfsusrgrp) + nidp->nid_namelen,
3849 	    M_NFSUSERGROUP, M_WAITOK | M_ZERO);
3850 	error = copyin(nidp->nid_name, newusrp->lug_name,
3851 	    nidp->nid_namelen);
3852 	if (error == 0 && nidp->nid_ngroup > 0 &&
3853 	    (nidp->nid_flag & NFSID_ADDUID) != 0) {
3854 		grps = malloc(sizeof(gid_t) * nidp->nid_ngroup, M_TEMP,
3855 		    M_WAITOK);
3856 		error = copyin(nidp->nid_grps, grps,
3857 		    sizeof(gid_t) * nidp->nid_ngroup);
3858 		if (error == 0) {
3859 			/*
3860 			 * Create a credential just like svc_getcred(),
3861 			 * but using the group list provided.
3862 			 */
3863 			cr = crget();
3864 			cr->cr_uid = cr->cr_ruid = cr->cr_svuid = nidp->nid_uid;
3865 			crsetgroups(cr, nidp->nid_ngroup, grps);
3866 			cr->cr_rgid = cr->cr_svgid = cr->cr_groups[0];
3867 			cr->cr_prison = &prison0;
3868 			prison_hold(cr->cr_prison);
3869 #ifdef MAC
3870 			mac_cred_associate_nfsd(cr);
3871 #endif
3872 			newusrp->lug_cred = cr;
3873 		}
3874 		free(grps, M_TEMP);
3875 	}
3876 	if (error) {
3877 		free(newusrp, M_NFSUSERGROUP);
3878 		goto out;
3879 	}
3880 	newusrp->lug_namelen = nidp->nid_namelen;
3881 
3882 	/*
3883 	 * The lock order is username[0]->[nfsrv_lughashsize - 1] followed
3884 	 * by uid[0]->[nfsrv_lughashsize - 1], with the same for group.
3885 	 * The flags user_locked, username_locked, group_locked and
3886 	 * groupname_locked are set to indicate all of those hash lists are
3887 	 * locked. hp_name != NULL  and hp_idnum != NULL indicates that
3888 	 * the respective one mutex is locked.
3889 	 */
3890 	user_locked = username_locked = group_locked = groupname_locked = 0;
3891 	hp_name = hp_idnum = NULL;
3892 
3893 	/*
3894 	 * Delete old entries, as required.
3895 	 */
3896 	if (nidp->nid_flag & (NFSID_DELUID | NFSID_ADDUID)) {
3897 		/* Must lock all username hash lists first, to avoid a LOR. */
3898 		for (i = 0; i < nfsrv_lughashsize; i++)
3899 			mtx_lock(&nfsusernamehash[i].mtx);
3900 		username_locked = 1;
3901 		hp_idnum = NFSUSERHASH(nidp->nid_uid);
3902 		mtx_lock(&hp_idnum->mtx);
3903 		TAILQ_FOREACH_SAFE(usrp, &hp_idnum->lughead, lug_numhash,
3904 		    nusrp) {
3905 			if (usrp->lug_uid == nidp->nid_uid)
3906 				nfsrv_removeuser(usrp, 1);
3907 		}
3908 	} else if (nidp->nid_flag & (NFSID_DELUSERNAME | NFSID_ADDUSERNAME)) {
3909 		hp_name = NFSUSERNAMEHASH(newusrp->lug_name,
3910 		    newusrp->lug_namelen);
3911 		mtx_lock(&hp_name->mtx);
3912 		TAILQ_FOREACH_SAFE(usrp, &hp_name->lughead, lug_namehash,
3913 		    nusrp) {
3914 			if (usrp->lug_namelen == newusrp->lug_namelen &&
3915 			    !NFSBCMP(usrp->lug_name, newusrp->lug_name,
3916 			    usrp->lug_namelen)) {
3917 				thp = NFSUSERHASH(usrp->lug_uid);
3918 				mtx_lock(&thp->mtx);
3919 				nfsrv_removeuser(usrp, 1);
3920 				mtx_unlock(&thp->mtx);
3921 			}
3922 		}
3923 		hp_idnum = NFSUSERHASH(nidp->nid_uid);
3924 		mtx_lock(&hp_idnum->mtx);
3925 	} else if (nidp->nid_flag & (NFSID_DELGID | NFSID_ADDGID)) {
3926 		/* Must lock all groupname hash lists first, to avoid a LOR. */
3927 		for (i = 0; i < nfsrv_lughashsize; i++)
3928 			mtx_lock(&nfsgroupnamehash[i].mtx);
3929 		groupname_locked = 1;
3930 		hp_idnum = NFSGROUPHASH(nidp->nid_gid);
3931 		mtx_lock(&hp_idnum->mtx);
3932 		TAILQ_FOREACH_SAFE(usrp, &hp_idnum->lughead, lug_numhash,
3933 		    nusrp) {
3934 			if (usrp->lug_gid == nidp->nid_gid)
3935 				nfsrv_removeuser(usrp, 0);
3936 		}
3937 	} else if (nidp->nid_flag & (NFSID_DELGROUPNAME | NFSID_ADDGROUPNAME)) {
3938 		hp_name = NFSGROUPNAMEHASH(newusrp->lug_name,
3939 		    newusrp->lug_namelen);
3940 		mtx_lock(&hp_name->mtx);
3941 		TAILQ_FOREACH_SAFE(usrp, &hp_name->lughead, lug_namehash,
3942 		    nusrp) {
3943 			if (usrp->lug_namelen == newusrp->lug_namelen &&
3944 			    !NFSBCMP(usrp->lug_name, newusrp->lug_name,
3945 			    usrp->lug_namelen)) {
3946 				thp = NFSGROUPHASH(usrp->lug_gid);
3947 				mtx_lock(&thp->mtx);
3948 				nfsrv_removeuser(usrp, 0);
3949 				mtx_unlock(&thp->mtx);
3950 			}
3951 		}
3952 		hp_idnum = NFSGROUPHASH(nidp->nid_gid);
3953 		mtx_lock(&hp_idnum->mtx);
3954 	}
3955 
3956 	/*
3957 	 * Now, we can add the new one.
3958 	 */
3959 	if (nidp->nid_usertimeout)
3960 		newusrp->lug_expiry = NFSD_MONOSEC + nidp->nid_usertimeout;
3961 	else
3962 		newusrp->lug_expiry = NFSD_MONOSEC + 5;
3963 	if (nidp->nid_flag & (NFSID_ADDUID | NFSID_ADDUSERNAME)) {
3964 		newusrp->lug_uid = nidp->nid_uid;
3965 		thp = NFSUSERHASH(newusrp->lug_uid);
3966 		mtx_assert(&thp->mtx, MA_OWNED);
3967 		TAILQ_INSERT_TAIL(&thp->lughead, newusrp, lug_numhash);
3968 		thp = NFSUSERNAMEHASH(newusrp->lug_name, newusrp->lug_namelen);
3969 		mtx_assert(&thp->mtx, MA_OWNED);
3970 		TAILQ_INSERT_TAIL(&thp->lughead, newusrp, lug_namehash);
3971 		atomic_add_int(&nfsrv_usercnt, 1);
3972 	} else if (nidp->nid_flag & (NFSID_ADDGID | NFSID_ADDGROUPNAME)) {
3973 		newusrp->lug_gid = nidp->nid_gid;
3974 		thp = NFSGROUPHASH(newusrp->lug_gid);
3975 		mtx_assert(&thp->mtx, MA_OWNED);
3976 		TAILQ_INSERT_TAIL(&thp->lughead, newusrp, lug_numhash);
3977 		thp = NFSGROUPNAMEHASH(newusrp->lug_name, newusrp->lug_namelen);
3978 		mtx_assert(&thp->mtx, MA_OWNED);
3979 		TAILQ_INSERT_TAIL(&thp->lughead, newusrp, lug_namehash);
3980 		atomic_add_int(&nfsrv_usercnt, 1);
3981 	} else {
3982 		if (newusrp->lug_cred != NULL)
3983 			crfree(newusrp->lug_cred);
3984 		free(newusrp, M_NFSUSERGROUP);
3985 	}
3986 
3987 	/*
3988 	 * Once per second, allow one thread to trim the cache.
3989 	 */
3990 	if (lasttime < NFSD_MONOSEC &&
3991 	    atomic_cmpset_acq_int(&onethread, 0, 1) != 0) {
3992 		/*
3993 		 * First, unlock the single mutexes, so that all entries
3994 		 * can be locked and any LOR is avoided.
3995 		 */
3996 		if (hp_name != NULL) {
3997 			mtx_unlock(&hp_name->mtx);
3998 			hp_name = NULL;
3999 		}
4000 		if (hp_idnum != NULL) {
4001 			mtx_unlock(&hp_idnum->mtx);
4002 			hp_idnum = NULL;
4003 		}
4004 
4005 		if ((nidp->nid_flag & (NFSID_DELUID | NFSID_ADDUID |
4006 		    NFSID_DELUSERNAME | NFSID_ADDUSERNAME)) != 0) {
4007 			if (username_locked == 0) {
4008 				for (i = 0; i < nfsrv_lughashsize; i++)
4009 					mtx_lock(&nfsusernamehash[i].mtx);
4010 				username_locked = 1;
4011 			}
4012 			KASSERT(user_locked == 0,
4013 			    ("nfssvc_idname: user_locked"));
4014 			for (i = 0; i < nfsrv_lughashsize; i++)
4015 				mtx_lock(&nfsuserhash[i].mtx);
4016 			user_locked = 1;
4017 			for (i = 0; i < nfsrv_lughashsize; i++) {
4018 				TAILQ_FOREACH_SAFE(usrp,
4019 				    &nfsuserhash[i].lughead, lug_numhash,
4020 				    nusrp)
4021 					if (usrp->lug_expiry < NFSD_MONOSEC)
4022 						nfsrv_removeuser(usrp, 1);
4023 			}
4024 			for (i = 0; i < nfsrv_lughashsize; i++) {
4025 				/*
4026 				 * Trim the cache using an approximate LRU
4027 				 * algorithm.  This code deletes the least
4028 				 * recently used entry on each hash list.
4029 				 */
4030 				if (nfsrv_usercnt <= nfsrv_usermax)
4031 					break;
4032 				usrp = TAILQ_FIRST(&nfsuserhash[i].lughead);
4033 				if (usrp != NULL)
4034 					nfsrv_removeuser(usrp, 1);
4035 			}
4036 		} else {
4037 			if (groupname_locked == 0) {
4038 				for (i = 0; i < nfsrv_lughashsize; i++)
4039 					mtx_lock(&nfsgroupnamehash[i].mtx);
4040 				groupname_locked = 1;
4041 			}
4042 			KASSERT(group_locked == 0,
4043 			    ("nfssvc_idname: group_locked"));
4044 			for (i = 0; i < nfsrv_lughashsize; i++)
4045 				mtx_lock(&nfsgrouphash[i].mtx);
4046 			group_locked = 1;
4047 			for (i = 0; i < nfsrv_lughashsize; i++) {
4048 				TAILQ_FOREACH_SAFE(usrp,
4049 				    &nfsgrouphash[i].lughead, lug_numhash,
4050 				    nusrp)
4051 					if (usrp->lug_expiry < NFSD_MONOSEC)
4052 						nfsrv_removeuser(usrp, 0);
4053 			}
4054 			for (i = 0; i < nfsrv_lughashsize; i++) {
4055 				/*
4056 				 * Trim the cache using an approximate LRU
4057 				 * algorithm.  This code deletes the least
4058 				 * recently user entry on each hash list.
4059 				 */
4060 				if (nfsrv_usercnt <= nfsrv_usermax)
4061 					break;
4062 				usrp = TAILQ_FIRST(&nfsgrouphash[i].lughead);
4063 				if (usrp != NULL)
4064 					nfsrv_removeuser(usrp, 0);
4065 			}
4066 		}
4067 		lasttime = NFSD_MONOSEC;
4068 		atomic_store_rel_int(&onethread, 0);
4069 	}
4070 
4071 	/* Now, unlock all locked mutexes. */
4072 	if (hp_idnum != NULL)
4073 		mtx_unlock(&hp_idnum->mtx);
4074 	if (hp_name != NULL)
4075 		mtx_unlock(&hp_name->mtx);
4076 	if (user_locked != 0)
4077 		for (i = 0; i < nfsrv_lughashsize; i++)
4078 			mtx_unlock(&nfsuserhash[i].mtx);
4079 	if (username_locked != 0)
4080 		for (i = 0; i < nfsrv_lughashsize; i++)
4081 			mtx_unlock(&nfsusernamehash[i].mtx);
4082 	if (group_locked != 0)
4083 		for (i = 0; i < nfsrv_lughashsize; i++)
4084 			mtx_unlock(&nfsgrouphash[i].mtx);
4085 	if (groupname_locked != 0)
4086 		for (i = 0; i < nfsrv_lughashsize; i++)
4087 			mtx_unlock(&nfsgroupnamehash[i].mtx);
4088 out:
4089 	NFSEXITCODE(error);
4090 	return (error);
4091 }
4092 
4093 /*
4094  * Remove a user/group name element.
4095  */
4096 static void
4097 nfsrv_removeuser(struct nfsusrgrp *usrp, int isuser)
4098 {
4099 	struct nfsrv_lughash *hp;
4100 
4101 	if (isuser != 0) {
4102 		hp = NFSUSERHASH(usrp->lug_uid);
4103 		mtx_assert(&hp->mtx, MA_OWNED);
4104 		TAILQ_REMOVE(&hp->lughead, usrp, lug_numhash);
4105 		hp = NFSUSERNAMEHASH(usrp->lug_name, usrp->lug_namelen);
4106 		mtx_assert(&hp->mtx, MA_OWNED);
4107 		TAILQ_REMOVE(&hp->lughead, usrp, lug_namehash);
4108 	} else {
4109 		hp = NFSGROUPHASH(usrp->lug_gid);
4110 		mtx_assert(&hp->mtx, MA_OWNED);
4111 		TAILQ_REMOVE(&hp->lughead, usrp, lug_numhash);
4112 		hp = NFSGROUPNAMEHASH(usrp->lug_name, usrp->lug_namelen);
4113 		mtx_assert(&hp->mtx, MA_OWNED);
4114 		TAILQ_REMOVE(&hp->lughead, usrp, lug_namehash);
4115 	}
4116 	atomic_add_int(&nfsrv_usercnt, -1);
4117 	if (usrp->lug_cred != NULL)
4118 		crfree(usrp->lug_cred);
4119 	free(usrp, M_NFSUSERGROUP);
4120 }
4121 
4122 /*
4123  * Free up all the allocations related to the name<-->id cache.
4124  * This function should only be called when the nfsuserd daemon isn't
4125  * running, since it doesn't do any locking.
4126  * This function is meant to be used when the nfscommon module is unloaded.
4127  */
4128 void
4129 nfsrv_cleanusergroup(void)
4130 {
4131 	struct nfsrv_lughash *hp, *hp2;
4132 	struct nfsusrgrp *nusrp, *usrp;
4133 	int i;
4134 
4135 	if (nfsuserhash == NULL)
4136 		return;
4137 
4138 	for (i = 0; i < nfsrv_lughashsize; i++) {
4139 		hp = &nfsuserhash[i];
4140 		TAILQ_FOREACH_SAFE(usrp, &hp->lughead, lug_numhash, nusrp) {
4141 			TAILQ_REMOVE(&hp->lughead, usrp, lug_numhash);
4142 			hp2 = NFSUSERNAMEHASH(usrp->lug_name,
4143 			    usrp->lug_namelen);
4144 			TAILQ_REMOVE(&hp2->lughead, usrp, lug_namehash);
4145 			if (usrp->lug_cred != NULL)
4146 				crfree(usrp->lug_cred);
4147 			free(usrp, M_NFSUSERGROUP);
4148 		}
4149 		hp = &nfsgrouphash[i];
4150 		TAILQ_FOREACH_SAFE(usrp, &hp->lughead, lug_numhash, nusrp) {
4151 			TAILQ_REMOVE(&hp->lughead, usrp, lug_numhash);
4152 			hp2 = NFSGROUPNAMEHASH(usrp->lug_name,
4153 			    usrp->lug_namelen);
4154 			TAILQ_REMOVE(&hp2->lughead, usrp, lug_namehash);
4155 			if (usrp->lug_cred != NULL)
4156 				crfree(usrp->lug_cred);
4157 			free(usrp, M_NFSUSERGROUP);
4158 		}
4159 		mtx_destroy(&nfsuserhash[i].mtx);
4160 		mtx_destroy(&nfsusernamehash[i].mtx);
4161 		mtx_destroy(&nfsgroupnamehash[i].mtx);
4162 		mtx_destroy(&nfsgrouphash[i].mtx);
4163 	}
4164 	free(nfsuserhash, M_NFSUSERGROUP);
4165 	free(nfsusernamehash, M_NFSUSERGROUP);
4166 	free(nfsgrouphash, M_NFSUSERGROUP);
4167 	free(nfsgroupnamehash, M_NFSUSERGROUP);
4168 	free(nfsrv_dnsname, M_NFSSTRING);
4169 }
4170 
4171 /*
4172  * This function scans a byte string and checks for UTF-8 compliance.
4173  * It returns 0 if it conforms and NFSERR_INVAL if not.
4174  */
4175 int
4176 nfsrv_checkutf8(u_int8_t *cp, int len)
4177 {
4178 	u_int32_t val = 0x0;
4179 	int cnt = 0, gotd = 0, shift = 0;
4180 	u_int8_t byte;
4181 	static int utf8_shift[5] = { 7, 11, 16, 21, 26 };
4182 	int error = 0;
4183 
4184 	/*
4185 	 * Here are what the variables are used for:
4186 	 * val - the calculated value of a multibyte char, used to check
4187 	 *       that it was coded with the correct range
4188 	 * cnt - the number of 10xxxxxx bytes to follow
4189 	 * gotd - set for a char of Dxxx, so D800<->DFFF can be checked for
4190 	 * shift - lower order bits of range (ie. "val >> shift" should
4191 	 *       not be 0, in other words, dividing by the lower bound
4192 	 *       of the range should get a non-zero value)
4193 	 * byte - used to calculate cnt
4194 	 */
4195 	while (len > 0) {
4196 		if (cnt > 0) {
4197 			/* This handles the 10xxxxxx bytes */
4198 			if ((*cp & 0xc0) != 0x80 ||
4199 			    (gotd && (*cp & 0x20))) {
4200 				error = NFSERR_INVAL;
4201 				goto out;
4202 			}
4203 			gotd = 0;
4204 			val <<= 6;
4205 			val |= (*cp & 0x3f);
4206 			cnt--;
4207 			if (cnt == 0 && (val >> shift) == 0x0) {
4208 				error = NFSERR_INVAL;
4209 				goto out;
4210 			}
4211 		} else if (*cp & 0x80) {
4212 			/* first byte of multi byte char */
4213 			byte = *cp;
4214 			while ((byte & 0x40) && cnt < 6) {
4215 				cnt++;
4216 				byte <<= 1;
4217 			}
4218 			if (cnt == 0 || cnt == 6) {
4219 				error = NFSERR_INVAL;
4220 				goto out;
4221 			}
4222 			val = (*cp & (0x3f >> cnt));
4223 			shift = utf8_shift[cnt - 1];
4224 			if (cnt == 2 && val == 0xd)
4225 				/* Check for the 0xd800-0xdfff case */
4226 				gotd = 1;
4227 		}
4228 		cp++;
4229 		len--;
4230 	}
4231 	if (cnt > 0)
4232 		error = NFSERR_INVAL;
4233 
4234 out:
4235 	NFSEXITCODE(error);
4236 	return (error);
4237 }
4238 
4239 /*
4240  * Parse the xdr for an NFSv4 FsLocations attribute. Return two malloc'd
4241  * strings, one with the root path in it and the other with the list of
4242  * locations. The list is in the same format as is found in nfr_refs.
4243  * It is a "," separated list of entries, where each of them is of the
4244  * form <server>:<rootpath>. For example
4245  * "nfsv4-test:/sub2,nfsv4-test2:/user/mnt,nfsv4-test2:/user/mnt2"
4246  * The nilp argument is set to 1 for the special case of a null fs_root
4247  * and an empty server list.
4248  * It returns NFSERR_BADXDR, if the xdr can't be parsed and returns the
4249  * number of xdr bytes parsed in sump.
4250  */
4251 static int
4252 nfsrv_getrefstr(struct nfsrv_descript *nd, u_char **fsrootp, u_char **srvp,
4253     int *sump, int *nilp)
4254 {
4255 	u_int32_t *tl;
4256 	u_char *cp = NULL, *cp2 = NULL, *cp3, *str;
4257 	int i, j, len, stringlen, cnt, slen, siz, xdrsum, error = 0, nsrv;
4258 	struct list {
4259 		SLIST_ENTRY(list) next;
4260 		int len;
4261 		u_char host[1];
4262 	} *lsp, *nlsp;
4263 	SLIST_HEAD(, list) head;
4264 
4265 	*fsrootp = NULL;
4266 	*srvp = NULL;
4267 	*nilp = 0;
4268 
4269 	/*
4270 	 * Get the fs_root path and check for the special case of null path
4271 	 * and 0 length server list.
4272 	 */
4273 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
4274 	len = fxdr_unsigned(int, *tl);
4275 	if (len < 0 || len > 10240) {
4276 		error = NFSERR_BADXDR;
4277 		goto nfsmout;
4278 	}
4279 	if (len == 0) {
4280 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
4281 		if (*tl != 0) {
4282 			error = NFSERR_BADXDR;
4283 			goto nfsmout;
4284 		}
4285 		*nilp = 1;
4286 		*sump = 2 * NFSX_UNSIGNED;
4287 		error = 0;
4288 		goto nfsmout;
4289 	}
4290 	cp = malloc(len + 1, M_NFSSTRING, M_WAITOK);
4291 	error = nfsrv_mtostr(nd, cp, len);
4292 	if (!error) {
4293 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
4294 		cnt = fxdr_unsigned(int, *tl);
4295 		if (cnt <= 0)
4296 			error = NFSERR_BADXDR;
4297 	}
4298 	if (error)
4299 		goto nfsmout;
4300 
4301 	/*
4302 	 * Now, loop through the location list and make up the srvlist.
4303 	 */
4304 	xdrsum = (2 * NFSX_UNSIGNED) + NFSM_RNDUP(len);
4305 	cp2 = cp3 = malloc(1024, M_NFSSTRING, M_WAITOK);
4306 	slen = 1024;
4307 	siz = 0;
4308 	for (i = 0; i < cnt; i++) {
4309 		SLIST_INIT(&head);
4310 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
4311 		nsrv = fxdr_unsigned(int, *tl);
4312 		if (nsrv <= 0) {
4313 			error = NFSERR_BADXDR;
4314 			goto nfsmout;
4315 		}
4316 
4317 		/*
4318 		 * Handle the first server by putting it in the srvstr.
4319 		 */
4320 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
4321 		len = fxdr_unsigned(int, *tl);
4322 		if (len <= 0 || len > 1024) {
4323 			error = NFSERR_BADXDR;
4324 			goto nfsmout;
4325 		}
4326 		nfsrv_refstrbigenough(siz + len + 3, &cp2, &cp3, &slen);
4327 		if (cp3 != cp2) {
4328 			*cp3++ = ',';
4329 			siz++;
4330 		}
4331 		error = nfsrv_mtostr(nd, cp3, len);
4332 		if (error)
4333 			goto nfsmout;
4334 		cp3 += len;
4335 		*cp3++ = ':';
4336 		siz += (len + 1);
4337 		xdrsum += (2 * NFSX_UNSIGNED) + NFSM_RNDUP(len);
4338 		for (j = 1; j < nsrv; j++) {
4339 			/*
4340 			 * Yuck, put them in an slist and process them later.
4341 			 */
4342 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
4343 			len = fxdr_unsigned(int, *tl);
4344 			if (len <= 0 || len > 1024) {
4345 				error = NFSERR_BADXDR;
4346 				goto nfsmout;
4347 			}
4348 			lsp = (struct list *)malloc(sizeof (struct list)
4349 			    + len, M_TEMP, M_WAITOK);
4350 			error = nfsrv_mtostr(nd, lsp->host, len);
4351 			if (error)
4352 				goto nfsmout;
4353 			xdrsum += NFSX_UNSIGNED + NFSM_RNDUP(len);
4354 			lsp->len = len;
4355 			SLIST_INSERT_HEAD(&head, lsp, next);
4356 		}
4357 
4358 		/*
4359 		 * Finally, we can get the path.
4360 		 */
4361 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
4362 		len = fxdr_unsigned(int, *tl);
4363 		if (len <= 0 || len > 1024) {
4364 			error = NFSERR_BADXDR;
4365 			goto nfsmout;
4366 		}
4367 		nfsrv_refstrbigenough(siz + len + 1, &cp2, &cp3, &slen);
4368 		error = nfsrv_mtostr(nd, cp3, len);
4369 		if (error)
4370 			goto nfsmout;
4371 		xdrsum += NFSX_UNSIGNED + NFSM_RNDUP(len);
4372 		str = cp3;
4373 		stringlen = len;
4374 		cp3 += len;
4375 		siz += len;
4376 		SLIST_FOREACH_SAFE(lsp, &head, next, nlsp) {
4377 			nfsrv_refstrbigenough(siz + lsp->len + stringlen + 3,
4378 			    &cp2, &cp3, &slen);
4379 			*cp3++ = ',';
4380 			NFSBCOPY(lsp->host, cp3, lsp->len);
4381 			cp3 += lsp->len;
4382 			*cp3++ = ':';
4383 			NFSBCOPY(str, cp3, stringlen);
4384 			cp3 += stringlen;
4385 			*cp3 = '\0';
4386 			siz += (lsp->len + stringlen + 2);
4387 			free(lsp, M_TEMP);
4388 		}
4389 	}
4390 	*fsrootp = cp;
4391 	*srvp = cp2;
4392 	*sump = xdrsum;
4393 	NFSEXITCODE2(0, nd);
4394 	return (0);
4395 nfsmout:
4396 	if (cp != NULL)
4397 		free(cp, M_NFSSTRING);
4398 	if (cp2 != NULL)
4399 		free(cp2, M_NFSSTRING);
4400 	NFSEXITCODE2(error, nd);
4401 	return (error);
4402 }
4403 
4404 /*
4405  * Make the malloc'd space large enough. This is a pain, but the xdr
4406  * doesn't set an upper bound on the side, so...
4407  */
4408 static void
4409 nfsrv_refstrbigenough(int siz, u_char **cpp, u_char **cpp2, int *slenp)
4410 {
4411 	u_char *cp;
4412 	int i;
4413 
4414 	if (siz <= *slenp)
4415 		return;
4416 	cp = malloc(siz + 1024, M_NFSSTRING, M_WAITOK);
4417 	NFSBCOPY(*cpp, cp, *slenp);
4418 	free(*cpp, M_NFSSTRING);
4419 	i = *cpp2 - *cpp;
4420 	*cpp = cp;
4421 	*cpp2 = cp + i;
4422 	*slenp = siz + 1024;
4423 }
4424 
4425 /*
4426  * Initialize the reply header data structures.
4427  */
4428 void
4429 nfsrvd_rephead(struct nfsrv_descript *nd)
4430 {
4431 	struct mbuf *mreq;
4432 
4433 	if ((nd->nd_flag & ND_EXTPG) != 0) {
4434 		mreq = mb_alloc_ext_plus_pages(PAGE_SIZE, M_WAITOK);
4435 		nd->nd_mreq = nd->nd_mb = mreq;
4436 		nd->nd_bpos = (char *)(void *)
4437 		    PHYS_TO_DMAP(mreq->m_epg_pa[0]);
4438 		nd->nd_bextpg = 0;
4439 		nd->nd_bextpgsiz = PAGE_SIZE;
4440 	} else {
4441 		/*
4442 		 * If this is a big reply, use a cluster.
4443 		 */
4444 		if ((nd->nd_flag & ND_GSSINITREPLY) == 0 &&
4445 		    nfs_bigreply[nd->nd_procnum]) {
4446 			NFSMCLGET(mreq, M_WAITOK);
4447 			nd->nd_mreq = mreq;
4448 			nd->nd_mb = mreq;
4449 		} else {
4450 			NFSMGET(mreq);
4451 			nd->nd_mreq = mreq;
4452 			nd->nd_mb = mreq;
4453 		}
4454 		nd->nd_bpos = mtod(mreq, char *);
4455 		mreq->m_len = 0;
4456 	}
4457 
4458 	if ((nd->nd_flag & ND_GSSINITREPLY) == 0)
4459 		NFSM_BUILD(nd->nd_errp, int *, NFSX_UNSIGNED);
4460 }
4461 
4462 /*
4463  * Lock a socket against others.
4464  * Currently used to serialize connect/disconnect attempts.
4465  */
4466 int
4467 newnfs_sndlock(int *flagp)
4468 {
4469 	struct timespec ts;
4470 
4471 	NFSLOCKSOCK();
4472 	while (*flagp & NFSR_SNDLOCK) {
4473 		*flagp |= NFSR_WANTSND;
4474 		ts.tv_sec = 0;
4475 		ts.tv_nsec = 0;
4476 		(void) nfsmsleep((caddr_t)flagp, NFSSOCKMUTEXPTR,
4477 		    PZERO - 1, "nfsndlck", &ts);
4478 	}
4479 	*flagp |= NFSR_SNDLOCK;
4480 	NFSUNLOCKSOCK();
4481 	return (0);
4482 }
4483 
4484 /*
4485  * Unlock the stream socket for others.
4486  */
4487 void
4488 newnfs_sndunlock(int *flagp)
4489 {
4490 
4491 	NFSLOCKSOCK();
4492 	if ((*flagp & NFSR_SNDLOCK) == 0)
4493 		panic("nfs sndunlock");
4494 	*flagp &= ~NFSR_SNDLOCK;
4495 	if (*flagp & NFSR_WANTSND) {
4496 		*flagp &= ~NFSR_WANTSND;
4497 		wakeup((caddr_t)flagp);
4498 	}
4499 	NFSUNLOCKSOCK();
4500 }
4501 
4502 int
4503 nfsv4_getipaddr(struct nfsrv_descript *nd, struct sockaddr_in *sin,
4504     struct sockaddr_in6 *sin6, sa_family_t *saf, int *isudp)
4505 {
4506 	struct in_addr saddr;
4507 	uint32_t portnum, *tl;
4508 	int i, j, k;
4509 	sa_family_t af = AF_UNSPEC;
4510 	char addr[64], protocol[5], *cp;
4511 	int cantparse = 0, error = 0;
4512 	uint16_t portv;
4513 
4514 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
4515 	i = fxdr_unsigned(int, *tl);
4516 	if (i >= 3 && i <= 4) {
4517 		error = nfsrv_mtostr(nd, protocol, i);
4518 		if (error)
4519 			goto nfsmout;
4520 		if (strcmp(protocol, "tcp") == 0) {
4521 			af = AF_INET;
4522 			*isudp = 0;
4523 		} else if (strcmp(protocol, "udp") == 0) {
4524 			af = AF_INET;
4525 			*isudp = 1;
4526 		} else if (strcmp(protocol, "tcp6") == 0) {
4527 			af = AF_INET6;
4528 			*isudp = 0;
4529 		} else if (strcmp(protocol, "udp6") == 0) {
4530 			af = AF_INET6;
4531 			*isudp = 1;
4532 		} else
4533 			cantparse = 1;
4534 	} else {
4535 		cantparse = 1;
4536 		if (i > 0) {
4537 			error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
4538 			if (error)
4539 				goto nfsmout;
4540 		}
4541 	}
4542 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
4543 	i = fxdr_unsigned(int, *tl);
4544 	if (i < 0) {
4545 		error = NFSERR_BADXDR;
4546 		goto nfsmout;
4547 	} else if (cantparse == 0 && i >= 11 && i < 64) {
4548 		/*
4549 		 * The shortest address is 11chars and the longest is < 64.
4550 		 */
4551 		error = nfsrv_mtostr(nd, addr, i);
4552 		if (error)
4553 			goto nfsmout;
4554 
4555 		/* Find the port# at the end and extract that. */
4556 		i = strlen(addr);
4557 		k = 0;
4558 		cp = &addr[i - 1];
4559 		/* Count back two '.'s from end to get port# field. */
4560 		for (j = 0; j < i; j++) {
4561 			if (*cp == '.') {
4562 				k++;
4563 				if (k == 2)
4564 					break;
4565 			}
4566 			cp--;
4567 		}
4568 		if (k == 2) {
4569 			/*
4570 			 * The NFSv4 port# is appended as .N.N, where N is
4571 			 * a decimal # in the range 0-255, just like an inet4
4572 			 * address. Cheat and use inet_aton(), which will
4573 			 * return a Class A address and then shift the high
4574 			 * order 8bits over to convert it to the port#.
4575 			 */
4576 			*cp++ = '\0';
4577 			if (inet_aton(cp, &saddr) == 1) {
4578 				portnum = ntohl(saddr.s_addr);
4579 				portv = (uint16_t)((portnum >> 16) |
4580 				    (portnum & 0xff));
4581 			} else
4582 				cantparse = 1;
4583 		} else
4584 			cantparse = 1;
4585 		if (cantparse == 0) {
4586 			if (af == AF_INET) {
4587 				if (inet_pton(af, addr, &sin->sin_addr) == 1) {
4588 					sin->sin_len = sizeof(*sin);
4589 					sin->sin_family = AF_INET;
4590 					sin->sin_port = htons(portv);
4591 					*saf = af;
4592 					return (0);
4593 				}
4594 			} else {
4595 				if (inet_pton(af, addr, &sin6->sin6_addr)
4596 				    == 1) {
4597 					sin6->sin6_len = sizeof(*sin6);
4598 					sin6->sin6_family = AF_INET6;
4599 					sin6->sin6_port = htons(portv);
4600 					*saf = af;
4601 					return (0);
4602 				}
4603 			}
4604 		}
4605 	} else {
4606 		if (i > 0) {
4607 			error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
4608 			if (error)
4609 				goto nfsmout;
4610 		}
4611 	}
4612 	error = EPERM;
4613 nfsmout:
4614 	return (error);
4615 }
4616 
4617 /*
4618  * Handle an NFSv4.1 Sequence request for the session.
4619  * If reply != NULL, use it to return the cached reply, as required.
4620  * The client gets a cached reply via this call for callbacks, however the
4621  * server gets a cached reply via the nfsv4_seqsess_cacherep() call.
4622  */
4623 int
4624 nfsv4_seqsession(uint32_t seqid, uint32_t slotid, uint32_t highslot,
4625     struct nfsslot *slots, struct mbuf **reply, uint16_t maxslot)
4626 {
4627 	struct mbuf *m;
4628 	int error;
4629 
4630 	error = 0;
4631 	if (reply != NULL)
4632 		*reply = NULL;
4633 	if (slotid > maxslot)
4634 		return (NFSERR_BADSLOT);
4635 	if (seqid == slots[slotid].nfssl_seq) {
4636 		/* A retry. */
4637 		if (slots[slotid].nfssl_inprog != 0)
4638 			error = NFSERR_DELAY;
4639 		else if (slots[slotid].nfssl_reply != NULL) {
4640 			if (reply != NULL) {
4641 				m = m_copym(slots[slotid].nfssl_reply, 0,
4642 				    M_COPYALL, M_NOWAIT);
4643 				if (m != NULL)
4644 					*reply = m;
4645 				else {
4646 					*reply = slots[slotid].nfssl_reply;
4647 					slots[slotid].nfssl_reply = NULL;
4648 				}
4649 			}
4650 			slots[slotid].nfssl_inprog = 1;
4651 			error = NFSERR_REPLYFROMCACHE;
4652 		} else
4653 			/* No reply cached, so just do it. */
4654 			slots[slotid].nfssl_inprog = 1;
4655 	} else if ((slots[slotid].nfssl_seq + 1) == seqid) {
4656 		if (slots[slotid].nfssl_reply != NULL)
4657 			m_freem(slots[slotid].nfssl_reply);
4658 		slots[slotid].nfssl_reply = NULL;
4659 		slots[slotid].nfssl_inprog = 1;
4660 		slots[slotid].nfssl_seq++;
4661 	} else
4662 		error = NFSERR_SEQMISORDERED;
4663 	return (error);
4664 }
4665 
4666 /*
4667  * Cache this reply for the slot.
4668  * Use the "rep" argument to return the cached reply if repstat is set to
4669  * NFSERR_REPLYFROMCACHE. The client never sets repstat to this value.
4670  */
4671 void
4672 nfsv4_seqsess_cacherep(uint32_t slotid, struct nfsslot *slots, int repstat,
4673    struct mbuf **rep)
4674 {
4675 	struct mbuf *m;
4676 
4677 	if (repstat == NFSERR_REPLYFROMCACHE) {
4678 		if (slots[slotid].nfssl_reply != NULL) {
4679 			/*
4680 			 * We cannot sleep here, but copy will usually
4681 			 * succeed.
4682 			 */
4683 			m = m_copym(slots[slotid].nfssl_reply, 0, M_COPYALL,
4684 			    M_NOWAIT);
4685 			if (m != NULL)
4686 				*rep = m;
4687 			else {
4688 				/*
4689 				 * Multiple retries would be extremely rare,
4690 				 * so using the cached reply will likely
4691 				 * be ok.
4692 				 */
4693 				*rep = slots[slotid].nfssl_reply;
4694 				slots[slotid].nfssl_reply = NULL;
4695 			}
4696 		} else
4697 			*rep = NULL;
4698 	} else {
4699 		if (slots[slotid].nfssl_reply != NULL)
4700 			m_freem(slots[slotid].nfssl_reply);
4701 		slots[slotid].nfssl_reply = *rep;
4702 	}
4703 	slots[slotid].nfssl_inprog = 0;
4704 }
4705 
4706 /*
4707  * Generate the xdr for an NFSv4.1 Sequence Operation.
4708  */
4709 void
4710 nfsv4_setsequence(struct nfsmount *nmp, struct nfsrv_descript *nd,
4711     struct nfsclsession *sep, int dont_replycache)
4712 {
4713 	uint32_t *tl, slotseq = 0;
4714 	int error, maxslot, slotpos;
4715 	uint8_t sessionid[NFSX_V4SESSIONID];
4716 
4717 	error = nfsv4_sequencelookup(nmp, sep, &slotpos, &maxslot, &slotseq,
4718 	    sessionid);
4719 	nd->nd_maxreq = sep->nfsess_maxreq;
4720 	nd->nd_maxresp = sep->nfsess_maxresp;
4721 
4722 	/* Build the Sequence arguments. */
4723 	NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 4 * NFSX_UNSIGNED);
4724 	nd->nd_sequence = tl;
4725 	bcopy(sessionid, tl, NFSX_V4SESSIONID);
4726 	tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
4727 	nd->nd_slotseq = tl;
4728 	if (error == 0) {
4729 		nd->nd_flag |= ND_HASSLOTID;
4730 		nd->nd_slotid = slotpos;
4731 		*tl++ = txdr_unsigned(slotseq);
4732 		*tl++ = txdr_unsigned(slotpos);
4733 		*tl++ = txdr_unsigned(maxslot);
4734 		if (dont_replycache == 0)
4735 			*tl = newnfs_true;
4736 		else
4737 			*tl = newnfs_false;
4738 	} else {
4739 		/*
4740 		 * There are two errors and the rest of the session can
4741 		 * just be zeros.
4742 		 * NFSERR_BADSESSION: This bad session should just generate
4743 		 *    the same error again when the RPC is retried.
4744 		 * ESTALE: A forced dismount is in progress and will cause the
4745 		 *    RPC to fail later.
4746 		 */
4747 		*tl++ = 0;
4748 		*tl++ = 0;
4749 		*tl++ = 0;
4750 		*tl = 0;
4751 	}
4752 	nd->nd_flag |= ND_HASSEQUENCE;
4753 }
4754 
4755 int
4756 nfsv4_sequencelookup(struct nfsmount *nmp, struct nfsclsession *sep,
4757     int *slotposp, int *maxslotp, uint32_t *slotseqp, uint8_t *sessionid)
4758 {
4759 	int i, maxslot, slotpos;
4760 	uint64_t bitval;
4761 
4762 	/* Find an unused slot. */
4763 	slotpos = -1;
4764 	maxslot = -1;
4765 	mtx_lock(&sep->nfsess_mtx);
4766 	do {
4767 		if (nmp != NULL && sep->nfsess_defunct != 0) {
4768 			/* Just return the bad session. */
4769 			bcopy(sep->nfsess_sessionid, sessionid,
4770 			    NFSX_V4SESSIONID);
4771 			mtx_unlock(&sep->nfsess_mtx);
4772 			return (NFSERR_BADSESSION);
4773 		}
4774 		bitval = 1;
4775 		for (i = 0; i < sep->nfsess_foreslots; i++) {
4776 			if ((bitval & sep->nfsess_slots) == 0) {
4777 				slotpos = i;
4778 				sep->nfsess_slots |= bitval;
4779 				sep->nfsess_slotseq[i]++;
4780 				*slotseqp = sep->nfsess_slotseq[i];
4781 				break;
4782 			}
4783 			bitval <<= 1;
4784 		}
4785 		if (slotpos == -1) {
4786 			/*
4787 			 * If a forced dismount is in progress, just return.
4788 			 * This RPC attempt will fail when it calls
4789 			 * newnfs_request().
4790 			 */
4791 			if (nmp != NULL && NFSCL_FORCEDISM(nmp->nm_mountp)) {
4792 				mtx_unlock(&sep->nfsess_mtx);
4793 				return (ESTALE);
4794 			}
4795 			/* Wake up once/sec, to check for a forced dismount. */
4796 			(void)mtx_sleep(&sep->nfsess_slots, &sep->nfsess_mtx,
4797 			    PZERO, "nfsclseq", hz);
4798 		}
4799 	} while (slotpos == -1);
4800 	/* Now, find the highest slot in use. (nfsc_slots is 64bits) */
4801 	bitval = 1;
4802 	for (i = 0; i < 64; i++) {
4803 		if ((bitval & sep->nfsess_slots) != 0)
4804 			maxslot = i;
4805 		bitval <<= 1;
4806 	}
4807 	bcopy(sep->nfsess_sessionid, sessionid, NFSX_V4SESSIONID);
4808 	mtx_unlock(&sep->nfsess_mtx);
4809 	*slotposp = slotpos;
4810 	*maxslotp = maxslot;
4811 	return (0);
4812 }
4813 
4814 /*
4815  * Free a session slot.
4816  */
4817 void
4818 nfsv4_freeslot(struct nfsclsession *sep, int slot, bool resetseq)
4819 {
4820 	uint64_t bitval;
4821 
4822 	bitval = 1;
4823 	if (slot > 0)
4824 		bitval <<= slot;
4825 	mtx_lock(&sep->nfsess_mtx);
4826 	if (resetseq)
4827 		sep->nfsess_slotseq[slot]--;
4828 	if ((bitval & sep->nfsess_slots) == 0)
4829 		printf("freeing free slot!!\n");
4830 	sep->nfsess_slots &= ~bitval;
4831 	wakeup(&sep->nfsess_slots);
4832 	mtx_unlock(&sep->nfsess_mtx);
4833 }
4834 
4835 /*
4836  * Search for a matching pnfsd DS, based on the nmp arg.
4837  * Return one if found, NULL otherwise.
4838  */
4839 struct nfsdevice *
4840 nfsv4_findmirror(struct nfsmount *nmp)
4841 {
4842 	struct nfsdevice *ds;
4843 
4844 	mtx_assert(NFSDDSMUTEXPTR, MA_OWNED);
4845 	/*
4846 	 * Search the DS server list for a match with nmp.
4847 	 */
4848 	if (nfsrv_devidcnt == 0)
4849 		return (NULL);
4850 	TAILQ_FOREACH(ds, &nfsrv_devidhead, nfsdev_list) {
4851 		if (ds->nfsdev_nmp == nmp) {
4852 			NFSCL_DEBUG(4, "nfsv4_findmirror: fnd main ds\n");
4853 			break;
4854 		}
4855 	}
4856 	return (ds);
4857 }
4858 
4859 /*
4860  * Fill in the fields of "struct nfsrv_descript".
4861  */
4862 void
4863 nfsm_set(struct nfsrv_descript *nd, u_int offs)
4864 {
4865 	struct mbuf *m;
4866 	int rlen;
4867 
4868 	m = nd->nd_mb;
4869 	if ((m->m_flags & M_EXTPG) != 0) {
4870 		nd->nd_bextpg = 0;
4871 		while (offs > 0) {
4872 			if (nd->nd_bextpg == 0)
4873 				rlen = m_epg_pagelen(m, 0, m->m_epg_1st_off);
4874 			else
4875 				rlen = m_epg_pagelen(m, nd->nd_bextpg, 0);
4876 			if (offs <= rlen)
4877 				break;
4878 			offs -= rlen;
4879 			nd->nd_bextpg++;
4880 			if (nd->nd_bextpg == m->m_epg_npgs) {
4881 				printf("nfsm_set: build offs "
4882 				    "out of range\n");
4883 				nd->nd_bextpg--;
4884 				break;
4885 			}
4886 		}
4887 		nd->nd_bpos = (char *)(void *)
4888 		    PHYS_TO_DMAP(m->m_epg_pa[nd->nd_bextpg]);
4889 		if (nd->nd_bextpg == 0)
4890 			nd->nd_bpos += m->m_epg_1st_off;
4891 		if (offs > 0) {
4892 			nd->nd_bpos += offs;
4893 			nd->nd_bextpgsiz = rlen - offs;
4894 		} else if (nd->nd_bextpg == 0)
4895 			nd->nd_bextpgsiz = PAGE_SIZE - m->m_epg_1st_off;
4896 		else
4897 			nd->nd_bextpgsiz = PAGE_SIZE;
4898 	} else
4899 		nd->nd_bpos = mtod(m, char *) + offs;
4900 }
4901 
4902 /*
4903  * Grow a ext_pgs mbuf list.  Either allocate another page or add
4904  * an mbuf to the list.
4905  */
4906 struct mbuf *
4907 nfsm_add_ext_pgs(struct mbuf *m, int maxextsiz, int *bextpg)
4908 {
4909 	struct mbuf *mp;
4910 	vm_page_t pg;
4911 
4912 	if ((m->m_epg_npgs + 1) * PAGE_SIZE > maxextsiz) {
4913 		mp = mb_alloc_ext_plus_pages(PAGE_SIZE, M_WAITOK);
4914 		*bextpg = 0;
4915 		m->m_next = mp;
4916 	} else {
4917 		do {
4918 			pg = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL |
4919 			    VM_ALLOC_NOOBJ | VM_ALLOC_NODUMP |
4920 			    VM_ALLOC_WIRED);
4921 			if (pg == NULL)
4922 				vm_wait(NULL);
4923 		} while (pg == NULL);
4924 		m->m_epg_pa[m->m_epg_npgs] = VM_PAGE_TO_PHYS(pg);
4925 		*bextpg = m->m_epg_npgs;
4926 		m->m_epg_npgs++;
4927 		m->m_epg_last_len = 0;
4928 		mp = m;
4929 	}
4930 	return (mp);
4931 }
4932