1190815Srmacklem/*- 2190815Srmacklem * Copyright (c) 1989, 1993 3190815Srmacklem * The Regents of the University of California. All rights reserved. 4190815Srmacklem * 5190815Srmacklem * This code is derived from software contributed to Berkeley by 6190815Srmacklem * Rick Macklem at The University of Guelph. 7190815Srmacklem * 8190815Srmacklem * Redistribution and use in source and binary forms, with or without 9190815Srmacklem * modification, are permitted provided that the following conditions 10190815Srmacklem * are met: 11190815Srmacklem * 1. Redistributions of source code must retain the above copyright 12190815Srmacklem * notice, this list of conditions and the following disclaimer. 13190815Srmacklem * 2. Redistributions in binary form must reproduce the above copyright 14190815Srmacklem * notice, this list of conditions and the following disclaimer in the 15190815Srmacklem * documentation and/or other materials provided with the distribution. 16190815Srmacklem * 4. Neither the name of the University nor the names of its contributors 17190815Srmacklem * may be used to endorse or promote products derived from this software 18190815Srmacklem * without specific prior written permission. 19190815Srmacklem * 20190815Srmacklem * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21190815Srmacklem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22190815Srmacklem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23190815Srmacklem * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24190815Srmacklem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25190815Srmacklem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26190815Srmacklem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27190815Srmacklem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28190815Srmacklem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29190815Srmacklem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30190815Srmacklem * SUCH DAMAGE. 31190815Srmacklem * 32190815Srmacklem */ 33190815Srmacklem 34190815Srmacklem#include <sys/cdefs.h> 35190815Srmacklem__FBSDID("$FreeBSD$"); 36190815Srmacklem 37190815Srmacklem#include "opt_nfs.h" 38190815Srmacklem 39190815Srmacklem#include <sys/param.h> 40190815Srmacklem#include <sys/systm.h> 41190815Srmacklem#include <sys/sysproto.h> 42190815Srmacklem#include <sys/kernel.h> 43190815Srmacklem#include <sys/sysctl.h> 44190815Srmacklem#include <sys/priv.h> 45190815Srmacklem#include <sys/proc.h> 46190815Srmacklem#include <sys/lock.h> 47190815Srmacklem#include <sys/mutex.h> 48190815Srmacklem#include <sys/module.h> 49190815Srmacklem#include <sys/sysent.h> 50190815Srmacklem#include <sys/syscall.h> 51190815Srmacklem#include <sys/sysproto.h> 52190815Srmacklem 53190815Srmacklem#include <security/audit/audit.h> 54190815Srmacklem 55190815Srmacklem#include <nfs/nfssvc.h> 56190815Srmacklem 57190815Srmacklemstatic int nfssvc_offset = SYS_nfssvc; 58190815Srmacklemstatic struct sysent nfssvc_prev_sysent; 59190815SrmacklemMAKE_SYSENT(nfssvc); 60190815Srmacklem 61190815Srmacklem/* 62190815Srmacklem * This tiny module simply handles the nfssvc() system call. The other 63190815Srmacklem * nfs modules that use the system call register themselves by setting 64190815Srmacklem * the nfsd_call_xxx function pointers non-NULL. 65190815Srmacklem */ 66190815Srmacklem 67190815Srmacklemint (*nfsd_call_nfsserver)(struct thread *, struct nfssvc_args *) = NULL; 68190815Srmacklemint (*nfsd_call_nfscommon)(struct thread *, struct nfssvc_args *) = NULL; 69190815Srmacklemint (*nfsd_call_nfscl)(struct thread *, struct nfssvc_args *) = NULL; 70190815Srmacklemint (*nfsd_call_nfsd)(struct thread *, struct nfssvc_args *) = NULL; 71190815Srmacklem 72190815Srmacklem/* 73190815Srmacklem * Nfs server psuedo system call for the nfsd's 74190815Srmacklem */ 75190815Srmacklemint 76225617Skmacysys_nfssvc(struct thread *td, struct nfssvc_args *uap) 77190815Srmacklem{ 78190815Srmacklem int error; 79190815Srmacklem 80190815Srmacklem KASSERT(!mtx_owned(&Giant), ("nfssvc(): called with Giant")); 81190815Srmacklem 82195104Srwatson AUDIT_ARG_CMD(uap->flag); 83190815Srmacklem 84221473Srmacklem /* Allow anyone to get the stats. */ 85221473Srmacklem if ((uap->flag & ~NFSSVC_GETSTATS) != 0) { 86221473Srmacklem error = priv_check(td, PRIV_NFS_DAEMON); 87221473Srmacklem if (error != 0) 88221473Srmacklem return (error); 89221473Srmacklem } 90190815Srmacklem error = EINVAL; 91190815Srmacklem if ((uap->flag & (NFSSVC_ADDSOCK | NFSSVC_OLDNFSD | NFSSVC_NFSD)) && 92190815Srmacklem nfsd_call_nfsserver != NULL) 93190815Srmacklem error = (*nfsd_call_nfsserver)(td, uap); 94243782Srmacklem else if ((uap->flag & (NFSSVC_CBADDSOCK | NFSSVC_NFSCBD | 95243782Srmacklem NFSSVC_DUMPMNTOPTS)) && nfsd_call_nfscl != NULL) 96190815Srmacklem error = (*nfsd_call_nfscl)(td, uap); 97190815Srmacklem else if ((uap->flag & (NFSSVC_IDNAME | NFSSVC_GETSTATS | 98190815Srmacklem NFSSVC_GSSDADDPORT | NFSSVC_GSSDADDFIRST | NFSSVC_GSSDDELETEALL | 99190815Srmacklem NFSSVC_NFSUSERDPORT | NFSSVC_NFSUSERDDELPORT)) && 100190815Srmacklem nfsd_call_nfscommon != NULL) 101190815Srmacklem error = (*nfsd_call_nfscommon)(td, uap); 102190815Srmacklem else if ((uap->flag & (NFSSVC_NFSDNFSD | NFSSVC_NFSDADDSOCK | 103190815Srmacklem NFSSVC_PUBLICFH | NFSSVC_V4ROOTEXPORT | NFSSVC_NOPUBLICFH | 104190815Srmacklem NFSSVC_STABLERESTART | NFSSVC_ADMINREVOKE | 105241561Srmacklem NFSSVC_DUMPCLIENTS | NFSSVC_DUMPLOCKS | NFSSVC_BACKUPSTABLE | 106241561Srmacklem NFSSVC_SUSPENDNFSD | NFSSVC_RESUMENFSD)) && 107190815Srmacklem nfsd_call_nfsd != NULL) 108190815Srmacklem error = (*nfsd_call_nfsd)(td, uap); 109190815Srmacklem if (error == EINTR || error == ERESTART) 110190815Srmacklem error = 0; 111190815Srmacklem return (error); 112190815Srmacklem} 113190815Srmacklem 114190815Srmacklem/* 115190815Srmacklem * Called once to initialize data structures... 116190815Srmacklem */ 117190815Srmacklemstatic int 118190815Srmacklemnfssvc_modevent(module_t mod, int type, void *data) 119190815Srmacklem{ 120190815Srmacklem static int registered; 121190815Srmacklem int error = 0; 122190815Srmacklem 123190815Srmacklem switch (type) { 124190815Srmacklem case MOD_LOAD: 125190815Srmacklem error = syscall_register(&nfssvc_offset, &nfssvc_sysent, 126190815Srmacklem &nfssvc_prev_sysent); 127190815Srmacklem if (error) 128190815Srmacklem break; 129190815Srmacklem registered = 1; 130190815Srmacklem break; 131190815Srmacklem 132190815Srmacklem case MOD_UNLOAD: 133190815Srmacklem if (nfsd_call_nfsserver != NULL || nfsd_call_nfscommon != NULL 134190815Srmacklem || nfsd_call_nfscl != NULL || nfsd_call_nfsd != NULL) { 135190815Srmacklem error = EBUSY; 136190815Srmacklem break; 137190815Srmacklem } 138190815Srmacklem if (registered) 139190815Srmacklem syscall_deregister(&nfssvc_offset, &nfssvc_prev_sysent); 140190815Srmacklem registered = 0; 141190815Srmacklem break; 142190815Srmacklem default: 143190815Srmacklem error = EOPNOTSUPP; 144190815Srmacklem break; 145190815Srmacklem } 146190815Srmacklem return error; 147190815Srmacklem} 148190815Srmacklemstatic moduledata_t nfssvc_mod = { 149190815Srmacklem "nfssvc", 150190815Srmacklem nfssvc_modevent, 151241394Skevlo NULL, 152190815Srmacklem}; 153190815SrmacklemDECLARE_MODULE(nfssvc, nfssvc_mod, SI_SUB_VFS, SI_ORDER_ANY); 154190815Srmacklem 155190815Srmacklem/* So that loader and kldload(2) can find us, wherever we are.. */ 156190815SrmacklemMODULE_VERSION(nfssvc, 1); 157190815Srmacklem 158