4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T.
26 * All rights reserved.
29 #include <sys/types.h>
30 #include <rpc/types.h>
31 #include <sys/systm.h>
33 #include <sys/errno.h>
35 #include <sys/policy.h>
36 #include <sys/siginfo.h>
37 #include <sys/proc.h> /* for exit() declaration */
40 #include <nfs/nfssys.h>
41 #include <sys/thread.h>
43 #include <rpc/rpcsys.h>
47 * This is filled in with an appropriate address for the
48 * function that will traverse the rfs4_client_t table
49 * and mark any matching IP Address as "forced_expire".
51 * It is the server init() function that plops the
54 void (*rfs4_client_clrst
)(struct nfs4clrst_args
*) = NULL
;
56 /* This filled in by nfssrv:_init() */
57 void (*nfs_srv_quiesce_func
)(void) = NULL
;
59 extern void nfscmd_args(uint_t
);
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
69 #define RFS4_LEASETIME 90 /* seconds */
70 time_t rfs4_lease_time
= RFS4_LEASETIME
;
71 time_t rfs4_grace_period
= RFS4_LEASETIME
;
73 /* DSS: distributed stable storage */
74 size_t nfs4_dss_buflen
= 0;
75 /* This filled in by nfssrv:_init() */
76 int (*nfs_srv_dss_func
)(char *, size_t) = NULL
;
81 STRUCT_DECL(exportfs_args
, ea
);
83 if (!INGLOBALZONE(curproc
))
84 return (set_errno(EPERM
));
85 STRUCT_INIT(ea
, get_udatamodel());
86 if (copyin(arg
, STRUCT_BUF(ea
), STRUCT_SIZE(ea
)))
87 return (set_errno(EFAULT
));
89 return (exportfs(STRUCT_BUF(ea
), get_udatamodel(), CRED()));
93 nfssys(enum nfssys_op opcode
, void *arg
)
97 if (!(opcode
== NFS_REVAUTH
|| opcode
== NFS4_SVC
) &&
98 secpolicy_nfs(CRED()) != 0)
99 return (set_errno(EPERM
));
102 case NFS4_CLR_STATE
: { /* Clear NFS4 client state */
103 struct nfs4clrst_args clr
;
104 STRUCT_DECL(nfs4clrst_args
, u_clr
);
107 * If the server is not loaded then no point in
108 * clearing nothing :-)
110 if (rfs4_client_clrst
== NULL
) {
114 if (!INGLOBALZONE(curproc
))
115 return (set_errno(EPERM
));
117 STRUCT_INIT(u_clr
, get_udatamodel());
119 if (copyin(arg
, STRUCT_BUF(u_clr
), STRUCT_SIZE(u_clr
)))
120 return (set_errno(EFAULT
));
122 clr
.vers
= STRUCT_FGET(u_clr
, vers
);
124 if (clr
.vers
!= NFS4_CLRST_VERSION
)
125 return (set_errno(EINVAL
));
127 clr
.addr_type
= STRUCT_FGET(u_clr
, addr_type
);
128 clr
.ap
= STRUCT_FGETP(u_clr
, ap
);
129 rfs4_client_clrst(&clr
);
133 case SVCPOOL_CREATE
: { /* setup an RPC server thread pool */
134 struct svcpool_args p
;
136 if (copyin(arg
, &p
, sizeof (p
)))
137 return (set_errno(EFAULT
));
139 error
= svc_pool_create(&p
);
143 case SVCPOOL_WAIT
: { /* wait in kernel for threads to be needed */
146 if (copyin(arg
, &id
, sizeof (id
)))
147 return (set_errno(EFAULT
));
149 error
= svc_wait(id
);
153 case SVCPOOL_RUN
: { /* give work to a runnable thread */
156 if (copyin(arg
, &id
, sizeof (id
)))
157 return (set_errno(EFAULT
));
159 error
= svc_do_run(id
);
163 case RDMA_SVC_INIT
: {
164 struct rdma_svc_args rsa
;
165 char netstore
[20] = "tcp";
167 if (!INGLOBALZONE(curproc
))
168 return (set_errno(EPERM
));
169 if (get_udatamodel() != DATAMODEL_NATIVE
) {
170 STRUCT_DECL(rdma_svc_args
, ursa
);
172 STRUCT_INIT(ursa
, get_udatamodel());
173 if (copyin(arg
, STRUCT_BUF(ursa
), STRUCT_SIZE(ursa
)))
174 return (set_errno(EFAULT
));
176 rsa
.poolid
= STRUCT_FGET(ursa
, poolid
);
177 rsa
.nfs_versmin
= STRUCT_FGET(ursa
, nfs_versmin
);
178 rsa
.nfs_versmax
= STRUCT_FGET(ursa
, nfs_versmax
);
179 rsa
.delegation
= STRUCT_FGET(ursa
, delegation
);
181 if (copyin(arg
, &rsa
, sizeof (rsa
)))
182 return (set_errno(EFAULT
));
184 rsa
.netid
= netstore
;
186 error
= rdma_start(&rsa
);
190 case NFS_SVC
: { /* NFS server daemon */
191 STRUCT_DECL(nfs_svc_args
, nsa
);
193 if (!INGLOBALZONE(curproc
))
194 return (set_errno(EPERM
));
195 STRUCT_INIT(nsa
, get_udatamodel());
197 if (copyin(arg
, STRUCT_BUF(nsa
), STRUCT_SIZE(nsa
)))
198 return (set_errno(EFAULT
));
200 error
= nfs_svc(STRUCT_BUF(nsa
), get_udatamodel());
204 case EXPORTFS
: { /* export a file system */
205 error
= nfs_export(arg
);
209 case NFS_GETFH
: { /* get a file handle */
210 STRUCT_DECL(nfs_getfh_args
, nga
);
212 if (!INGLOBALZONE(curproc
))
213 return (set_errno(EPERM
));
214 STRUCT_INIT(nga
, get_udatamodel());
215 if (copyin(arg
, STRUCT_BUF(nga
), STRUCT_SIZE(nga
)))
216 return (set_errno(EFAULT
));
218 error
= nfs_getfh(STRUCT_BUF(nga
), get_udatamodel(), CRED());
222 case NFS_REVAUTH
: { /* revoke the cached credentials for the uid */
223 STRUCT_DECL(nfs_revauth_args
, nra
);
225 STRUCT_INIT(nra
, get_udatamodel());
226 if (copyin(arg
, STRUCT_BUF(nra
), STRUCT_SIZE(nra
)))
227 return (set_errno(EFAULT
));
229 /* This call performs its own privilege checking */
230 error
= sec_clnt_revoke(STRUCT_FGET(nra
, authtype
),
231 STRUCT_FGET(nra
, uid
), CRED(), NULL
, get_udatamodel());
235 case LM_SVC
: { /* LM server daemon */
236 struct lm_svc_args lsa
;
238 if (get_udatamodel() != DATAMODEL_NATIVE
) {
239 STRUCT_DECL(lm_svc_args
, ulsa
);
241 STRUCT_INIT(ulsa
, get_udatamodel());
242 if (copyin(arg
, STRUCT_BUF(ulsa
), STRUCT_SIZE(ulsa
)))
243 return (set_errno(EFAULT
));
245 lsa
.version
= STRUCT_FGET(ulsa
, version
);
246 lsa
.fd
= STRUCT_FGET(ulsa
, fd
);
247 lsa
.n_fmly
= STRUCT_FGET(ulsa
, n_fmly
);
248 lsa
.n_proto
= STRUCT_FGET(ulsa
, n_proto
);
249 lsa
.n_rdev
= expldev(STRUCT_FGET(ulsa
, n_rdev
));
250 lsa
.debug
= STRUCT_FGET(ulsa
, debug
);
251 lsa
.timout
= STRUCT_FGET(ulsa
, timout
);
252 lsa
.grace
= STRUCT_FGET(ulsa
, grace
);
253 lsa
.retransmittimeout
= STRUCT_FGET(ulsa
,
256 if (copyin(arg
, &lsa
, sizeof (lsa
)))
257 return (set_errno(EFAULT
));
260 error
= lm_svc(&lsa
);
265 error
= lm_shutdown();
269 case LOG_FLUSH
: { /* Flush log buffer and possibly rename */
270 STRUCT_DECL(nfsl_flush_args
, nfa
);
272 STRUCT_INIT(nfa
, get_udatamodel());
273 if (copyin(arg
, STRUCT_BUF(nfa
), STRUCT_SIZE(nfa
)))
274 return (set_errno(EFAULT
));
276 error
= nfsl_flush(STRUCT_BUF(nfa
), get_udatamodel());
280 case NFS4_SVC
: { /* NFS client callback daemon */
282 STRUCT_DECL(nfs4_svc_args
, nsa
);
284 STRUCT_INIT(nsa
, get_udatamodel());
286 if (copyin(arg
, STRUCT_BUF(nsa
), STRUCT_SIZE(nsa
)))
287 return (set_errno(EFAULT
));
289 error
= nfs4_svc(STRUCT_BUF(nsa
), get_udatamodel());
293 /* Request that NFSv4 server quiesce on next shutdown */
294 case NFS4_SVC_REQUEST_QUIESCE
: {
297 /* check that nfssrv module is loaded */
298 if (nfs_srv_quiesce_func
== NULL
)
299 return (set_errno(ENOTSUP
));
301 if (copyin(arg
, &id
, sizeof (id
)))
302 return (set_errno(EFAULT
));
304 error
= svc_pool_control(id
, SVCPSET_SHUTDOWN_PROC
,
305 (void *)nfs_srv_quiesce_func
);
310 struct nfsidmap_args idm
;
312 if (copyin(arg
, &idm
, sizeof (idm
)))
313 return (set_errno(EFAULT
));
315 nfs_idmap_args(&idm
);
320 case NFS4_DSS_SETPATHS_SIZE
: {
321 /* crosses ILP32/LP64 boundary */
322 uint32_t nfs4_dss_bufsize
= 0;
324 if (copyin(arg
, &nfs4_dss_bufsize
, sizeof (nfs4_dss_bufsize
)))
325 return (set_errno(EFAULT
));
326 nfs4_dss_buflen
= (long)nfs4_dss_bufsize
;
331 case NFS4_DSS_SETPATHS
: {
334 /* check that nfssrv module is loaded */
335 if (nfs_srv_dss_func
== NULL
)
336 return (set_errno(ENOTSUP
));
339 * NFS4_DSS_SETPATHS_SIZE must be called before
340 * NFS4_DSS_SETPATHS, to tell us how big a buffer we need
343 if (nfs4_dss_buflen
== 0)
344 return (set_errno(EINVAL
));
345 nfs4_dss_bufp
= kmem_alloc(nfs4_dss_buflen
, KM_SLEEP
);
346 if (nfs4_dss_bufp
== NULL
)
347 return (set_errno(ENOMEM
));
349 if (copyin(arg
, nfs4_dss_bufp
, nfs4_dss_buflen
)) {
350 kmem_free(nfs4_dss_bufp
, nfs4_dss_buflen
);
351 return (set_errno(EFAULT
));
354 /* unpack the buffer and extract the pathnames */
355 error
= nfs_srv_dss_func(nfs4_dss_bufp
, nfs4_dss_buflen
);
356 kmem_free(nfs4_dss_bufp
, nfs4_dss_buflen
);
361 case NFS4_EPHEMERAL_MOUNT_TO
: {
365 * Not a very complicated call.
367 if (copyin(arg
, &mount_to
, sizeof (mount_to
)))
368 return (set_errno(EFAULT
));
369 nfs4_ephemeral_set_mount_to(mount_to
);
378 * For now, only passing down the door fd; if we
379 * ever need to pass down more info, we can use
380 * a (properly aligned) struct.
382 if (copyin(arg
, &did
, sizeof (did
)))
383 return (set_errno(EFAULT
));
393 * For now, only passing down the door fd; if we
394 * ever need to pass down more info, we can use
395 * a (properly aligned) struct.
397 if (copyin(arg
, &did
, sizeof (did
)))
398 return (set_errno(EFAULT
));
409 return ((error
!= 0) ? set_errno(error
) : 0);