xref: /illumos-gate/usr/src/uts/common/fs/nfs/nfs_sys.c (revision fea9cb91bd8e12d84069b4dab1268363668b4bff)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 1983,1984,1985,1986,1987,1988,1989  AT&T.
27  * All rights reserved.
28  */
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #include <sys/types.h>
33 #include <rpc/types.h>
34 #include <sys/systm.h>
35 #include <sys/vfs.h>
36 #include <sys/errno.h>
37 #include <sys/cred.h>
38 #include <sys/policy.h>
39 #include <sys/siginfo.h>
40 #include <sys/proc.h>		/* for exit() declaration */
41 #include <nfs/nfs4.h>
42 #include <nfs/nfssys.h>
43 #include <sys/thread.h>
44 #include <rpc/auth.h>
45 #include <rpc/rpcsys.h>
46 #include <rpc/svc.h>
47 
48 /*
49  * This is filled in with an appropriate address for the
50  * function that will traverse the rfs4_client_t table
51  * and mark any matching IP Address as "forced_expire".
52  *
53  * It is the server init() function that plops the
54  * function pointer.
55  */
56 void (*rfs4_client_clrst)(struct nfs4clrst_args *) = NULL;
57 
58 /* This filled in by nfssrv:_init() */
59 void (*nfs_srv_quiesce_func)(void) = NULL;
60 
61 /*
62  * These will be reset by klmmod:lm_svc(), when lockd starts NLM service,
63  * based on values read by lockd from /etc/default/nfs. Since nfssrv depends on
64  * klmmod, the declarations need to be here (in nfs, on which both depend) so
65  * that nfssrv can see the klmmod changes.
66  * When the dependency of NFSv4 on NLM/lockd is removed, this will need to
67  * be adjusted.
68  */
69 #define	RFS4_LEASETIME 90			/* seconds */
70 time_t rfs4_lease_time = RFS4_LEASETIME;
71 time_t rfs4_grace_period = RFS4_LEASETIME;
72 
73 int
74 nfssys(enum nfssys_op opcode, void *arg)
75 {
76 	int error = 0;
77 
78 	if (!(opcode == NFS_REVAUTH || opcode == NFS4_SVC) &&
79 	    secpolicy_nfs(CRED()) != 0)
80 		return (set_errno(EPERM));
81 
82 	switch (opcode) {
83 	case NFS4_CLR_STATE: { /* Clear NFS4 client state */
84 		struct nfs4clrst_args clr;
85 		STRUCT_DECL(nfs4clrst_args, u_clr);
86 
87 		/*
88 		 * If the server is not loaded then no point in
89 		 * clearing nothing :-)
90 		 */
91 		if (rfs4_client_clrst == NULL) {
92 			break;
93 		}
94 
95 		if (!INGLOBALZONE(curproc))
96 			return (set_errno(EPERM));
97 
98 		STRUCT_INIT(u_clr, get_udatamodel());
99 
100 		if (copyin(arg, STRUCT_BUF(u_clr), STRUCT_SIZE(u_clr)))
101 			return (set_errno(EFAULT));
102 
103 		clr.vers = STRUCT_FGET(u_clr, vers);
104 
105 		if (clr.vers != NFS4_CLRST_VERSION)
106 			return (set_errno(EINVAL));
107 
108 		clr.addr_type = STRUCT_FGET(u_clr, addr_type);
109 		clr.ap = STRUCT_FGETP(u_clr, ap);
110 		rfs4_client_clrst(&clr);
111 		break;
112 	}
113 
114 	case SVCPOOL_CREATE: { /* setup an RPC server thread pool */
115 		struct svcpool_args p;
116 
117 		if (copyin(arg, &p, sizeof (p)))
118 			return (set_errno(EFAULT));
119 
120 		error = svc_pool_create(&p);
121 		break;
122 	}
123 
124 	case SVCPOOL_WAIT: { /* wait in kernel for threads to be needed */
125 		int id;
126 
127 		if (copyin(arg, &id, sizeof (id)))
128 			return (set_errno(EFAULT));
129 
130 		error = svc_wait(id);
131 		break;
132 	}
133 
134 	case SVCPOOL_RUN: { /* give work to a runnable thread */
135 		int id;
136 
137 		if (copyin(arg, &id, sizeof (id)))
138 			return (set_errno(EFAULT));
139 
140 		error = svc_do_run(id);
141 		break;
142 	}
143 
144 	case RDMA_SVC_INIT: {
145 		struct rdma_svc_args rsa;
146 		char netstore[20] = "tcp";
147 
148 		if (!INGLOBALZONE(curproc))
149 			return (set_errno(EPERM));
150 		if (get_udatamodel() != DATAMODEL_NATIVE) {
151 			STRUCT_DECL(rdma_svc_args, ursa);
152 
153 			STRUCT_INIT(ursa, get_udatamodel());
154 			if (copyin(arg, STRUCT_BUF(ursa), STRUCT_SIZE(ursa)))
155 				return (set_errno(EFAULT));
156 
157 			rsa.poolid = STRUCT_FGET(ursa, poolid);
158 			rsa.nfs_versmin = STRUCT_FGET(ursa, nfs_versmin);
159 			rsa.nfs_versmax = STRUCT_FGET(ursa, nfs_versmax);
160 			rsa.delegation = STRUCT_FGET(ursa, delegation);
161 		} else {
162 			if (copyin(arg, &rsa, sizeof (rsa)))
163 				return (set_errno(EFAULT));
164 		}
165 		rsa.netid = netstore;
166 
167 		error = rdma_start(&rsa);
168 		break;
169 	}
170 
171 	case NFS_SVC: { /* NFS server daemon */
172 		STRUCT_DECL(nfs_svc_args, nsa);
173 
174 		if (!INGLOBALZONE(curproc))
175 			return (set_errno(EPERM));
176 		STRUCT_INIT(nsa, get_udatamodel());
177 
178 		if (copyin(arg, STRUCT_BUF(nsa), STRUCT_SIZE(nsa)))
179 			return (set_errno(EFAULT));
180 
181 		error = nfs_svc(STRUCT_BUF(nsa), get_udatamodel());
182 		break;
183 	}
184 
185 	/* Request that NFS server quiesce on next shutdown */
186 	case NFS_SVC_REQUEST_QUIESCE: {
187 		int id;
188 
189 		/* check that nfssrv module is loaded */
190 		if (nfs_srv_quiesce_func == NULL)
191 			return (set_errno(ENOTSUP));
192 
193 		if (copyin(arg, &id, sizeof (id)))
194 			return (set_errno(EFAULT));
195 
196 		error = svc_pool_control(id, SVCPSET_SHUTDOWN_PROC,
197 		    (void *)nfs_srv_quiesce_func);
198 		break;
199 	}
200 
201 	case EXPORTFS: { /* export a file system */
202 		STRUCT_DECL(exportfs_args, ea);
203 
204 		if (!INGLOBALZONE(curproc))
205 			return (set_errno(EPERM));
206 		STRUCT_INIT(ea, get_udatamodel());
207 		if (copyin(arg, STRUCT_BUF(ea), STRUCT_SIZE(ea)))
208 			return (set_errno(EFAULT));
209 
210 		error = exportfs(STRUCT_BUF(ea), get_udatamodel(), CRED());
211 		break;
212 	}
213 
214 	case NFS_GETFH: { /* get a file handle */
215 		STRUCT_DECL(nfs_getfh_args, nga);
216 
217 		if (!INGLOBALZONE(curproc))
218 			return (set_errno(EPERM));
219 		STRUCT_INIT(nga, get_udatamodel());
220 		if (copyin(arg, STRUCT_BUF(nga), STRUCT_SIZE(nga)))
221 			return (set_errno(EFAULT));
222 
223 		error = nfs_getfh(STRUCT_BUF(nga), get_udatamodel(), CRED());
224 		break;
225 	}
226 
227 	case NFS_REVAUTH: { /* revoke the cached credentials for the uid */
228 		STRUCT_DECL(nfs_revauth_args, nra);
229 
230 		STRUCT_INIT(nra, get_udatamodel());
231 		if (copyin(arg, STRUCT_BUF(nra), STRUCT_SIZE(nra)))
232 			return (set_errno(EFAULT));
233 
234 		/* This call performs its own privilege checking */
235 		error = sec_clnt_revoke(STRUCT_FGET(nra, authtype),
236 		    STRUCT_FGET(nra, uid), CRED(), NULL, get_udatamodel());
237 		break;
238 	}
239 
240 	case LM_SVC: { /* LM server daemon */
241 		struct lm_svc_args lsa;
242 
243 		if (get_udatamodel() != DATAMODEL_NATIVE) {
244 			STRUCT_DECL(lm_svc_args, ulsa);
245 
246 			STRUCT_INIT(ulsa, get_udatamodel());
247 			if (copyin(arg, STRUCT_BUF(ulsa), STRUCT_SIZE(ulsa)))
248 				return (set_errno(EFAULT));
249 
250 			lsa.version = STRUCT_FGET(ulsa, version);
251 			lsa.fd = STRUCT_FGET(ulsa, fd);
252 			lsa.n_fmly = STRUCT_FGET(ulsa, n_fmly);
253 			lsa.n_proto = STRUCT_FGET(ulsa, n_proto);
254 			lsa.n_rdev = expldev(STRUCT_FGET(ulsa, n_rdev));
255 			lsa.debug = STRUCT_FGET(ulsa, debug);
256 			lsa.timout = STRUCT_FGET(ulsa, timout);
257 			lsa.grace = STRUCT_FGET(ulsa, grace);
258 			lsa.retransmittimeout = STRUCT_FGET(ulsa,
259 			    retransmittimeout);
260 		} else {
261 			if (copyin(arg, &lsa, sizeof (lsa)))
262 				return (set_errno(EFAULT));
263 		}
264 
265 		error = lm_svc(&lsa);
266 		break;
267 	}
268 
269 	case KILL_LOCKMGR: {
270 		error = lm_shutdown();
271 		break;
272 	}
273 
274 	case LOG_FLUSH:	{	/* Flush log buffer and possibly rename */
275 		STRUCT_DECL(nfsl_flush_args, nfa);
276 
277 		STRUCT_INIT(nfa, get_udatamodel());
278 		if (copyin(arg, STRUCT_BUF(nfa), STRUCT_SIZE(nfa)))
279 			return (set_errno(EFAULT));
280 
281 		error = nfsl_flush(STRUCT_BUF(nfa), get_udatamodel());
282 		break;
283 	}
284 
285 	case NFS4_SVC: { /* NFS client callback daemon */
286 
287 		STRUCT_DECL(nfs4_svc_args, nsa);
288 
289 		STRUCT_INIT(nsa, get_udatamodel());
290 
291 		if (copyin(arg, STRUCT_BUF(nsa), STRUCT_SIZE(nsa)))
292 			return (set_errno(EFAULT));
293 
294 		error = nfs4_svc(STRUCT_BUF(nsa), get_udatamodel());
295 		break;
296 	}
297 
298 	case NFS_IDMAP: {
299 		struct nfsidmap_args idm;
300 
301 		if (copyin(arg, &idm, sizeof (idm)))
302 			return (set_errno(EFAULT));
303 
304 		nfs_idmap_args(&idm);
305 		error = 0;
306 		break;
307 	}
308 
309 	default:
310 		error = EINVAL;
311 		break;
312 	}
313 
314 	return ((error != 0) ? set_errno(error) : 0);
315 }
316