xref: /freebsd/sys/fs/nfsserver/nfs_nfsdsocket.c (revision 95d45410b5100e07f6f98450bcd841a8945d4726)
1 /*-
2  * Copyright (c) 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Rick Macklem at The University of Guelph.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 4. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  */
33 
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36 
37 /*
38  * Socket operations for use by the nfs server.
39  */
40 
41 #ifndef APPLEKEXT
42 #include <fs/nfs/nfsport.h>
43 
44 extern struct nfsstats newnfsstats;
45 extern struct nfsrvfh nfs_pubfh, nfs_rootfh;
46 extern int nfs_pubfhset, nfs_rootfhset;
47 extern struct nfsv4lock nfsv4rootfs_lock;
48 extern struct nfsrv_stablefirst nfsrv_stablefirst;
49 extern struct nfsclienthashhead nfsclienthash[NFSCLIENTHASHSIZE];
50 extern int nfsrc_floodlevel, nfsrc_tcpsavedreplies;
51 extern int nfsd_debuglevel;
52 NFSV4ROOTLOCKMUTEX;
53 NFSSTATESPINLOCK;
54 
55 int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *,
56     int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
57 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
58 	nfsrvd_getattr,
59 	nfsrvd_setattr,
60 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
61 	nfsrvd_access,
62 	nfsrvd_readlink,
63 	nfsrvd_read,
64 	nfsrvd_write,
65 	nfsrvd_create,
66 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
67 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
68 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
69 	nfsrvd_remove,
70 	nfsrvd_remove,
71 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
72 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
73 	nfsrvd_readdir,
74 	nfsrvd_readdirplus,
75 	nfsrvd_statfs,
76 	nfsrvd_fsinfo,
77 	nfsrvd_pathconf,
78 	nfsrvd_commit,
79 };
80 
81 int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *,
82     int, vnode_t , vnode_t *, fhandle_t *,
83     NFSPROC_T *, struct nfsexstuff *) = {
84 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
85 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
86 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
87 	nfsrvd_lookup,
88 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
89 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
90 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
91 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
92 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
93 	nfsrvd_mkdir,
94 	nfsrvd_symlink,
95 	nfsrvd_mknod,
96 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
97 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
98 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
99 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
100 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
101 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
102 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
103 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
104 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
105 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
106 };
107 
108 int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
109     int, vnode_t , vnode_t , NFSPROC_T *,
110     struct nfsexstuff *, struct nfsexstuff *) = {
111 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
112 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
113 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
114 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
115 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
116 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
117 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
118 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
119 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
120 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
121 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
122 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
123 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
124 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
125 	nfsrvd_rename,
126 	nfsrvd_link,
127 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
128 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
129 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
130 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
131 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
132 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
133 };
134 
135 int (*nfsrv4_ops0[NFSV41_NOPS])(struct nfsrv_descript *,
136     int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
137 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
138 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
139 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
140 	nfsrvd_access,
141 	nfsrvd_close,
142 	nfsrvd_commit,
143 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
144 	nfsrvd_delegpurge,
145 	nfsrvd_delegreturn,
146 	nfsrvd_getattr,
147 	nfsrvd_getfh,
148 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
149 	nfsrvd_lock,
150 	nfsrvd_lockt,
151 	nfsrvd_locku,
152 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
153 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
154 	nfsrvd_verify,
155 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
156 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
157 	nfsrvd_openconfirm,
158 	nfsrvd_opendowngrade,
159 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
160 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
161 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
162 	nfsrvd_read,
163 	nfsrvd_readdirplus,
164 	nfsrvd_readlink,
165 	nfsrvd_remove,
166 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
167 	nfsrvd_renew,
168 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
169 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
170 	nfsrvd_secinfo,
171 	nfsrvd_setattr,
172 	nfsrvd_setclientid,
173 	nfsrvd_setclientidcfrm,
174 	nfsrvd_verify,
175 	nfsrvd_write,
176 	nfsrvd_releaselckown,
177 	nfsrvd_notsupp,
178 	nfsrvd_notsupp,
179 	nfsrvd_exchangeid,
180 	nfsrvd_createsession,
181 	nfsrvd_destroysession,
182 	nfsrvd_freestateid,
183 	nfsrvd_notsupp,
184 	nfsrvd_notsupp,
185 	nfsrvd_notsupp,
186 	nfsrvd_notsupp,
187 	nfsrvd_notsupp,
188 	nfsrvd_notsupp,
189 	nfsrvd_notsupp,
190 	nfsrvd_sequence,
191 	nfsrvd_notsupp,
192 	nfsrvd_notsupp,
193 	nfsrvd_notsupp,
194 	nfsrvd_destroyclientid,
195 	nfsrvd_reclaimcomplete,
196 };
197 
198 int (*nfsrv4_ops1[NFSV41_NOPS])(struct nfsrv_descript *,
199     int, vnode_t , vnode_t *, fhandle_t *,
200     NFSPROC_T *, struct nfsexstuff *) = {
201 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
202 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
203 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
204 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
205 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
206 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
207 	nfsrvd_mknod,
208 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
209 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
210 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
211 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
212 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
213 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
214 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
215 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
216 	nfsrvd_lookup,
217 	nfsrvd_lookup,
218 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
219 	nfsrvd_open,
220 	nfsrvd_openattr,
221 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
222 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
223 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
224 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
225 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
226 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
227 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
228 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
229 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
230 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
231 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
232 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
233 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
234 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
235 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
236 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
237 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
238 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
239 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
240 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
241 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
242 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
243 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
244 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
245 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
246 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
247 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
248 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
249 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
250 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
251 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
252 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
253 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
254 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
255 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
256 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
257 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
258 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
259 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
260 };
261 
262 int (*nfsrv4_ops2[NFSV41_NOPS])(struct nfsrv_descript *,
263     int, vnode_t , vnode_t , NFSPROC_T *,
264     struct nfsexstuff *, struct nfsexstuff *) = {
265 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
266 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
267 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
268 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
269 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
270 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
271 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
272 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
273 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
274 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
275 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
276 	nfsrvd_link,
277 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
278 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
279 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
280 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
281 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
282 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
283 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
284 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
285 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
286 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
287 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
288 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
289 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
290 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
291 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
292 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
293 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
294 	nfsrvd_rename,
295 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
296 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
297 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
298 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
299 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
300 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
301 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
302 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
303 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
304 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
305 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
306 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
307 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
308 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
309 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
310 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
311 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
312 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
313 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
314 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
315 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
316 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
317 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
318 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
319 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
320 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
321 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
322 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
323 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
324 };
325 #endif	/* !APPLEKEXT */
326 
327 /*
328  * Static array that defines which nfs rpc's are nonidempotent
329  */
330 static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
331 	FALSE,
332 	FALSE,
333 	TRUE,
334 	FALSE,
335 	FALSE,
336 	FALSE,
337 	FALSE,
338 	TRUE,
339 	TRUE,
340 	TRUE,
341 	TRUE,
342 	TRUE,
343 	TRUE,
344 	TRUE,
345 	TRUE,
346 	TRUE,
347 	FALSE,
348 	FALSE,
349 	FALSE,
350 	FALSE,
351 	FALSE,
352 	FALSE,
353 };
354 
355 /*
356  * This static array indicates whether or not the RPC modifies the
357  * file system.
358  */
359 static int nfs_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
360     1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
361     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
362 
363 /* local functions */
364 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
365     u_char *tag, int taglen, u_int32_t minorvers, NFSPROC_T *p);
366 
367 
368 /*
369  * This static array indicates which server procedures require the extra
370  * arguments to return the current file handle for V2, 3.
371  */
372 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
373 	1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
374 
375 extern struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS];
376 
377 static int nfsv3to4op[NFS_V3NPROCS] = {
378 	NFSPROC_NULL,
379 	NFSV4OP_GETATTR,
380 	NFSV4OP_SETATTR,
381 	NFSV4OP_LOOKUP,
382 	NFSV4OP_ACCESS,
383 	NFSV4OP_READLINK,
384 	NFSV4OP_READ,
385 	NFSV4OP_WRITE,
386 	NFSV4OP_V3CREATE,
387 	NFSV4OP_MKDIR,
388 	NFSV4OP_SYMLINK,
389 	NFSV4OP_MKNOD,
390 	NFSV4OP_REMOVE,
391 	NFSV4OP_RMDIR,
392 	NFSV4OP_RENAME,
393 	NFSV4OP_LINK,
394 	NFSV4OP_READDIR,
395 	NFSV4OP_READDIRPLUS,
396 	NFSV4OP_FSSTAT,
397 	NFSV4OP_FSINFO,
398 	NFSV4OP_PATHCONF,
399 	NFSV4OP_COMMIT,
400 };
401 
402 /*
403  * Do an RPC. Basically, get the file handles translated to vnode pointers
404  * and then call the appropriate server routine. The server routines are
405  * split into groups, based on whether they use a file handle or file
406  * handle plus name or ...
407  * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
408  */
409 APPLESTATIC void
410 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
411     u_int32_t minorvers, NFSPROC_T *p)
412 {
413 	int error = 0, lktype;
414 	vnode_t vp;
415 	mount_t mp = NULL;
416 	struct nfsrvfh fh;
417 	struct nfsexstuff nes;
418 
419 	/*
420 	 * Get a locked vnode for the first file handle
421 	 */
422 	if (!(nd->nd_flag & ND_NFSV4)) {
423 		KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
424 		/*
425 		 * For NFSv3, if the malloc/mget allocation is near limits,
426 		 * return NFSERR_DELAY.
427 		 */
428 		if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
429 			nd->nd_repstat = NFSERR_DELAY;
430 			vp = NULL;
431 		} else {
432 			error = nfsrv_mtofh(nd, &fh);
433 			if (error) {
434 				if (error != EBADRPC)
435 					printf("nfs dorpc err1=%d\n", error);
436 				nd->nd_repstat = NFSERR_GARBAGE;
437 				goto out;
438 			}
439 			if (nd->nd_procnum == NFSPROC_READ ||
440 			    nd->nd_procnum == NFSPROC_WRITE ||
441 			    nd->nd_procnum == NFSPROC_READDIR ||
442 			    nd->nd_procnum == NFSPROC_READLINK ||
443 			    nd->nd_procnum == NFSPROC_GETATTR ||
444 			    nd->nd_procnum == NFSPROC_ACCESS)
445 				lktype = LK_SHARED;
446 			else
447 				lktype = LK_EXCLUSIVE;
448 			if (nd->nd_flag & ND_PUBLOOKUP)
449 				nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
450 				    &mp, nfs_writerpc[nd->nd_procnum], p);
451 			else
452 				nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
453 				    &mp, nfs_writerpc[nd->nd_procnum], p);
454 			if (nd->nd_repstat == NFSERR_PROGNOTV4)
455 				goto out;
456 		}
457 	}
458 
459 	/*
460 	 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
461 	 * cache, as required.
462 	 * For V4, nfsrvd_compound() does this.
463 	 */
464 	if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
465 		nd->nd_flag |= ND_SAVEREPLY;
466 
467 	nfsrvd_rephead(nd);
468 	/*
469 	 * If nd_repstat is non-zero, just fill in the reply status
470 	 * to complete the RPC reply for V2. Otherwise, you must do
471 	 * the RPC.
472 	 */
473 	if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
474 		*nd->nd_errp = nfsd_errmap(nd);
475 		NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
476 		if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
477 			vn_finished_write(mp);
478 		goto out;
479 	}
480 
481 	/*
482 	 * Now the procedure can be performed. For V4, nfsrvd_compound()
483 	 * works through the sub-rpcs, otherwise just call the procedure.
484 	 * The procedures are in three groups with different arguments.
485 	 * The group is indicated by the value in nfs_retfh[].
486 	 */
487 	if (nd->nd_flag & ND_NFSV4) {
488 		nfsrvd_compound(nd, isdgram, tag, taglen, minorvers, p);
489 	} else {
490 		if (nfs_retfh[nd->nd_procnum] == 1) {
491 			if (vp)
492 				NFSVOPUNLOCK(vp, 0);
493 			error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
494 			    vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes);
495 		} else if (nfs_retfh[nd->nd_procnum] == 2) {
496 			error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
497 			    vp, NULL, p, &nes, NULL);
498 		} else {
499 			error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
500 			    vp, p, &nes);
501 		}
502 		if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
503 			vn_finished_write(mp);
504 		NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
505 	}
506 	if (error) {
507 		if (error != EBADRPC)
508 			printf("nfs dorpc err2=%d\n", error);
509 		nd->nd_repstat = NFSERR_GARBAGE;
510 	}
511 	*nd->nd_errp = nfsd_errmap(nd);
512 
513 	/*
514 	 * Don't cache certain reply status values.
515 	 */
516 	if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
517 	    (nd->nd_repstat == NFSERR_GARBAGE ||
518 	     nd->nd_repstat == NFSERR_BADXDR ||
519 	     nd->nd_repstat == NFSERR_MOVED ||
520 	     nd->nd_repstat == NFSERR_DELAY ||
521 	     nd->nd_repstat == NFSERR_BADSEQID ||
522 	     nd->nd_repstat == NFSERR_RESOURCE ||
523 	     nd->nd_repstat == NFSERR_SERVERFAULT ||
524 	     nd->nd_repstat == NFSERR_STALECLIENTID ||
525 	     nd->nd_repstat == NFSERR_STALESTATEID ||
526 	     nd->nd_repstat == NFSERR_OLDSTATEID ||
527 	     nd->nd_repstat == NFSERR_BADSTATEID ||
528 	     nd->nd_repstat == NFSERR_GRACE ||
529 	     nd->nd_repstat == NFSERR_NOGRACE))
530 		nd->nd_flag &= ~ND_SAVEREPLY;
531 
532 out:
533 	NFSEXITCODE2(0, nd);
534 }
535 
536 /*
537  * Breaks down a compound RPC request and calls the server routines for
538  * the subprocedures.
539  * Some suboperations are performed directly here to simplify file handle<-->
540  * vnode pointer handling.
541  */
542 static void
543 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
544     int taglen, u_int32_t minorvers, NFSPROC_T *p)
545 {
546 	int i, op, op0 = 0;
547 	u_int32_t *tl;
548 	struct nfsclient *clp, *nclp;
549 	int numops, error = 0, igotlock;
550 	u_int32_t retops = 0, *retopsp = NULL, *repp;
551 	vnode_t vp, nvp, savevp;
552 	struct nfsrvfh fh;
553 	mount_t new_mp, temp_mp = NULL;
554 	struct ucred *credanon;
555 	struct nfsexstuff nes, vpnes, savevpnes;
556 	fsid_t cur_fsid, save_fsid;
557 	static u_int64_t compref = 0;
558 
559 	NFSVNO_EXINIT(&vpnes);
560 	NFSVNO_EXINIT(&savevpnes);
561 	/*
562 	 * Put the seq# of the current compound RPC in nfsrv_descript.
563 	 * (This is used by nfsrv_checkgetattr(), to see if the write
564 	 *  delegation was created by the same compound RPC as the one
565 	 *  with that Getattr in it.)
566 	 * Don't worry about the 64bit number wrapping around. It ain't
567 	 * gonna happen before this server gets shut down/rebooted.
568 	 */
569 	nd->nd_compref = compref++;
570 
571 	/*
572 	 * Check for and optionally get a lock on the root. This lock means that
573 	 * no nfsd will be fiddling with the V4 file system and state stuff. It
574 	 * is required when the V4 root is being changed, the stable storage
575 	 * restart file is being updated, or callbacks are being done.
576 	 * When any of the nfsd are processing an NFSv4 compound RPC, they must
577 	 * either hold a reference count (nfs_usecnt) or the lock. When
578 	 * nfsrv_unlock() is called to release the lock, it can optionally
579 	 * also get a reference count, which saves the need for a call to
580 	 * nfsrv_getref() after nfsrv_unlock().
581 	 */
582 	/*
583 	 * First, check to see if we need to wait for an update lock.
584 	 */
585 	igotlock = 0;
586 	NFSLOCKV4ROOTMUTEX();
587 	if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
588 		igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
589 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
590 	else
591 		igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
592 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
593 	NFSUNLOCKV4ROOTMUTEX();
594 	if (igotlock) {
595 		/*
596 		 * If I got the lock, I can update the stable storage file.
597 		 * Done when the grace period is over or a client has long
598 		 * since expired.
599 		 */
600 		nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
601 		if ((nfsrv_stablefirst.nsf_flags &
602 		    (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
603 			nfsrv_updatestable(p);
604 
605 		/*
606 		 * If at least one client has long since expired, search
607 		 * the client list for them, write a REVOKE record on the
608 		 * stable storage file and then remove them from the client
609 		 * list.
610 		 */
611 		if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
612 			nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
613 			for (i = 0; i < NFSCLIENTHASHSIZE; i++) {
614 			    LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
615 				nclp) {
616 				if (clp->lc_flags & LCL_EXPIREIT) {
617 				    if (!LIST_EMPTY(&clp->lc_open) ||
618 					!LIST_EMPTY(&clp->lc_deleg))
619 					nfsrv_writestable(clp->lc_id,
620 					    clp->lc_idlen, NFSNST_REVOKE, p);
621 				    nfsrv_cleanclient(clp, p);
622 				    nfsrv_freedeleglist(&clp->lc_deleg);
623 				    nfsrv_freedeleglist(&clp->lc_olddeleg);
624 				    LIST_REMOVE(clp, lc_hash);
625 				    nfsrv_zapclient(clp, p);
626 				}
627 			    }
628 			}
629 		}
630 		NFSLOCKV4ROOTMUTEX();
631 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
632 		NFSUNLOCKV4ROOTMUTEX();
633 	} else {
634 		/*
635 		 * If we didn't get the lock, we need to get a refcnt,
636 		 * which also checks for and waits for the lock.
637 		 */
638 		NFSLOCKV4ROOTMUTEX();
639 		nfsv4_getref(&nfsv4rootfs_lock, NULL,
640 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
641 		NFSUNLOCKV4ROOTMUTEX();
642 	}
643 
644 	/*
645 	 * If flagged, search for open owners that haven't had any opens
646 	 * for a long time.
647 	 */
648 	if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
649 		nfsrv_throwawayopens(p);
650 	}
651 
652 	savevp = vp = NULL;
653 	save_fsid.val[0] = save_fsid.val[1] = 0;
654 	cur_fsid.val[0] = cur_fsid.val[1] = 0;
655 
656 	/* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
657 	if (taglen < 0) {
658 		error = EBADRPC;
659 		goto nfsmout;
660 	}
661 
662 	(void) nfsm_strtom(nd, tag, taglen);
663 	NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
664 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
665 	if (minorvers != NFSV4_MINORVERSION && minorvers != NFSV41_MINORVERSION)
666 		nd->nd_repstat = NFSERR_MINORVERMISMATCH;
667 	if (nd->nd_repstat)
668 		numops = 0;
669 	else
670 		numops = fxdr_unsigned(int, *tl);
671 	/*
672 	 * Loop around doing the sub ops.
673 	 * vp - is an unlocked vnode pointer for the CFH
674 	 * savevp - is an unlocked vnode pointer for the SAVEDFH
675 	 * (at some future date, it might turn out to be more appropriate
676 	 *  to keep the file handles instead of vnode pointers?)
677 	 * savevpnes and vpnes - are the export flags for the above.
678 	 */
679 	for (i = 0; i < numops; i++) {
680 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
681 		NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
682 		*repp = *tl;
683 		op = fxdr_unsigned(int, *tl);
684 		NFSD_DEBUG(4, "op=%d\n", op);
685 		if (op < NFSV4OP_ACCESS ||
686 		    (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
687 		    (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV41) != 0)) {
688 			nd->nd_repstat = NFSERR_OPILLEGAL;
689 			*repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
690 			*repp = nfsd_errmap(nd);
691 			retops++;
692 			break;
693 		} else {
694 			repp++;
695 		}
696 		if (i == 0)
697 			op0 = op;
698 		if (i == numops - 1)
699 			nd->nd_flag |= ND_LASTOP;
700 
701 		/*
702 		 * Check for a referral on the current FH and, if so, return
703 		 * NFSERR_MOVED for all ops that allow it, except Getattr.
704 		 */
705 		if (vp != NULL && op != NFSV4OP_GETATTR &&
706 		    nfsv4root_getreferral(vp, NULL, 0) != NULL &&
707 		    nfsrv_errmoved(op)) {
708 			nd->nd_repstat = NFSERR_MOVED;
709 			*repp = nfsd_errmap(nd);
710 			retops++;
711 			break;
712 		}
713 
714 		/*
715 		 * For NFSv4.1, check for a Sequence Operation being first
716 		 * or one of the other allowed operations by itself.
717 		 */
718 		if ((nd->nd_flag & ND_NFSV41) != 0) {
719 			if (i != 0 && op == NFSV4OP_SEQUENCE)
720 				nd->nd_repstat = NFSERR_SEQUENCEPOS;
721 			else if (i == 0 && op != NFSV4OP_SEQUENCE &&
722 			    op != NFSV4OP_EXCHANGEID &&
723 			    op != NFSV4OP_CREATESESSION &&
724 			    op != NFSV4OP_BINDCONNTOSESS &&
725 			    op != NFSV4OP_DESTROYCLIENTID &&
726 			    op != NFSV4OP_DESTROYSESSION)
727 				nd->nd_repstat = NFSERR_OPNOTINSESS;
728 			else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
729 				nd->nd_repstat = NFSERR_NOTONLYOP;
730 			if (nd->nd_repstat != 0) {
731 				*repp = nfsd_errmap(nd);
732 				retops++;
733 				break;
734 			}
735 		}
736 
737 		nd->nd_procnum = op;
738 		/*
739 		 * If over flood level, reply NFSERR_RESOURCE, if at the first
740 		 * Op. (Since a client recovery from NFSERR_RESOURCE can get
741 		 * really nasty for certain Op sequences, I'll play it safe
742 		 * and only return the error at the beginning.) The cache
743 		 * will still function over flood level, but uses lots of
744 		 * mbufs.)
745 		 * If nfsrv_mallocmget_limit() returns True, the system is near
746 		 * to its limit for memory that malloc()/mget() can allocate.
747 		 */
748 		if (i == 0 && (nd->nd_rp == NULL ||
749 		    nd->nd_rp->rc_refcnt == 0) &&
750 		    (nfsrv_mallocmget_limit() ||
751 		     nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
752 			if (nfsrc_tcpsavedreplies > nfsrc_floodlevel) {
753 				printf("nfsd server cache flooded, try to");
754 				printf(" increase nfsrc_floodlevel\n");
755 			}
756 			nd->nd_repstat = NFSERR_RESOURCE;
757 			*repp = nfsd_errmap(nd);
758 			if (op == NFSV4OP_SETATTR) {
759 				/*
760 				 * Setattr replies require a bitmap.
761 				 * even for errors like these.
762 				 */
763 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
764 				*tl = 0;
765 			}
766 			retops++;
767 			break;
768 		}
769 		if (nfsv4_opflag[op].savereply)
770 			nd->nd_flag |= ND_SAVEREPLY;
771 		NFSINCRGLOBAL(newnfsstats.srvrpccnt[nd->nd_procnum]);
772 		switch (op) {
773 		case NFSV4OP_PUTFH:
774 			error = nfsrv_mtofh(nd, &fh);
775 			if (error)
776 				goto nfsmout;
777 			if (!nd->nd_repstat)
778 				nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
779 				    NULL, 0, p);
780 			/* For now, allow this for non-export FHs */
781 			if (!nd->nd_repstat) {
782 				if (vp)
783 					vrele(vp);
784 				vp = nvp;
785 				cur_fsid = vp->v_mount->mnt_stat.f_fsid;
786 				NFSVOPUNLOCK(vp, 0);
787 				vpnes = nes;
788 			}
789 			break;
790 		case NFSV4OP_PUTPUBFH:
791 			if (nfs_pubfhset)
792 			    nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
793 				&nes, NULL, 0, p);
794 			else
795 			    nd->nd_repstat = NFSERR_NOFILEHANDLE;
796 			if (!nd->nd_repstat) {
797 				if (vp)
798 					vrele(vp);
799 				vp = nvp;
800 				cur_fsid = vp->v_mount->mnt_stat.f_fsid;
801 				NFSVOPUNLOCK(vp, 0);
802 				vpnes = nes;
803 			}
804 			break;
805 		case NFSV4OP_PUTROOTFH:
806 			if (nfs_rootfhset) {
807 				nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
808 				    &nes, NULL, 0, p);
809 				if (!nd->nd_repstat) {
810 					if (vp)
811 						vrele(vp);
812 					vp = nvp;
813 					cur_fsid = vp->v_mount->mnt_stat.f_fsid;
814 					NFSVOPUNLOCK(vp, 0);
815 					vpnes = nes;
816 				}
817 			} else
818 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
819 			break;
820 		case NFSV4OP_SAVEFH:
821 			if (vp && NFSVNO_EXPORTED(&vpnes)) {
822 				nd->nd_repstat = 0;
823 				/* If vp == savevp, a no-op */
824 				if (vp != savevp) {
825 					if (savevp)
826 						vrele(savevp);
827 					VREF(vp);
828 					savevp = vp;
829 					savevpnes = vpnes;
830 					save_fsid = cur_fsid;
831 				}
832 			} else {
833 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
834 			}
835 			break;
836 		case NFSV4OP_RESTOREFH:
837 			if (savevp) {
838 				nd->nd_repstat = 0;
839 				/* If vp == savevp, a no-op */
840 				if (vp != savevp) {
841 					VREF(savevp);
842 					vrele(vp);
843 					vp = savevp;
844 					vpnes = savevpnes;
845 					cur_fsid = save_fsid;
846 				}
847 			} else {
848 				nd->nd_repstat = NFSERR_RESTOREFH;
849 			}
850 			break;
851 		default:
852 		    /*
853 		     * Allow a Lookup, Getattr, GetFH, Secinfo on an
854 		     * non-exported directory if
855 		     * nfs_rootfhset. Do I need to allow any other Ops?
856 		     * (You can only have a non-exported vpnes if
857 		     *  nfs_rootfhset is true. See nfsd_fhtovp())
858 		     * Allow AUTH_SYS to be used for file systems
859 		     * exported GSS only for certain Ops, to allow
860 		     * clients to do mounts more easily.
861 		     */
862 		    if (nfsv4_opflag[op].needscfh && vp) {
863 			if (!NFSVNO_EXPORTED(&vpnes) &&
864 			    op != NFSV4OP_LOOKUP &&
865 			    op != NFSV4OP_GETATTR &&
866 			    op != NFSV4OP_GETFH &&
867 			    op != NFSV4OP_ACCESS &&
868 			    op != NFSV4OP_READLINK &&
869 			    op != NFSV4OP_SECINFO)
870 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
871 			else if (nfsvno_testexp(nd, &vpnes) &&
872 			    op != NFSV4OP_LOOKUP &&
873 			    op != NFSV4OP_GETFH &&
874 			    op != NFSV4OP_GETATTR &&
875 			    op != NFSV4OP_SECINFO)
876 				nd->nd_repstat = NFSERR_WRONGSEC;
877 			if (nd->nd_repstat) {
878 				if (op == NFSV4OP_SETATTR) {
879 				    /*
880 				     * Setattr reply requires a bitmap
881 				     * even for errors like these.
882 				     */
883 				    NFSM_BUILD(tl, u_int32_t *,
884 					NFSX_UNSIGNED);
885 				    *tl = 0;
886 				}
887 				break;
888 			}
889 		    }
890 		    if (nfsv4_opflag[op].retfh == 1) {
891 			if (!vp) {
892 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
893 				break;
894 			}
895 			VREF(vp);
896 			if (nfsv4_opflag[op].modifyfs)
897 				vn_start_write(vp, &temp_mp, V_WAIT);
898 			error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
899 			    &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes);
900 			if (!error && !nd->nd_repstat) {
901 			    if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
902 				new_mp = nvp->v_mount;
903 				if (cur_fsid.val[0] !=
904 				    new_mp->mnt_stat.f_fsid.val[0] ||
905 				    cur_fsid.val[1] !=
906 				    new_mp->mnt_stat.f_fsid.val[1]) {
907 				    /* crossed a server mount point */
908 				    nd->nd_repstat = nfsvno_checkexp(new_mp,
909 					nd->nd_nam, &nes, &credanon);
910 				    if (!nd->nd_repstat)
911 					nd->nd_repstat = nfsd_excred(nd,
912 					    &nes, credanon);
913 				    if (credanon != NULL)
914 					crfree(credanon);
915 				    if (!nd->nd_repstat) {
916 					vpnes = nes;
917 					cur_fsid = new_mp->mnt_stat.f_fsid;
918 				    }
919 				}
920 				/* Lookup ops return a locked vnode */
921 				NFSVOPUNLOCK(nvp, 0);
922 			    }
923 			    if (!nd->nd_repstat) {
924 				    vrele(vp);
925 				    vp = nvp;
926 			    } else
927 				    vrele(nvp);
928 			}
929 			if (nfsv4_opflag[op].modifyfs)
930 				vn_finished_write(temp_mp);
931 		    } else if (nfsv4_opflag[op].retfh == 2) {
932 			if (vp == NULL || savevp == NULL) {
933 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
934 				break;
935 			} else if (cur_fsid.val[0] != save_fsid.val[0] ||
936 			    cur_fsid.val[1] != save_fsid.val[1]) {
937 				nd->nd_repstat = NFSERR_XDEV;
938 				break;
939 			}
940 			if (nfsv4_opflag[op].modifyfs)
941 				vn_start_write(savevp, &temp_mp, V_WAIT);
942 			if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
943 				VREF(vp);
944 				VREF(savevp);
945 				error = (*(nfsrv4_ops2[op]))(nd, isdgram,
946 				    savevp, vp, p, &savevpnes, &vpnes);
947 			} else
948 				nd->nd_repstat = NFSERR_PERM;
949 			if (nfsv4_opflag[op].modifyfs)
950 				vn_finished_write(temp_mp);
951 		    } else {
952 			if (nfsv4_opflag[op].retfh != 0)
953 				panic("nfsrvd_compound");
954 			if (nfsv4_opflag[op].needscfh) {
955 				if (vp != NULL) {
956 					if (nfsv4_opflag[op].modifyfs)
957 						vn_start_write(vp, &temp_mp,
958 						    V_WAIT);
959 					if (NFSVOPLOCK(vp, nfsv4_opflag[op].lktype)
960 					    == 0)
961 						VREF(vp);
962 					else
963 						nd->nd_repstat = NFSERR_PERM;
964 				} else {
965 					nd->nd_repstat = NFSERR_NOFILEHANDLE;
966 					if (op == NFSV4OP_SETATTR) {
967 						/*
968 						 * Setattr reply requires a
969 						 * bitmap even for errors like
970 						 * these.
971 						 */
972 						NFSM_BUILD(tl, u_int32_t *,
973 						    NFSX_UNSIGNED);
974 						*tl = 0;
975 					}
976 					break;
977 				}
978 				if (nd->nd_repstat == 0)
979 					error = (*(nfsrv4_ops0[op]))(nd,
980 					    isdgram, vp, p, &vpnes);
981 				if (nfsv4_opflag[op].modifyfs)
982 					vn_finished_write(temp_mp);
983 			} else {
984 				error = (*(nfsrv4_ops0[op]))(nd, isdgram,
985 				    NULL, p, &vpnes);
986 			}
987 		    }
988 		};
989 		if (error) {
990 			if (error == EBADRPC || error == NFSERR_BADXDR) {
991 				nd->nd_repstat = NFSERR_BADXDR;
992 			} else {
993 				nd->nd_repstat = error;
994 				printf("nfsv4 comperr0=%d\n", error);
995 			}
996 			error = 0;
997 		}
998 		retops++;
999 		if (nd->nd_repstat) {
1000 			*repp = nfsd_errmap(nd);
1001 			break;
1002 		} else {
1003 			*repp = 0;	/* NFS4_OK */
1004 		}
1005 	}
1006 nfsmout:
1007 	if (error) {
1008 		if (error == EBADRPC || error == NFSERR_BADXDR)
1009 			nd->nd_repstat = NFSERR_BADXDR;
1010 		else
1011 			printf("nfsv4 comperr1=%d\n", error);
1012 	}
1013 	if (taglen == -1) {
1014 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1015 		*tl++ = 0;
1016 		*tl = 0;
1017 	} else {
1018 		*retopsp = txdr_unsigned(retops);
1019 	}
1020 	if (vp)
1021 		vrele(vp);
1022 	if (savevp)
1023 		vrele(savevp);
1024 	NFSLOCKV4ROOTMUTEX();
1025 	nfsv4_relref(&nfsv4rootfs_lock);
1026 	NFSUNLOCKV4ROOTMUTEX();
1027 
1028 	NFSEXITCODE2(0, nd);
1029 }
1030