/* * Called by nfssvc() for nfsds. Just loops around servicing rpc requests * until it is killed by a signal. */ int nfsrvd_nfsd(struct thread *td, struct nfsd_nfsd_args *args) { char principal[MAXHOSTNAMELEN + 5]; int error = 0; bool_t ret2, ret3, ret4; error = copyinstr(args->principal, principal, sizeof (principal), NULL); if (error) goto out; /* * Only the first nfsd actually does any work. The RPC code * adds threads to it as needed. Any extra processes offered * by nfsd just exit. If nfsd is new enough, it will call us * once with a structure that specifies how many threads to * use. */ NFSD_LOCK(); if (newnfs_numnfsd == 0) { newnfs_numnfsd++; NFSD_UNLOCK(); /* An empty string implies AUTH_SYS only. */ if (principal[0] != '\0') { ret2 = rpc_gss_set_svc_name_call(principal, "kerberosv5", GSS_C_INDEFINITE, NFS_PROG, NFS_VER2); ret3 = rpc_gss_set_svc_name_call(principal, "kerberosv5", GSS_C_INDEFINITE, NFS_PROG, NFS_VER3); ret4 = rpc_gss_set_svc_name_call(principal, "kerberosv5", GSS_C_INDEFINITE, NFS_PROG, NFS_VER4); if (!ret2 || !ret3 || !ret4) printf("nfsd: can't register svc name\n"); } nfsrvd_pool->sp_minthreads = args->minthreads; nfsrvd_pool->sp_maxthreads = args->maxthreads; svc_run(nfsrvd_pool); if (principal[0] != '\0') { rpc_gss_clear_svc_name_call(NFS_PROG, NFS_VER2); rpc_gss_clear_svc_name_call(NFS_PROG, NFS_VER3); rpc_gss_clear_svc_name_call(NFS_PROG, NFS_VER4); } NFSD_LOCK(); newnfs_numnfsd--; nfsrvd_init(1); } NFSD_UNLOCK(); out: NFSEXITCODE(error); return (error); }
/* * Called by nfssvc() for nfscbds. Just loops around servicing rpc requests * until it is killed by a signal. * * For now, only support callbacks via RPCSEC_GSS if there is a KerberosV * keytab entry with a host based entry in it on the client. (I'm not even * sure that getting Acceptor credentials for a user principal with a * credentials cache is possible, but even if it is, major changes to the * kgssapi would be required.) * I don't believe that this is a serious limitation since, as of 2009, most * NFSv4 servers supporting callbacks are using AUTH_SYS for callbacks even * when the client is using RPCSEC_GSS. (This BSD server uses AUTH_SYS * for callbacks unless nfsrv_gsscallbackson is set non-zero.) */ int nfscbd_nfsd(struct thread *td, struct nfsd_nfscbd_args *args) { char principal[128]; int error; if (args != NULL) { error = copyinstr(args->principal, principal, sizeof(principal), NULL); if (error) return (error); } else { principal[0] = '\0'; } /* * Only the first nfsd actually does any work. The RPC code * adds threads to it as needed. Any extra processes offered * by nfsd just exit. If nfsd is new enough, it will call us * once with a structure that specifies how many threads to * use. */ NFSD_LOCK(); if (nfs_numnfscbd == 0) { nfs_numnfscbd++; NFSD_UNLOCK(); if (principal[0] != '\0') rpc_gss_set_svc_name_call(principal, "kerberosv5", GSS_C_INDEFINITE, NFS_CALLBCKPROG, NFSV4_CBVERS); nfscbd_pool->sp_minthreads = 4; nfscbd_pool->sp_maxthreads = 4; svc_run(nfscbd_pool); rpc_gss_clear_svc_name_call(NFS_CALLBCKPROG, NFSV4_CBVERS); NFSD_LOCK(); nfs_numnfscbd--; nfsrvd_cbinit(1); } NFSD_UNLOCK(); return (0); }
/* * Initialize the data structures for the server. * Handshake with any new nfsds starting up to avoid any chance of * corruption. */ void nfsrvd_init(int terminating) { NFSD_LOCK_ASSERT(); if (terminating) { nfsd_master_proc = NULL; NFSD_UNLOCK(); svcpool_destroy(nfsrvd_pool); nfsrvd_pool = NULL; NFSD_LOCK(); } NFSD_UNLOCK(); nfsrvd_pool = svcpool_create("nfsd", SYSCTL_STATIC_CHILDREN(_vfs_nfsd)); nfsrvd_pool->sp_rcache = NULL; nfsrvd_pool->sp_assign = fhanew_assign; nfsrvd_pool->sp_done = fha_nd_complete; NFSD_LOCK(); }
/* * Initialize the data structures for the server. * Handshake with any new nfsds starting up to avoid any chance of * corruption. */ void nfsrvd_cbinit(int terminating) { NFSD_LOCK_ASSERT(); if (terminating) { /* Wait for any xprt registrations to complete. */ while (nfs_numnfscbd > 0) msleep(&nfs_numnfscbd, NFSDLOCKMUTEXPTR, PZERO, "nfscbdt", 0); } if (nfscbd_pool == NULL) { NFSD_UNLOCK(); nfscbd_pool = svcpool_create("nfscbd", NULL); nfscbd_pool->sp_rcache = NULL; nfscbd_pool->sp_assign = NULL; nfscbd_pool->sp_done = NULL; NFSD_LOCK(); } }
/* * Called once to initialize data structures... */ static int nfsrv_modevent(module_t mod, int type, void *data) { int error = 0; switch (type) { case MOD_LOAD: mtx_init(&nfsd_mtx, "nfsd_mtx", NULL, MTX_DEF); nfsrv_nfs_true = txdr_unsigned(TRUE); nfsrv_nfs_false = txdr_unsigned(FALSE); nfsrv_nfs_xdrneg1 = txdr_unsigned(-1); nfsrv_ticks = (hz * NFS_TICKINTVL + 500) / 1000; if (nfsrv_ticks < 1) nfsrv_ticks = 1; NFSD_LOCK(); nfsrv_init(0); /* Init server data structures */ NFSD_UNLOCK(); nfsd_call_nfsserver = nfssvc_nfsserver; break; case MOD_UNLOAD: if (nfsrv_numnfsd != 0) { error = EBUSY; break; } nfsd_call_nfsserver = NULL; callout_drain(&nfsrv_callout); mtx_destroy(&nfsd_mtx); break; default: error = EOPNOTSUPP; break; } return error; }