nfs_nfsdkrpc.c revision 192780
1191783Srmacklem/*-
2191783Srmacklem * Copyright (c) 1989, 1993
3191783Srmacklem *	The Regents of the University of California.  All rights reserved.
4191783Srmacklem *
5191783Srmacklem * This code is derived from software contributed to Berkeley by
6191783Srmacklem * Rick Macklem at The University of Guelph.
7191783Srmacklem *
8191783Srmacklem * Redistribution and use in source and binary forms, with or without
9191783Srmacklem * modification, are permitted provided that the following conditions
10191783Srmacklem * are met:
11191783Srmacklem * 1. Redistributions of source code must retain the above copyright
12191783Srmacklem *    notice, this list of conditions and the following disclaimer.
13191783Srmacklem * 2. Redistributions in binary form must reproduce the above copyright
14191783Srmacklem *    notice, this list of conditions and the following disclaimer in the
15191783Srmacklem *    documentation and/or other materials provided with the distribution.
16191783Srmacklem * 4. Neither the name of the University nor the names of its contributors
17191783Srmacklem *    may be used to endorse or promote products derived from this software
18191783Srmacklem *    without specific prior written permission.
19191783Srmacklem *
20191783Srmacklem * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21191783Srmacklem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22191783Srmacklem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23191783Srmacklem * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24191783Srmacklem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25191783Srmacklem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26191783Srmacklem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27191783Srmacklem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28191783Srmacklem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29191783Srmacklem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30191783Srmacklem * SUCH DAMAGE.
31191783Srmacklem *
32191783Srmacklem */
33191783Srmacklem
34191783Srmacklem#include <sys/cdefs.h>
35191783Srmacklem__FBSDID("$FreeBSD: head/sys/fs/nfsserver/nfs_nfsdkrpc.c 192780 2009-05-26 01:09:33Z rmacklem $");
36191783Srmacklem
37191783Srmacklem#include "opt_inet6.h"
38191783Srmacklem#include "opt_kgssapi.h"
39191783Srmacklem
40191783Srmacklem#include <fs/nfs/nfsport.h>
41191783Srmacklem
42191783Srmacklem#include <rpc/rpc.h>
43191783Srmacklem#include <rpc/rpcsec_gss.h>
44191783Srmacklem
45191783SrmacklemNFSDLOCKMUTEX;
46191783Srmacklem
47191783Srmacklem/*
48191783Srmacklem * Mapping of old NFS Version 2 RPC numbers to generic numbers.
49191783Srmacklem */
50191783Srmacklemstatic int newnfs_nfsv3_procid[NFS_V3NPROCS] = {
51191783Srmacklem	NFSPROC_NULL,
52191783Srmacklem	NFSPROC_GETATTR,
53191783Srmacklem	NFSPROC_SETATTR,
54191783Srmacklem	NFSPROC_NOOP,
55191783Srmacklem	NFSPROC_LOOKUP,
56191783Srmacklem	NFSPROC_READLINK,
57191783Srmacklem	NFSPROC_READ,
58191783Srmacklem	NFSPROC_NOOP,
59191783Srmacklem	NFSPROC_WRITE,
60191783Srmacklem	NFSPROC_CREATE,
61191783Srmacklem	NFSPROC_REMOVE,
62191783Srmacklem	NFSPROC_RENAME,
63191783Srmacklem	NFSPROC_LINK,
64191783Srmacklem	NFSPROC_SYMLINK,
65191783Srmacklem	NFSPROC_MKDIR,
66191783Srmacklem	NFSPROC_RMDIR,
67191783Srmacklem	NFSPROC_READDIR,
68191783Srmacklem	NFSPROC_FSSTAT,
69191783Srmacklem	NFSPROC_NOOP,
70191783Srmacklem	NFSPROC_NOOP,
71191783Srmacklem	NFSPROC_NOOP,
72191783Srmacklem	NFSPROC_NOOP,
73191783Srmacklem};
74191783Srmacklem
75191783Srmacklem
76191783SrmacklemSYSCTL_DECL(_vfs_newnfs);
77191783Srmacklem
78191783SrmacklemSVCPOOL		*nfsrvd_pool;
79191783Srmacklem
80191783Srmacklemstatic int	nfs_privport = 0;
81191783SrmacklemSYSCTL_INT(_vfs_newnfs, OID_AUTO, nfs_privport, CTLFLAG_RW,
82191783Srmacklem    &nfs_privport, 0,
83191783Srmacklem    "Only allow clients using a privileged port for NFSv2 and 3");
84191783Srmacklem
85191783Srmacklemstatic int nfs_proc(struct nfsrv_descript *, u_int32_t, struct socket *,
86191783Srmacklem    u_int64_t, struct nfsrvcache **);
87191783Srmacklem
88191783Srmacklemextern u_long sb_max_adj;
89191783Srmacklemextern int newnfs_numnfsd;
90191783Srmacklem
91191783Srmacklem/*
92191783Srmacklem * NFS server system calls
93191783Srmacklem */
94191783Srmacklem
95191783Srmacklemstatic void
96191783Srmacklemnfssvc_program(struct svc_req *rqst, SVCXPRT *xprt)
97191783Srmacklem{
98191783Srmacklem	struct nfsrv_descript nd;
99191783Srmacklem	struct nfsrvcache *rp = NULL;
100192121Srmacklem	int cacherep, credflavor;
101191783Srmacklem
102191783Srmacklem	memset(&nd, 0, sizeof(nd));
103191783Srmacklem	if (rqst->rq_vers == NFS_VER2) {
104191783Srmacklem		if (rqst->rq_proc > NFSV2PROC_STATFS) {
105191783Srmacklem			svcerr_noproc(rqst);
106191783Srmacklem			svc_freereq(rqst);
107191783Srmacklem			return;
108191783Srmacklem		}
109191783Srmacklem		nd.nd_procnum = newnfs_nfsv3_procid[rqst->rq_proc];
110191783Srmacklem		nd.nd_flag = ND_NFSV2;
111191783Srmacklem	} else if (rqst->rq_vers == NFS_VER3) {
112191783Srmacklem		if (rqst->rq_proc >= NFS_V3NPROCS) {
113191783Srmacklem			svcerr_noproc(rqst);
114191783Srmacklem			svc_freereq(rqst);
115191783Srmacklem			return;
116191783Srmacklem		}
117191783Srmacklem		nd.nd_procnum = rqst->rq_proc;
118191783Srmacklem		nd.nd_flag = ND_NFSV3;
119191783Srmacklem	} else {
120191783Srmacklem		if (rqst->rq_proc != NFSPROC_NULL &&
121191783Srmacklem		    rqst->rq_proc != NFSV4PROC_COMPOUND) {
122191783Srmacklem			svcerr_noproc(rqst);
123191783Srmacklem			svc_freereq(rqst);
124191783Srmacklem			return;
125191783Srmacklem		}
126191783Srmacklem		nd.nd_procnum = rqst->rq_proc;
127191783Srmacklem		nd.nd_flag = ND_NFSV4;
128191783Srmacklem	}
129191783Srmacklem
130191783Srmacklem	/*
131191783Srmacklem	 * Note: we want rq_addr, not svc_getrpccaller for nd_nam2 -
132191783Srmacklem	 * NFS_SRVMAXDATA uses a NULL value for nd_nam2 to detect TCP
133191783Srmacklem	 * mounts.
134191783Srmacklem	 */
135191783Srmacklem	nd.nd_mrep = rqst->rq_args;
136191783Srmacklem	rqst->rq_args = NULL;
137191783Srmacklem	newnfs_realign(&nd.nd_mrep);
138191783Srmacklem	nd.nd_md = nd.nd_mrep;
139191783Srmacklem	nd.nd_dpos = mtod(nd.nd_md, caddr_t);
140191783Srmacklem	nd.nd_nam = svc_getrpccaller(rqst);
141191783Srmacklem	nd.nd_nam2 = rqst->rq_addr;
142191783Srmacklem	nd.nd_mreq = NULL;
143191783Srmacklem	nd.nd_cred = NULL;
144191783Srmacklem
145191783Srmacklem	if (nfs_privport && (nd.nd_flag & ND_NFSV4) == 0) {
146191783Srmacklem		/* Check if source port is privileged */
147191783Srmacklem		u_short port;
148191783Srmacklem		struct sockaddr *nam = nd.nd_nam;
149191783Srmacklem		struct sockaddr_in *sin;
150191783Srmacklem
151191783Srmacklem		sin = (struct sockaddr_in *)nam;
152191783Srmacklem		/*
153191783Srmacklem		 * INET/INET6 - same code:
154191783Srmacklem		 *    sin_port and sin6_port are at same offset
155191783Srmacklem		 */
156191783Srmacklem		port = ntohs(sin->sin_port);
157191783Srmacklem		if (port >= IPPORT_RESERVED &&
158191783Srmacklem		    nd.nd_procnum != NFSPROC_NULL) {
159191783Srmacklem#ifdef INET6
160191783Srmacklem			char b6[INET6_ADDRSTRLEN];
161191783Srmacklem#if defined(KLD_MODULE)
162191783Srmacklem			/* Do not use ip6_sprintf: the nfs module should work without INET6. */
163191783Srmacklem#define	ip6_sprintf(buf, a)						\
164191783Srmacklem			(sprintf((buf), "%x:%x:%x:%x:%x:%x:%x:%x",	\
165191783Srmacklem			    (a)->s6_addr16[0], (a)->s6_addr16[1],	\
166191783Srmacklem			    (a)->s6_addr16[2], (a)->s6_addr16[3],	\
167191783Srmacklem			    (a)->s6_addr16[4], (a)->s6_addr16[5],	\
168191783Srmacklem			    (a)->s6_addr16[6], (a)->s6_addr16[7]),	\
169191783Srmacklem			    (buf))
170191783Srmacklem#endif
171191783Srmacklem#endif
172191783Srmacklem			printf("NFS request from unprivileged port (%s:%d)\n",
173191783Srmacklem#ifdef INET6
174191783Srmacklem			    sin->sin_family == AF_INET6 ?
175191783Srmacklem			    ip6_sprintf(b6, &satosin6(sin)->sin6_addr) :
176191783Srmacklem#if defined(KLD_MODULE)
177191783Srmacklem#undef ip6_sprintf
178191783Srmacklem#endif
179191783Srmacklem#endif
180191783Srmacklem			    inet_ntoa(sin->sin_addr), port);
181191783Srmacklem			svcerr_weakauth(rqst);
182191783Srmacklem			svc_freereq(rqst);
183191783Srmacklem			m_freem(nd.nd_mrep);
184191783Srmacklem			return;
185191783Srmacklem		}
186191783Srmacklem	}
187191783Srmacklem
188191783Srmacklem	if (nd.nd_procnum != NFSPROC_NULL) {
189192121Srmacklem		if (!svc_getcred(rqst, &nd.nd_cred, &credflavor)) {
190191783Srmacklem			svcerr_weakauth(rqst);
191191783Srmacklem			svc_freereq(rqst);
192191783Srmacklem			m_freem(nd.nd_mrep);
193191783Srmacklem			return;
194191783Srmacklem		}
195192121Srmacklem
196192121Srmacklem		/* Set the flag based on credflavor */
197192121Srmacklem		if (credflavor == RPCSEC_GSS_KRB5) {
198192121Srmacklem			nd.nd_flag |= ND_GSS;
199192121Srmacklem		} else if (credflavor == RPCSEC_GSS_KRB5I) {
200192121Srmacklem			nd.nd_flag |= (ND_GSS | ND_GSSINTEGRITY);
201192121Srmacklem		} else if (credflavor == RPCSEC_GSS_KRB5P) {
202192121Srmacklem			nd.nd_flag |= (ND_GSS | ND_GSSPRIVACY);
203192121Srmacklem		} else if (credflavor != AUTH_SYS) {
204192121Srmacklem			svcerr_weakauth(rqst);
205192121Srmacklem			svc_freereq(rqst);
206192121Srmacklem			m_freem(nd.nd_mrep);
207192121Srmacklem			return;
208192121Srmacklem		}
209192121Srmacklem
210191783Srmacklem#ifdef MAC
211191783Srmacklem		mac_cred_associate_nfsd(nd.nd_cred);
212191783Srmacklem#endif
213192780Srmacklem		if ((nd.nd_flag & ND_NFSV4) != 0) {
214191783Srmacklem			nd.nd_repstat = nfsvno_v4rootexport(&nd);
215192780Srmacklem			if (nd.nd_repstat != 0) {
216192780Srmacklem				svcerr_weakauth(rqst);
217192780Srmacklem				svc_freereq(rqst);
218192780Srmacklem				m_freem(nd.nd_mrep);
219192780Srmacklem				return;
220192780Srmacklem			}
221192780Srmacklem		}
222191783Srmacklem
223191783Srmacklem		cacherep = nfs_proc(&nd, rqst->rq_xid, xprt->xp_socket,
224191783Srmacklem		    xprt->xp_sockref, &rp);
225191783Srmacklem	} else {
226191783Srmacklem		NFSMGET(nd.nd_mreq);
227191783Srmacklem		nd.nd_mreq->m_len = 0;
228191783Srmacklem		cacherep = RC_REPLY;
229191783Srmacklem	}
230191783Srmacklem	if (nd.nd_mrep != NULL)
231191783Srmacklem		m_freem(nd.nd_mrep);
232191783Srmacklem
233191783Srmacklem	if (nd.nd_cred != NULL)
234191783Srmacklem		crfree(nd.nd_cred);
235191783Srmacklem
236191783Srmacklem	if (cacherep == RC_DROPIT) {
237191783Srmacklem		if (nd.nd_mreq != NULL)
238191783Srmacklem			m_freem(nd.nd_mreq);
239191783Srmacklem		svc_freereq(rqst);
240191783Srmacklem		return;
241191783Srmacklem	}
242191783Srmacklem
243191783Srmacklem	if (nd.nd_mreq == NULL) {
244191783Srmacklem		svcerr_decode(rqst);
245191783Srmacklem		svc_freereq(rqst);
246191783Srmacklem		return;
247191783Srmacklem	}
248191783Srmacklem
249191783Srmacklem	if (nd.nd_repstat & NFSERR_AUTHERR) {
250191783Srmacklem		svcerr_auth(rqst, nd.nd_repstat & ~NFSERR_AUTHERR);
251191783Srmacklem		if (nd.nd_mreq != NULL)
252191783Srmacklem			m_freem(nd.nd_mreq);
253191783Srmacklem	} else if (!svc_sendreply_mbuf(rqst, nd.nd_mreq)) {
254191783Srmacklem		svcerr_systemerr(rqst);
255191783Srmacklem	}
256191783Srmacklem	if (rp != NULL)
257191783Srmacklem		nfsrvd_sentcache(rp, xprt->xp_socket, 0);
258191783Srmacklem	svc_freereq(rqst);
259191783Srmacklem}
260191783Srmacklem
261191783Srmacklem/*
262191783Srmacklem * Check the cache and, optionally, do the RPC.
263191783Srmacklem * Return the appropriate cache response.
264191783Srmacklem */
265191783Srmacklemstatic int
266191783Srmacklemnfs_proc(struct nfsrv_descript *nd, u_int32_t xid, struct socket *so,
267191783Srmacklem    u_int64_t sockref, struct nfsrvcache **rpp)
268191783Srmacklem{
269191783Srmacklem	struct thread *td = curthread;
270191783Srmacklem	int cacherep = RC_DOIT, isdgram;
271191783Srmacklem
272191783Srmacklem	*rpp = NULL;
273191783Srmacklem	if (nd->nd_nam2 == NULL) {
274191783Srmacklem		nd->nd_flag |= ND_STREAMSOCK;
275191783Srmacklem		isdgram = 0;
276191783Srmacklem	} else {
277191783Srmacklem		isdgram = 1;
278191783Srmacklem	}
279191783Srmacklem	NFSGETTIME(&nd->nd_starttime);
280191783Srmacklem
281191783Srmacklem	/*
282192780Srmacklem	 * Two cases:
283191783Srmacklem	 * 1 - For NFSv2 over UDP, if we are near our malloc/mget
284191783Srmacklem	 *     limit, just drop the request. There is no
285191783Srmacklem	 *     NFSERR_RESOURCE or NFSERR_DELAY for NFSv2 and the
286191783Srmacklem	 *     client will timeout/retry over UDP in a little while.
287192780Srmacklem	 * 2 - nd_repstat == 0 && nd_mreq == NULL, which
288191783Srmacklem	 *     means a normal nfs rpc, so check the cache
289191783Srmacklem	 */
290191783Srmacklem	if ((nd->nd_flag & ND_NFSV2) && nd->nd_nam2 != NULL &&
291191783Srmacklem	    nfsrv_mallocmget_limit()) {
292191783Srmacklem		cacherep = RC_DROPIT;
293191783Srmacklem	} else {
294191783Srmacklem		/*
295191783Srmacklem		 * For NFSv3, play it safe and assume that the client is
296191783Srmacklem		 * doing retries on the same TCP connection.
297191783Srmacklem		 */
298191783Srmacklem		if ((nd->nd_flag & (ND_NFSV4 | ND_STREAMSOCK)) ==
299191783Srmacklem		    ND_STREAMSOCK)
300191783Srmacklem			nd->nd_flag |= ND_SAMETCPCONN;
301191783Srmacklem		nd->nd_retxid = xid;
302191783Srmacklem		nd->nd_tcpconntime = NFSD_MONOSEC;
303191783Srmacklem		nd->nd_sockref = sockref;
304191783Srmacklem		cacherep = nfsrvd_getcache(nd, so);
305191783Srmacklem	}
306191783Srmacklem
307191783Srmacklem	/*
308191783Srmacklem	 * Handle the request. There are three cases.
309191783Srmacklem	 * RC_DOIT - do the RPC
310191783Srmacklem	 * RC_REPLY - return the reply already created
311191783Srmacklem	 * RC_DROPIT - just throw the request away
312191783Srmacklem	 */
313191783Srmacklem	if (cacherep == RC_DOIT) {
314191783Srmacklem		nfsrvd_dorpc(nd, isdgram, td);
315191783Srmacklem		if (nd->nd_repstat == NFSERR_DONTREPLY)
316191783Srmacklem			cacherep = RC_DROPIT;
317191783Srmacklem		else
318191783Srmacklem			cacherep = RC_REPLY;
319191783Srmacklem		*rpp = nfsrvd_updatecache(nd, so);
320191783Srmacklem	}
321191783Srmacklem	return (cacherep);
322191783Srmacklem}
323191783Srmacklem
324191783Srmacklem/*
325191783Srmacklem * Adds a socket to the list for servicing by nfsds.
326191783Srmacklem */
327191783Srmacklemint
328191783Srmacklemnfsrvd_addsock(struct file *fp)
329191783Srmacklem{
330191783Srmacklem	int siz;
331191783Srmacklem	struct socket *so;
332191783Srmacklem	int error;
333191783Srmacklem	SVCXPRT *xprt;
334191783Srmacklem	static u_int64_t sockref = 0;
335191783Srmacklem
336191783Srmacklem	so = fp->f_data;
337191783Srmacklem
338191783Srmacklem	siz = sb_max_adj;
339191783Srmacklem	error = soreserve(so, siz, siz);
340191783Srmacklem	if (error) {
341191783Srmacklem		return (error);
342191783Srmacklem	}
343191783Srmacklem
344191783Srmacklem	/*
345191783Srmacklem	 * Steal the socket from userland so that it doesn't close
346191783Srmacklem	 * unexpectedly.
347191783Srmacklem	 */
348191783Srmacklem	if (so->so_type == SOCK_DGRAM)
349191783Srmacklem		xprt = svc_dg_create(nfsrvd_pool, so, 0, 0);
350191783Srmacklem	else
351191783Srmacklem		xprt = svc_vc_create(nfsrvd_pool, so, 0, 0);
352191783Srmacklem	if (xprt) {
353191783Srmacklem		fp->f_ops = &badfileops;
354191783Srmacklem		fp->f_data = NULL;
355191783Srmacklem		xprt->xp_sockref = ++sockref;
356191783Srmacklem		svc_reg(xprt, NFS_PROG, NFS_VER2, nfssvc_program, NULL);
357191783Srmacklem		svc_reg(xprt, NFS_PROG, NFS_VER3, nfssvc_program, NULL);
358191783Srmacklem		svc_reg(xprt, NFS_PROG, NFS_VER4, nfssvc_program, NULL);
359191783Srmacklem	}
360191783Srmacklem
361191783Srmacklem	return (0);
362191783Srmacklem}
363191783Srmacklem
364191783Srmacklem/*
365191783Srmacklem * Called by nfssvc() for nfsds. Just loops around servicing rpc requests
366191783Srmacklem * until it is killed by a signal.
367191783Srmacklem */
368191783Srmacklemint
369191783Srmacklemnfsrvd_nfsd(struct thread *td, struct nfsd_nfsd_args *args)
370191783Srmacklem{
371191783Srmacklem#ifdef KGSSAPI
372192017Srmacklem	char principal[MAXHOSTNAMELEN + 5];
373191783Srmacklem	int error;
374191783Srmacklem	bool_t ret2, ret3, ret4;
375191783Srmacklem#endif
376191783Srmacklem
377191783Srmacklem#ifdef KGSSAPI
378192017Srmacklem	error = copyinstr(args->principal, principal, sizeof (principal),
379192017Srmacklem	    NULL);
380192017Srmacklem	if (error)
381192017Srmacklem		return (error);
382191783Srmacklem#endif
383191783Srmacklem
384191783Srmacklem	/*
385191783Srmacklem	 * Only the first nfsd actually does any work. The RPC code
386191783Srmacklem	 * adds threads to it as needed. Any extra processes offered
387191783Srmacklem	 * by nfsd just exit. If nfsd is new enough, it will call us
388191783Srmacklem	 * once with a structure that specifies how many threads to
389191783Srmacklem	 * use.
390191783Srmacklem	 */
391191783Srmacklem	NFSD_LOCK();
392191783Srmacklem	if (newnfs_numnfsd == 0) {
393191783Srmacklem		newnfs_numnfsd++;
394191783Srmacklem
395191783Srmacklem		NFSD_UNLOCK();
396191783Srmacklem
397191783Srmacklem#ifdef KGSSAPI
398192017Srmacklem		/* An empty string implies AUTH_SYS only. */
399192017Srmacklem		if (principal[0] != '\0') {
400192017Srmacklem			ret2 = rpc_gss_set_svc_name(principal, "kerberosv5",
401192017Srmacklem			    GSS_C_INDEFINITE, NFS_PROG, NFS_VER2);
402192017Srmacklem			ret3 = rpc_gss_set_svc_name(principal, "kerberosv5",
403192017Srmacklem			    GSS_C_INDEFINITE, NFS_PROG, NFS_VER3);
404192017Srmacklem			ret4 = rpc_gss_set_svc_name(principal, "kerberosv5",
405192017Srmacklem			    GSS_C_INDEFINITE, NFS_PROG, NFS_VER4);
406191783Srmacklem
407192017Srmacklem			if (!ret2 || !ret3 || !ret4) {
408192017Srmacklem				NFSD_LOCK();
409192017Srmacklem				newnfs_numnfsd--;
410192017Srmacklem				nfsrvd_init(1);
411192017Srmacklem				NFSD_UNLOCK();
412192017Srmacklem				return (EAUTH);
413192017Srmacklem			}
414191783Srmacklem		}
415191783Srmacklem#endif
416191783Srmacklem
417192017Srmacklem		nfsrvd_pool->sp_minthreads = args->minthreads;
418192017Srmacklem		nfsrvd_pool->sp_maxthreads = args->maxthreads;
419191783Srmacklem
420191783Srmacklem		svc_run(nfsrvd_pool);
421191783Srmacklem
422191783Srmacklem#ifdef KGSSAPI
423192017Srmacklem		if (principal[0] != '\0') {
424192017Srmacklem			rpc_gss_clear_svc_name(NFS_PROG, NFS_VER2);
425192017Srmacklem			rpc_gss_clear_svc_name(NFS_PROG, NFS_VER3);
426192017Srmacklem			rpc_gss_clear_svc_name(NFS_PROG, NFS_VER4);
427192017Srmacklem		}
428191783Srmacklem#endif
429191783Srmacklem
430191783Srmacklem		NFSD_LOCK();
431191783Srmacklem		newnfs_numnfsd--;
432191783Srmacklem		nfsrvd_init(1);
433191783Srmacklem	}
434191783Srmacklem	NFSD_UNLOCK();
435191783Srmacklem
436191783Srmacklem	return (0);
437191783Srmacklem}
438191783Srmacklem
439191783Srmacklem/*
440191783Srmacklem * Initialize the data structures for the server.
441191783Srmacklem * Handshake with any new nfsds starting up to avoid any chance of
442191783Srmacklem * corruption.
443191783Srmacklem */
444191783Srmacklemvoid
445191783Srmacklemnfsrvd_init(int terminating)
446191783Srmacklem{
447191783Srmacklem
448191783Srmacklem	NFSD_LOCK_ASSERT();
449191783Srmacklem
450191783Srmacklem	if (terminating) {
451191783Srmacklem		NFSD_UNLOCK();
452191783Srmacklem		svcpool_destroy(nfsrvd_pool);
453191783Srmacklem		nfsrvd_pool = NULL;
454191783Srmacklem		NFSD_LOCK();
455191783Srmacklem	}
456191783Srmacklem
457191783Srmacklem	NFSD_UNLOCK();
458191783Srmacklem
459191783Srmacklem	nfsrvd_pool = svcpool_create("nfsd", SYSCTL_STATIC_CHILDREN(_vfs_newnfs));
460191783Srmacklem	nfsrvd_pool->sp_rcache = NULL;
461191783Srmacklem	nfsrvd_pool->sp_assign = NULL;
462191783Srmacklem	nfsrvd_pool->sp_done = NULL;
463191783Srmacklem
464191783Srmacklem	NFSD_LOCK();
465191783Srmacklem}
466191783Srmacklem
467