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