nfs_nfsdsocket.c revision 270066
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: stable/10/sys/fs/nfsserver/nfs_nfsdsocket.c 270066 2014-08-16 21:36:22Z rmacklem $");
36
37/*
38 * Socket operations for use by the nfs server.
39 */
40
41#ifndef APPLEKEXT
42#include <fs/nfs/nfsport.h>
43
44extern struct nfsstats newnfsstats;
45extern struct nfsrvfh nfs_pubfh, nfs_rootfh;
46extern int nfs_pubfhset, nfs_rootfhset;
47extern struct nfsv4lock nfsv4rootfs_lock;
48extern struct nfsrv_stablefirst nfsrv_stablefirst;
49extern struct nfsclienthashhead nfsclienthash[NFSCLIENTHASHSIZE];
50extern int nfsrc_floodlevel, nfsrc_tcpsavedreplies;
51extern int nfsd_debuglevel;
52NFSV4ROOTLOCKMUTEX;
53NFSSTATESPINLOCK;
54
55int (*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
81int (*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
108int (*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
135int (*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
198int (*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
262int (*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 */
330static 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 */
359static 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 */
364static 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 */
372static 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
375extern struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS];
376
377static 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 */
409APPLESTATIC void
410nfsrvd_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
532out:
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 */
542static void
543nfsrvd_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 "
754				    "increasing vfs.nfsd.tcphighwater\n");
755			nd->nd_repstat = NFSERR_RESOURCE;
756			*repp = nfsd_errmap(nd);
757			if (op == NFSV4OP_SETATTR) {
758				/*
759				 * Setattr replies require a bitmap.
760				 * even for errors like these.
761				 */
762				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
763				*tl = 0;
764			}
765			retops++;
766			break;
767		}
768		if (nfsv4_opflag[op].savereply)
769			nd->nd_flag |= ND_SAVEREPLY;
770		NFSINCRGLOBAL(newnfsstats.srvrpccnt[nd->nd_procnum]);
771		switch (op) {
772		case NFSV4OP_PUTFH:
773			error = nfsrv_mtofh(nd, &fh);
774			if (error)
775				goto nfsmout;
776			if (!nd->nd_repstat)
777				nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
778				    NULL, 0, p);
779			/* For now, allow this for non-export FHs */
780			if (!nd->nd_repstat) {
781				if (vp)
782					vrele(vp);
783				vp = nvp;
784				cur_fsid = vp->v_mount->mnt_stat.f_fsid;
785				NFSVOPUNLOCK(vp, 0);
786				vpnes = nes;
787			}
788			break;
789		case NFSV4OP_PUTPUBFH:
790			if (nfs_pubfhset)
791			    nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
792				&nes, NULL, 0, p);
793			else
794			    nd->nd_repstat = NFSERR_NOFILEHANDLE;
795			if (!nd->nd_repstat) {
796				if (vp)
797					vrele(vp);
798				vp = nvp;
799				cur_fsid = vp->v_mount->mnt_stat.f_fsid;
800				NFSVOPUNLOCK(vp, 0);
801				vpnes = nes;
802			}
803			break;
804		case NFSV4OP_PUTROOTFH:
805			if (nfs_rootfhset) {
806				nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
807				    &nes, NULL, 0, p);
808				if (!nd->nd_repstat) {
809					if (vp)
810						vrele(vp);
811					vp = nvp;
812					cur_fsid = vp->v_mount->mnt_stat.f_fsid;
813					NFSVOPUNLOCK(vp, 0);
814					vpnes = nes;
815				}
816			} else
817				nd->nd_repstat = NFSERR_NOFILEHANDLE;
818			break;
819		case NFSV4OP_SAVEFH:
820			if (vp && NFSVNO_EXPORTED(&vpnes)) {
821				nd->nd_repstat = 0;
822				/* If vp == savevp, a no-op */
823				if (vp != savevp) {
824					if (savevp)
825						vrele(savevp);
826					VREF(vp);
827					savevp = vp;
828					savevpnes = vpnes;
829					save_fsid = cur_fsid;
830				}
831			} else {
832				nd->nd_repstat = NFSERR_NOFILEHANDLE;
833			}
834			break;
835		case NFSV4OP_RESTOREFH:
836			if (savevp) {
837				nd->nd_repstat = 0;
838				/* If vp == savevp, a no-op */
839				if (vp != savevp) {
840					VREF(savevp);
841					vrele(vp);
842					vp = savevp;
843					vpnes = savevpnes;
844					cur_fsid = save_fsid;
845				}
846			} else {
847				nd->nd_repstat = NFSERR_RESTOREFH;
848			}
849			break;
850		default:
851		    /*
852		     * Allow a Lookup, Getattr, GetFH, Secinfo on an
853		     * non-exported directory if
854		     * nfs_rootfhset. Do I need to allow any other Ops?
855		     * (You can only have a non-exported vpnes if
856		     *  nfs_rootfhset is true. See nfsd_fhtovp())
857		     * Allow AUTH_SYS to be used for file systems
858		     * exported GSS only for certain Ops, to allow
859		     * clients to do mounts more easily.
860		     */
861		    if (nfsv4_opflag[op].needscfh && vp) {
862			if (!NFSVNO_EXPORTED(&vpnes) &&
863			    op != NFSV4OP_LOOKUP &&
864			    op != NFSV4OP_GETATTR &&
865			    op != NFSV4OP_GETFH &&
866			    op != NFSV4OP_ACCESS &&
867			    op != NFSV4OP_READLINK &&
868			    op != NFSV4OP_SECINFO)
869				nd->nd_repstat = NFSERR_NOFILEHANDLE;
870			else if (nfsvno_testexp(nd, &vpnes) &&
871			    op != NFSV4OP_LOOKUP &&
872			    op != NFSV4OP_GETFH &&
873			    op != NFSV4OP_GETATTR &&
874			    op != NFSV4OP_SECINFO)
875				nd->nd_repstat = NFSERR_WRONGSEC;
876			if (nd->nd_repstat) {
877				if (op == NFSV4OP_SETATTR) {
878				    /*
879				     * Setattr reply requires a bitmap
880				     * even for errors like these.
881				     */
882				    NFSM_BUILD(tl, u_int32_t *,
883					NFSX_UNSIGNED);
884				    *tl = 0;
885				}
886				break;
887			}
888		    }
889		    if (nfsv4_opflag[op].retfh == 1) {
890			if (!vp) {
891				nd->nd_repstat = NFSERR_NOFILEHANDLE;
892				break;
893			}
894			VREF(vp);
895			if (nfsv4_opflag[op].modifyfs)
896				vn_start_write(vp, &temp_mp, V_WAIT);
897			error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
898			    &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes);
899			if (!error && !nd->nd_repstat) {
900			    if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
901				new_mp = nvp->v_mount;
902				if (cur_fsid.val[0] !=
903				    new_mp->mnt_stat.f_fsid.val[0] ||
904				    cur_fsid.val[1] !=
905				    new_mp->mnt_stat.f_fsid.val[1]) {
906				    /* crossed a server mount point */
907				    nd->nd_repstat = nfsvno_checkexp(new_mp,
908					nd->nd_nam, &nes, &credanon);
909				    if (!nd->nd_repstat)
910					nd->nd_repstat = nfsd_excred(nd,
911					    &nes, credanon);
912				    if (credanon != NULL)
913					crfree(credanon);
914				    if (!nd->nd_repstat) {
915					vpnes = nes;
916					cur_fsid = new_mp->mnt_stat.f_fsid;
917				    }
918				}
919				/* Lookup ops return a locked vnode */
920				NFSVOPUNLOCK(nvp, 0);
921			    }
922			    if (!nd->nd_repstat) {
923				    vrele(vp);
924				    vp = nvp;
925			    } else
926				    vrele(nvp);
927			}
928			if (nfsv4_opflag[op].modifyfs)
929				vn_finished_write(temp_mp);
930		    } else if (nfsv4_opflag[op].retfh == 2) {
931			if (vp == NULL || savevp == NULL) {
932				nd->nd_repstat = NFSERR_NOFILEHANDLE;
933				break;
934			} else if (cur_fsid.val[0] != save_fsid.val[0] ||
935			    cur_fsid.val[1] != save_fsid.val[1]) {
936				nd->nd_repstat = NFSERR_XDEV;
937				break;
938			}
939			if (nfsv4_opflag[op].modifyfs)
940				vn_start_write(savevp, &temp_mp, V_WAIT);
941			if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
942				VREF(vp);
943				VREF(savevp);
944				error = (*(nfsrv4_ops2[op]))(nd, isdgram,
945				    savevp, vp, p, &savevpnes, &vpnes);
946			} else
947				nd->nd_repstat = NFSERR_PERM;
948			if (nfsv4_opflag[op].modifyfs)
949				vn_finished_write(temp_mp);
950		    } else {
951			if (nfsv4_opflag[op].retfh != 0)
952				panic("nfsrvd_compound");
953			if (nfsv4_opflag[op].needscfh) {
954				if (vp != NULL) {
955					if (nfsv4_opflag[op].modifyfs)
956						vn_start_write(vp, &temp_mp,
957						    V_WAIT);
958					if (NFSVOPLOCK(vp, nfsv4_opflag[op].lktype)
959					    == 0)
960						VREF(vp);
961					else
962						nd->nd_repstat = NFSERR_PERM;
963				} else {
964					nd->nd_repstat = NFSERR_NOFILEHANDLE;
965					if (op == NFSV4OP_SETATTR) {
966						/*
967						 * Setattr reply requires a
968						 * bitmap even for errors like
969						 * these.
970						 */
971						NFSM_BUILD(tl, u_int32_t *,
972						    NFSX_UNSIGNED);
973						*tl = 0;
974					}
975					break;
976				}
977				if (nd->nd_repstat == 0)
978					error = (*(nfsrv4_ops0[op]))(nd,
979					    isdgram, vp, p, &vpnes);
980				if (nfsv4_opflag[op].modifyfs)
981					vn_finished_write(temp_mp);
982			} else {
983				error = (*(nfsrv4_ops0[op]))(nd, isdgram,
984				    NULL, p, &vpnes);
985			}
986		    }
987		};
988		if (error) {
989			if (error == EBADRPC || error == NFSERR_BADXDR) {
990				nd->nd_repstat = NFSERR_BADXDR;
991			} else {
992				nd->nd_repstat = error;
993				printf("nfsv4 comperr0=%d\n", error);
994			}
995			error = 0;
996		}
997		retops++;
998		if (nd->nd_repstat) {
999			*repp = nfsd_errmap(nd);
1000			break;
1001		} else {
1002			*repp = 0;	/* NFS4_OK */
1003		}
1004	}
1005nfsmout:
1006	if (error) {
1007		if (error == EBADRPC || error == NFSERR_BADXDR)
1008			nd->nd_repstat = NFSERR_BADXDR;
1009		else
1010			printf("nfsv4 comperr1=%d\n", error);
1011	}
1012	if (taglen == -1) {
1013		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1014		*tl++ = 0;
1015		*tl = 0;
1016	} else {
1017		*retopsp = txdr_unsigned(retops);
1018	}
1019	if (vp)
1020		vrele(vp);
1021	if (savevp)
1022		vrele(savevp);
1023	NFSLOCKV4ROOTMUTEX();
1024	nfsv4_relref(&nfsv4rootfs_lock);
1025	NFSUNLOCKV4ROOTMUTEX();
1026
1027	NFSEXITCODE2(0, nd);
1028}
1029