nfs_nfsdkrpc.c revision 284199
1139743Simp/*- 239212Sgibbs * Copyright (c) 1989, 1993 339212Sgibbs * The Regents of the University of California. All rights reserved. 439212Sgibbs * 539212Sgibbs * This code is derived from software contributed to Berkeley by 639212Sgibbs * Rick Macklem at The University of Guelph. 739212Sgibbs * 839212Sgibbs * Redistribution and use in source and binary forms, with or without 939212Sgibbs * modification, are permitted provided that the following conditions 1039212Sgibbs * are met: 1139212Sgibbs * 1. Redistributions of source code must retain the above copyright 1239212Sgibbs * notice, this list of conditions and the following disclaimer. 1339212Sgibbs * 2. Redistributions in binary form must reproduce the above copyright 1439212Sgibbs * notice, this list of conditions and the following disclaimer in the 1539212Sgibbs * documentation and/or other materials provided with the distribution. 1639212Sgibbs * 4. Neither the name of the University nor the names of its contributors 1739212Sgibbs * may be used to endorse or promote products derived from this software 1839212Sgibbs * without specific prior written permission. 1939212Sgibbs * 2039212Sgibbs * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2139212Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2239212Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2339212Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2439212Sgibbs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2539212Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2639212Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2739212Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2850477Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2939212Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3039212Sgibbs * SUCH DAMAGE. 3139212Sgibbs * 3239212Sgibbs */ 3339212Sgibbs 3439212Sgibbs#include <sys/cdefs.h> 35168876Sscottl__FBSDID("$FreeBSD: stable/10/sys/fs/nfsserver/nfs_nfsdkrpc.c 284199 2015-06-10 02:04:02Z kib $"); 3639212Sgibbs 3755206Speter#include <sys/param.h> 38256843Smav#include <sys/systm.h> 3939212Sgibbs 40248874Smarius#include "opt_inet6.h" 41248874Smarius#include "opt_kgssapi.h" 42111979Sphk 43111979Sphk#include <fs/nfs/nfsport.h> 4460168Sn_hibma 4558972Sn_hibma#include <rpc/rpc.h> 4672119Speter#include <rpc/rpcsec_gss.h> 4772119Speter 48316139Smav#include <nfs/nfs_fha.h> 49203108Smav#include <fs/nfsserver/nfs_fha_new.h> 5039212Sgibbs 5172119Speter#include <security/mac/mac_framework.h> 5272119Speter 5372119SpeterNFSDLOCKMUTEX; 5472119SpeterNFSV4ROOTLOCKMUTEX; 5572119Speterstruct nfsv4lock nfsd_suspend_lock; 5672119Speter 5772119Speter/* 5872119Speter * Mapping of old NFS Version 2 RPC numbers to generic numbers. 5972119Speter */ 60316139Smavint newnfs_nfsv3_procid[NFS_V3NPROCS] = { 61132199Sphk NFSPROC_NULL, 62132199Sphk NFSPROC_GETATTR, 6372119Speter NFSPROC_SETATTR, 6472119Speter NFSPROC_NOOP, 6572119Speter NFSPROC_LOOKUP, 6672119Speter NFSPROC_READLINK, 6772119Speter NFSPROC_READ, 6872119Speter NFSPROC_NOOP, 6972119Speter NFSPROC_WRITE, 7072119Speter NFSPROC_CREATE, 7172119Speter NFSPROC_REMOVE, 7272119Speter NFSPROC_RENAME, 7372119Speter NFSPROC_LINK, 74316139Smav NFSPROC_SYMLINK, 75316139Smav NFSPROC_MKDIR, 76316139Smav NFSPROC_RMDIR, 77316139Smav NFSPROC_READDIR, 78316139Smav NFSPROC_FSSTAT, 7939212Sgibbs NFSPROC_NOOP, 80316139Smav NFSPROC_NOOP, 81316139Smav NFSPROC_NOOP, 82316139Smav NFSPROC_NOOP, 83316139Smav}; 84316139Smav 85316139Smav 8639212SgibbsSYSCTL_DECL(_vfs_nfsd); 87316139Smav 88316139SmavSVCPOOL *nfsrvd_pool; 8960938Sjake 9039212Sgibbsstatic int nfs_privport = 0; 91198708SmavSYSCTL_INT(_vfs_nfsd, OID_AUTO, nfs_privport, CTLFLAG_RWTUN, 92198708Smav &nfs_privport, 0, 93316139Smav "Only allow clients using a privileged port for NFSv2 and 3"); 9439212Sgibbs 9539212Sgibbsstatic int nfs_minvers = NFS_VER2; 9639212SgibbsSYSCTL_INT(_vfs_nfsd, OID_AUTO, server_min_nfsvers, CTLFLAG_RWTUN, 97136132Sscottl &nfs_minvers, 0, "The lowest version of NFS handled by the server"); 9839212Sgibbs 9939212Sgibbsstatic int nfs_maxvers = NFS_VER4; 100249585SgaborSYSCTL_INT(_vfs_nfsd, OID_AUTO, server_max_nfsvers, CTLFLAG_RWTUN, 10139212Sgibbs &nfs_maxvers, 0, "The highest version of NFS handled by the server"); 10239212Sgibbs 10339212Sgibbsstatic int nfs_proc(struct nfsrv_descript *, u_int32_t, SVCXPRT *xprt, 10439212Sgibbs struct nfsrvcache **); 10539212Sgibbs 10639212Sgibbsextern u_long sb_max_adj; 10739212Sgibbsextern int newnfs_numnfsd; 10839212Sgibbsextern struct proc *nfsd_master_proc; 10939212Sgibbs 11040603Sken/* 11139212Sgibbs * NFS server system calls 11239212Sgibbs */ 11339212Sgibbs 11440603Skenstatic void 11539212Sgibbsnfssvc_program(struct svc_req *rqst, SVCXPRT *xprt) 11639212Sgibbs{ 11739212Sgibbs struct nfsrv_descript nd; 11839212Sgibbs struct nfsrvcache *rp = NULL; 119168752Sscottl int cacherep, credflavor; 12039212Sgibbs 12139212Sgibbs memset(&nd, 0, sizeof(nd)); 12239212Sgibbs if (rqst->rq_vers == NFS_VER2) { 12339212Sgibbs if (rqst->rq_proc > NFSV2PROC_STATFS || 12439212Sgibbs newnfs_nfsv3_procid[rqst->rq_proc] == NFSPROC_NOOP) { 12539212Sgibbs svcerr_noproc(rqst); 12639212Sgibbs svc_freereq(rqst); 12739212Sgibbs goto out; 12840318Sken } 129256843Smav nd.nd_procnum = newnfs_nfsv3_procid[rqst->rq_proc]; 130230000Sken nd.nd_flag = ND_NFSV2; 131256552Smav } else if (rqst->rq_vers == NFS_VER3) { 132355341Smav if (rqst->rq_proc >= NFS_V3NPROCS) { 133355341Smav svcerr_noproc(rqst); 134256843Smav svc_freereq(rqst); 135256843Smav goto out; 136256843Smav } 137256843Smav nd.nd_procnum = rqst->rq_proc; 13839212Sgibbs nd.nd_flag = ND_NFSV3; 13960938Sjake } else { 14060938Sjake if (rqst->rq_proc != NFSPROC_NULL && 14160938Sjake rqst->rq_proc != NFSV4PROC_COMPOUND) { 14239212Sgibbs svcerr_noproc(rqst); 14339212Sgibbs svc_freereq(rqst); 144256843Smav goto out; 14539212Sgibbs } 14639212Sgibbs nd.nd_procnum = rqst->rq_proc; 14739212Sgibbs nd.nd_flag = ND_NFSV4; 14839212Sgibbs } 14939212Sgibbs 15039212Sgibbs /* 151346758Smav * Note: we want rq_addr, not svc_getrpccaller for nd_nam2 - 15239212Sgibbs * NFS_SRVMAXDATA uses a NULL value for nd_nam2 to detect TCP 15339212Sgibbs * mounts. 15439212Sgibbs */ 15540603Sken nd.nd_mrep = rqst->rq_args; 15640603Sken rqst->rq_args = NULL; 15740603Sken newnfs_realign(&nd.nd_mrep, M_WAITOK); 15840603Sken nd.nd_md = nd.nd_mrep; 15958111Sn_hibma nd.nd_dpos = mtod(nd.nd_md, caddr_t); 16058111Sn_hibma nd.nd_nam = svc_getrpccaller(rqst); 16139212Sgibbs nd.nd_nam2 = rqst->rq_addr; 162223081Sgibbs nd.nd_mreq = NULL; 16339212Sgibbs nd.nd_cred = NULL; 164260541Smav 16539212Sgibbs if (nfs_privport && (nd.nd_flag & ND_NFSV4) == 0) { 166186319Strasz /* Check if source port is privileged */ 167230000Sken u_short port; 168168752Sscottl struct sockaddr *nam = nd.nd_nam; 169168752Sscottl struct sockaddr_in *sin; 17039212Sgibbs 17139212Sgibbs sin = (struct sockaddr_in *)nam; 172288420Smav /* 173288420Smav * INET/INET6 - same code: 17439212Sgibbs * sin_port and sin6_port are at same offset 17539212Sgibbs */ 17639212Sgibbs port = ntohs(sin->sin_port); 17739212Sgibbs if (port >= IPPORT_RESERVED && 17839212Sgibbs nd.nd_procnum != NFSPROC_NULL) { 17939212Sgibbs#ifdef INET6 18039212Sgibbs char b6[INET6_ADDRSTRLEN]; 18139212Sgibbs#if defined(KLD_MODULE) 18239212Sgibbs /* Do not use ip6_sprintf: the nfs module should work without INET6. */ 18339212Sgibbs#define ip6_sprintf(buf, a) \ 184194627Sscottl (sprintf((buf), "%x:%x:%x:%x:%x:%x:%x:%x", \ 18539212Sgibbs (a)->s6_addr16[0], (a)->s6_addr16[1], \ 18639212Sgibbs (a)->s6_addr16[2], (a)->s6_addr16[3], \ 18739212Sgibbs (a)->s6_addr16[4], (a)->s6_addr16[5], \ 18839212Sgibbs (a)->s6_addr16[6], (a)->s6_addr16[7]), \ 18947412Sgibbs (buf)) 19039212Sgibbs#endif 191203108Smav#endif 19239212Sgibbs printf("NFS request from unprivileged port (%s:%d)\n", 19347412Sgibbs#ifdef INET6 19447412Sgibbs sin->sin_family == AF_INET6 ? 19547412Sgibbs ip6_sprintf(b6, &satosin6(sin)->sin6_addr) : 19647412Sgibbs#if defined(KLD_MODULE) 19747412Sgibbs#undef ip6_sprintf 19847412Sgibbs#endif 19947412Sgibbs#endif 20039212Sgibbs inet_ntoa(sin->sin_addr), port); 20139212Sgibbs svcerr_weakauth(rqst); 20239212Sgibbs svc_freereq(rqst); 203256843Smav m_freem(nd.nd_mrep); 204256843Smav goto out; 205168876Sscottl } 206256843Smav } 207168876Sscottl 208168876Sscottl if (nd.nd_procnum != NFSPROC_NULL) { 209256843Smav if (!svc_getcred(rqst, &nd.nd_cred, &credflavor)) { 210256843Smav svcerr_weakauth(rqst); 211168876Sscottl svc_freereq(rqst); 212256843Smav m_freem(nd.nd_mrep); 213256843Smav goto out; 214200180Smav } 215256843Smav 216256843Smav /* Set the flag based on credflavor */ 217223081Sgibbs if (credflavor == RPCSEC_GSS_KRB5) { 218256843Smav nd.nd_flag |= ND_GSS; 219256843Smav } else if (credflavor == RPCSEC_GSS_KRB5I) { 220256843Smav nd.nd_flag |= (ND_GSS | ND_GSSINTEGRITY); 221256843Smav } else if (credflavor == RPCSEC_GSS_KRB5P) { 222256843Smav nd.nd_flag |= (ND_GSS | ND_GSSPRIVACY); 223256843Smav } else if (credflavor != AUTH_SYS) { 224248868Smav svcerr_weakauth(rqst); 225248868Smav svc_freereq(rqst); 226248868Smav m_freem(nd.nd_mrep); 227248868Smav goto out; 228248868Smav } 229248868Smav 230248868Smav#ifdef MAC 231248868Smav mac_cred_associate_nfsd(nd.nd_cred); 232248868Smav#endif 233248868Smav /* 234248868Smav * Get a refcnt (shared lock) on nfsd_suspend_lock. 235248868Smav * NFSSVC_SUSPENDNFSD will take an exclusive lock on 236248868Smav * nfsd_suspend_lock to suspend these threads. 237248868Smav * This must be done here, before the check of 238248868Smav * nfsv4root exports by nfsvno_v4rootexport(). 239248868Smav */ 240248868Smav NFSLOCKV4ROOTMUTEX(); 241248868Smav nfsv4_getref(&nfsd_suspend_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, 242248868Smav NULL); 243248868Smav NFSUNLOCKV4ROOTMUTEX(); 244256843Smav 245248868Smav if ((nd.nd_flag & ND_NFSV4) != 0) { 246248868Smav nd.nd_repstat = nfsvno_v4rootexport(&nd); 247248868Smav if (nd.nd_repstat != 0) { 248248868Smav NFSLOCKV4ROOTMUTEX(); 249248868Smav nfsv4_relref(&nfsd_suspend_lock); 250248868Smav NFSUNLOCKV4ROOTMUTEX(); 251248868Smav svcerr_weakauth(rqst); 252248868Smav svc_freereq(rqst); 253248868Smav m_freem(nd.nd_mrep); 254248868Smav goto out; 255248868Smav } 256248868Smav } 257248868Smav 258248868Smav cacherep = nfs_proc(&nd, rqst->rq_xid, xprt, &rp); 259248868Smav NFSLOCKV4ROOTMUTEX(); 260248868Smav nfsv4_relref(&nfsd_suspend_lock); 26155206Speter NFSUNLOCKV4ROOTMUTEX(); 26239212Sgibbs } else { 263 NFSMGET(nd.nd_mreq); 264 nd.nd_mreq->m_len = 0; 265 cacherep = RC_REPLY; 266 } 267 if (nd.nd_mrep != NULL) 268 m_freem(nd.nd_mrep); 269 270 if (nd.nd_cred != NULL) 271 crfree(nd.nd_cred); 272 273 if (cacherep == RC_DROPIT) { 274 if (nd.nd_mreq != NULL) 275 m_freem(nd.nd_mreq); 276 svc_freereq(rqst); 277 goto out; 278 } 279 280 if (nd.nd_mreq == NULL) { 281 svcerr_decode(rqst); 282 svc_freereq(rqst); 283 goto out; 284 } 285 286 if (nd.nd_repstat & NFSERR_AUTHERR) { 287 svcerr_auth(rqst, nd.nd_repstat & ~NFSERR_AUTHERR); 288 if (nd.nd_mreq != NULL) 289 m_freem(nd.nd_mreq); 290 } else if (!svc_sendreply_mbuf(rqst, nd.nd_mreq)) { 291 svcerr_systemerr(rqst); 292 } 293 if (rp != NULL) { 294 nfsrvd_sentcache(rp, (rqst->rq_reply_seq != 0 || 295 SVC_ACK(xprt, NULL)), rqst->rq_reply_seq); 296 } 297 svc_freereq(rqst); 298 299out: 300 if (softdep_ast_cleanup != NULL) 301 softdep_ast_cleanup(); 302 NFSEXITCODE(0); 303} 304 305/* 306 * Check the cache and, optionally, do the RPC. 307 * Return the appropriate cache response. 308 */ 309static int 310nfs_proc(struct nfsrv_descript *nd, u_int32_t xid, SVCXPRT *xprt, 311 struct nfsrvcache **rpp) 312{ 313 struct thread *td = curthread; 314 int cacherep = RC_DOIT, isdgram, taglen = -1; 315 struct mbuf *m; 316 u_char tag[NFSV4_SMALLSTR + 1], *tagstr = NULL; 317 u_int32_t minorvers = 0; 318 uint32_t ack; 319 320 *rpp = NULL; 321 if (nd->nd_nam2 == NULL) { 322 nd->nd_flag |= ND_STREAMSOCK; 323 isdgram = 0; 324 } else { 325 isdgram = 1; 326 } 327 328 /* 329 * Two cases: 330 * 1 - For NFSv2 over UDP, if we are near our malloc/mget 331 * limit, just drop the request. There is no 332 * NFSERR_RESOURCE or NFSERR_DELAY for NFSv2 and the 333 * client will timeout/retry over UDP in a little while. 334 * 2 - nd_repstat == 0 && nd_mreq == NULL, which 335 * means a normal nfs rpc, so check the cache 336 */ 337 if ((nd->nd_flag & ND_NFSV2) && nd->nd_nam2 != NULL && 338 nfsrv_mallocmget_limit()) { 339 cacherep = RC_DROPIT; 340 } else { 341 /* 342 * For NFSv3, play it safe and assume that the client is 343 * doing retries on the same TCP connection. 344 */ 345 if ((nd->nd_flag & (ND_NFSV4 | ND_STREAMSOCK)) == 346 ND_STREAMSOCK) 347 nd->nd_flag |= ND_SAMETCPCONN; 348 nd->nd_retxid = xid; 349 nd->nd_tcpconntime = NFSD_MONOSEC; 350 nd->nd_sockref = xprt->xp_sockref; 351 if ((nd->nd_flag & ND_NFSV4) != 0) 352 nfsd_getminorvers(nd, tag, &tagstr, &taglen, 353 &minorvers); 354 if ((nd->nd_flag & ND_NFSV41) != 0) 355 /* NFSv4.1 caches replies in the session slots. */ 356 cacherep = RC_DOIT; 357 else { 358 cacherep = nfsrvd_getcache(nd); 359 ack = 0; 360 SVC_ACK(xprt, &ack); 361 nfsrc_trimcache(xprt->xp_sockref, ack, 0); 362 } 363 } 364 365 /* 366 * Handle the request. There are three cases. 367 * RC_DOIT - do the RPC 368 * RC_REPLY - return the reply already created 369 * RC_DROPIT - just throw the request away 370 */ 371 if (cacherep == RC_DOIT) { 372 if ((nd->nd_flag & ND_NFSV41) != 0) 373 nd->nd_xprt = xprt; 374 nfsrvd_dorpc(nd, isdgram, tagstr, taglen, minorvers, td); 375 if ((nd->nd_flag & ND_NFSV41) != 0) { 376 if (nd->nd_repstat != NFSERR_REPLYFROMCACHE && 377 (nd->nd_flag & ND_SAVEREPLY) != 0) { 378 /* Cache a copy of the reply. */ 379 m = m_copym(nd->nd_mreq, 0, M_COPYALL, 380 M_WAITOK); 381 } else 382 m = NULL; 383 if ((nd->nd_flag & ND_HASSEQUENCE) != 0) 384 nfsrv_cache_session(nd->nd_sessionid, 385 nd->nd_slotid, nd->nd_repstat, &m); 386 if (nd->nd_repstat == NFSERR_REPLYFROMCACHE) 387 nd->nd_repstat = 0; 388 cacherep = RC_REPLY; 389 } else { 390 if (nd->nd_repstat == NFSERR_DONTREPLY) 391 cacherep = RC_DROPIT; 392 else 393 cacherep = RC_REPLY; 394 *rpp = nfsrvd_updatecache(nd); 395 } 396 } 397 if (tagstr != NULL && taglen > NFSV4_SMALLSTR) 398 free(tagstr, M_TEMP); 399 400 NFSEXITCODE2(0, nd); 401 return (cacherep); 402} 403 404static void 405nfssvc_loss(SVCXPRT *xprt) 406{ 407 uint32_t ack; 408 409 ack = 0; 410 SVC_ACK(xprt, &ack); 411 nfsrc_trimcache(xprt->xp_sockref, ack, 1); 412} 413 414/* 415 * Adds a socket to the list for servicing by nfsds. 416 */ 417int 418nfsrvd_addsock(struct file *fp) 419{ 420 int siz; 421 struct socket *so; 422 int error = 0; 423 SVCXPRT *xprt; 424 static u_int64_t sockref = 0; 425 426 so = fp->f_data; 427 428 siz = sb_max_adj; 429 error = soreserve(so, siz, siz); 430 if (error) 431 goto out; 432 433 /* 434 * Steal the socket from userland so that it doesn't close 435 * unexpectedly. 436 */ 437 if (so->so_type == SOCK_DGRAM) 438 xprt = svc_dg_create(nfsrvd_pool, so, 0, 0); 439 else 440 xprt = svc_vc_create(nfsrvd_pool, so, 0, 0); 441 if (xprt) { 442 fp->f_ops = &badfileops; 443 fp->f_data = NULL; 444 xprt->xp_sockref = ++sockref; 445 if (nfs_minvers == NFS_VER2) 446 svc_reg(xprt, NFS_PROG, NFS_VER2, nfssvc_program, 447 NULL); 448 if (nfs_minvers <= NFS_VER3 && nfs_maxvers >= NFS_VER3) 449 svc_reg(xprt, NFS_PROG, NFS_VER3, nfssvc_program, 450 NULL); 451 if (nfs_maxvers >= NFS_VER4) 452 svc_reg(xprt, NFS_PROG, NFS_VER4, nfssvc_program, 453 NULL); 454 if (so->so_type == SOCK_STREAM) 455 svc_loss_reg(xprt, nfssvc_loss); 456 SVC_RELEASE(xprt); 457 } 458 459out: 460 NFSEXITCODE(error); 461 return (error); 462} 463 464/* 465 * Called by nfssvc() for nfsds. Just loops around servicing rpc requests 466 * until it is killed by a signal. 467 */ 468int 469nfsrvd_nfsd(struct thread *td, struct nfsd_nfsd_args *args) 470{ 471 char principal[MAXHOSTNAMELEN + 5]; 472 struct proc *p; 473 int error = 0; 474 bool_t ret2, ret3, ret4; 475 476 error = copyinstr(args->principal, principal, sizeof (principal), 477 NULL); 478 if (error) 479 goto out; 480 481 /* 482 * Only the first nfsd actually does any work. The RPC code 483 * adds threads to it as needed. Any extra processes offered 484 * by nfsd just exit. If nfsd is new enough, it will call us 485 * once with a structure that specifies how many threads to 486 * use. 487 */ 488 NFSD_LOCK(); 489 if (newnfs_numnfsd == 0) { 490 p = td->td_proc; 491 PROC_LOCK(p); 492 p->p_flag2 |= P2_AST_SU; 493 PROC_UNLOCK(p); 494 newnfs_numnfsd++; 495 496 NFSD_UNLOCK(); 497 498 /* An empty string implies AUTH_SYS only. */ 499 if (principal[0] != '\0') { 500 ret2 = rpc_gss_set_svc_name_call(principal, 501 "kerberosv5", GSS_C_INDEFINITE, NFS_PROG, NFS_VER2); 502 ret3 = rpc_gss_set_svc_name_call(principal, 503 "kerberosv5", GSS_C_INDEFINITE, NFS_PROG, NFS_VER3); 504 ret4 = rpc_gss_set_svc_name_call(principal, 505 "kerberosv5", GSS_C_INDEFINITE, NFS_PROG, NFS_VER4); 506 507 if (!ret2 || !ret3 || !ret4) 508 printf("nfsd: can't register svc name\n"); 509 } 510 511 nfsrvd_pool->sp_minthreads = args->minthreads; 512 nfsrvd_pool->sp_maxthreads = args->maxthreads; 513 514 svc_run(nfsrvd_pool); 515 516 if (principal[0] != '\0') { 517 rpc_gss_clear_svc_name_call(NFS_PROG, NFS_VER2); 518 rpc_gss_clear_svc_name_call(NFS_PROG, NFS_VER3); 519 rpc_gss_clear_svc_name_call(NFS_PROG, NFS_VER4); 520 } 521 522 NFSD_LOCK(); 523 newnfs_numnfsd--; 524 nfsrvd_init(1); 525 PROC_LOCK(p); 526 p->p_flag2 &= ~P2_AST_SU; 527 PROC_UNLOCK(p); 528 } 529 NFSD_UNLOCK(); 530 531out: 532 NFSEXITCODE(error); 533 return (error); 534} 535 536/* 537 * Initialize the data structures for the server. 538 * Handshake with any new nfsds starting up to avoid any chance of 539 * corruption. 540 */ 541void 542nfsrvd_init(int terminating) 543{ 544 545 NFSD_LOCK_ASSERT(); 546 547 if (terminating) { 548 nfsd_master_proc = NULL; 549 NFSD_UNLOCK(); 550 svcpool_destroy(nfsrvd_pool); 551 nfsrvd_pool = NULL; 552 NFSD_LOCK(); 553 } 554 555 NFSD_UNLOCK(); 556 557 nfsrvd_pool = svcpool_create("nfsd", SYSCTL_STATIC_CHILDREN(_vfs_nfsd)); 558 nfsrvd_pool->sp_rcache = NULL; 559 nfsrvd_pool->sp_assign = fhanew_assign; 560 nfsrvd_pool->sp_done = fha_nd_complete; 561 562 NFSD_LOCK(); 563} 564 565