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