45NFSDLOCKMUTEX; 46 47/* 48 * Mapping of old NFS Version 2 RPC numbers to generic numbers. 49 */ 50static int newnfs_nfsv3_procid[NFS_V3NPROCS] = { 51 NFSPROC_NULL, 52 NFSPROC_GETATTR, 53 NFSPROC_SETATTR, 54 NFSPROC_NOOP, 55 NFSPROC_LOOKUP, 56 NFSPROC_READLINK, 57 NFSPROC_READ, 58 NFSPROC_NOOP, 59 NFSPROC_WRITE, 60 NFSPROC_CREATE, 61 NFSPROC_REMOVE, 62 NFSPROC_RENAME, 63 NFSPROC_LINK, 64 NFSPROC_SYMLINK, 65 NFSPROC_MKDIR, 66 NFSPROC_RMDIR, 67 NFSPROC_READDIR, 68 NFSPROC_FSSTAT, 69 NFSPROC_NOOP, 70 NFSPROC_NOOP, 71 NFSPROC_NOOP, 72 NFSPROC_NOOP, 73}; 74 75 76SYSCTL_DECL(_vfs_newnfs); 77 78SVCPOOL *nfsrvd_pool; 79 80static int nfs_privport = 0; 81SYSCTL_INT(_vfs_newnfs, OID_AUTO, nfs_privport, CTLFLAG_RW, 82 &nfs_privport, 0, 83 "Only allow clients using a privileged port for NFSv2 and 3"); 84 85static int nfs_minvers = NFS_VER2; 86SYSCTL_INT(_vfs_newnfs, OID_AUTO, server_min_nfsvers, CTLFLAG_RW, 87 &nfs_minvers, 0, "The lowest version of NFS handled by the server"); 88 89static int nfs_maxvers = NFS_VER4; 90SYSCTL_INT(_vfs_newnfs, OID_AUTO, server_max_nfsvers, CTLFLAG_RW, 91 &nfs_maxvers, 0, "The highest version of NFS handled by the server"); 92 93static int nfs_proc(struct nfsrv_descript *, u_int32_t, struct socket *, 94 u_int64_t, struct nfsrvcache **); 95 96extern u_long sb_max_adj; 97extern int newnfs_numnfsd; 98 99/* 100 * NFS server system calls 101 */ 102 103static void 104nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt) 105{ 106 struct nfsrv_descript nd; 107 struct nfsrvcache *rp = NULL; 108 int cacherep, credflavor; 109 110 memset(&nd, 0, sizeof(nd)); 111 if (rqst->rq_vers == NFS_VER2) { 112 if (rqst->rq_proc > NFSV2PROC_STATFS) { 113 svcerr_noproc(rqst); 114 svc_freereq(rqst); 115 return; 116 } 117 nd.nd_procnum = newnfs_nfsv3_procid[rqst->rq_proc]; 118 nd.nd_flag = ND_NFSV2; 119 } else if (rqst->rq_vers == NFS_VER3) { 120 if (rqst->rq_proc >= NFS_V3NPROCS) { 121 svcerr_noproc(rqst); 122 svc_freereq(rqst); 123 return; 124 } 125 nd.nd_procnum = rqst->rq_proc; 126 nd.nd_flag = ND_NFSV3; 127 } else { 128 if (rqst->rq_proc != NFSPROC_NULL && 129 rqst->rq_proc != NFSV4PROC_COMPOUND) { 130 svcerr_noproc(rqst); 131 svc_freereq(rqst); 132 return; 133 } 134 nd.nd_procnum = rqst->rq_proc; 135 nd.nd_flag = ND_NFSV4; 136 } 137 138 /* 139 * Note: we want rq_addr, not svc_getrpccaller for nd_nam2 - 140 * NFS_SRVMAXDATA uses a NULL value for nd_nam2 to detect TCP 141 * mounts. 142 */ 143 nd.nd_mrep = rqst->rq_args; 144 rqst->rq_args = NULL; 145 newnfs_realign(&nd.nd_mrep); 146 nd.nd_md = nd.nd_mrep; 147 nd.nd_dpos = mtod(nd.nd_md, caddr_t); 148 nd.nd_nam = svc_getrpccaller(rqst); 149 nd.nd_nam2 = rqst->rq_addr; 150 nd.nd_mreq = NULL; 151 nd.nd_cred = NULL; 152 153 if (nfs_privport && (nd.nd_flag & ND_NFSV4) == 0) { 154 /* Check if source port is privileged */ 155 u_short port; 156 struct sockaddr *nam = nd.nd_nam; 157 struct sockaddr_in *sin; 158 159 sin = (struct sockaddr_in *)nam; 160 /* 161 * INET/INET6 - same code: 162 * sin_port and sin6_port are at same offset 163 */ 164 port = ntohs(sin->sin_port); 165 if (port >= IPPORT_RESERVED && 166 nd.nd_procnum != NFSPROC_NULL) { 167#ifdef INET6 168 char b6[INET6_ADDRSTRLEN]; 169#if defined(KLD_MODULE) 170 /* Do not use ip6_sprintf: the nfs module should work without INET6. */ 171#define ip6_sprintf(buf, a) \ 172 (sprintf((buf), "%x:%x:%x:%x:%x:%x:%x:%x", \ 173 (a)->s6_addr16[0], (a)->s6_addr16[1], \ 174 (a)->s6_addr16[2], (a)->s6_addr16[3], \ 175 (a)->s6_addr16[4], (a)->s6_addr16[5], \ 176 (a)->s6_addr16[6], (a)->s6_addr16[7]), \ 177 (buf)) 178#endif 179#endif 180 printf("NFS request from unprivileged port (%s:%d)\n", 181#ifdef INET6 182 sin->sin_family == AF_INET6 ? 183 ip6_sprintf(b6, &satosin6(sin)->sin6_addr) : 184#if defined(KLD_MODULE) 185#undef ip6_sprintf 186#endif 187#endif 188 inet_ntoa(sin->sin_addr), port); 189 svcerr_weakauth(rqst); 190 svc_freereq(rqst); 191 m_freem(nd.nd_mrep); 192 return; 193 } 194 } 195 196 if (nd.nd_procnum != NFSPROC_NULL) { 197 if (!svc_getcred(rqst, &nd.nd_cred, &credflavor)) { 198 svcerr_weakauth(rqst); 199 svc_freereq(rqst); 200 m_freem(nd.nd_mrep); 201 return; 202 } 203 204 /* Set the flag based on credflavor */ 205 if (credflavor == RPCSEC_GSS_KRB5) { 206 nd.nd_flag |= ND_GSS; 207 } else if (credflavor == RPCSEC_GSS_KRB5I) { 208 nd.nd_flag |= (ND_GSS | ND_GSSINTEGRITY); 209 } else if (credflavor == RPCSEC_GSS_KRB5P) { 210 nd.nd_flag |= (ND_GSS | ND_GSSPRIVACY); 211 } else if (credflavor != AUTH_SYS) { 212 svcerr_weakauth(rqst); 213 svc_freereq(rqst); 214 m_freem(nd.nd_mrep); 215 return; 216 } 217 218#ifdef MAC 219 mac_cred_associate_nfsd(nd.nd_cred); 220#endif 221 if ((nd.nd_flag & ND_NFSV4) != 0) { 222 nd.nd_repstat = nfsvno_v4rootexport(&nd); 223 if (nd.nd_repstat != 0) { 224 svcerr_weakauth(rqst); 225 svc_freereq(rqst); 226 m_freem(nd.nd_mrep); 227 return; 228 } 229 } 230 231 cacherep = nfs_proc(&nd, rqst->rq_xid, xprt->xp_socket, 232 xprt->xp_sockref, &rp); 233 } else { 234 NFSMGET(nd.nd_mreq); 235 nd.nd_mreq->m_len = 0; 236 cacherep = RC_REPLY; 237 } 238 if (nd.nd_mrep != NULL) 239 m_freem(nd.nd_mrep); 240 241 if (nd.nd_cred != NULL) 242 crfree(nd.nd_cred); 243 244 if (cacherep == RC_DROPIT) { 245 if (nd.nd_mreq != NULL) 246 m_freem(nd.nd_mreq); 247 svc_freereq(rqst); 248 return; 249 } 250 251 if (nd.nd_mreq == NULL) { 252 svcerr_decode(rqst); 253 svc_freereq(rqst); 254 return; 255 } 256 257 if (nd.nd_repstat & NFSERR_AUTHERR) { 258 svcerr_auth(rqst, nd.nd_repstat & ~NFSERR_AUTHERR); 259 if (nd.nd_mreq != NULL) 260 m_freem(nd.nd_mreq); 261 } else if (!svc_sendreply_mbuf(rqst, nd.nd_mreq)) { 262 svcerr_systemerr(rqst); 263 } 264 if (rp != NULL) 265 nfsrvd_sentcache(rp, xprt->xp_socket, 0); 266 svc_freereq(rqst); 267} 268 269/* 270 * Check the cache and, optionally, do the RPC. 271 * Return the appropriate cache response. 272 */ 273static int 274nfs_proc(struct nfsrv_descript *nd, u_int32_t xid, struct socket *so, 275 u_int64_t sockref, struct nfsrvcache **rpp) 276{ 277 struct thread *td = curthread; 278 int cacherep = RC_DOIT, isdgram; 279 280 *rpp = NULL; 281 if (nd->nd_nam2 == NULL) { 282 nd->nd_flag |= ND_STREAMSOCK; 283 isdgram = 0; 284 } else { 285 isdgram = 1; 286 } 287 NFSGETTIME(&nd->nd_starttime); 288 289 /* 290 * Two cases: 291 * 1 - For NFSv2 over UDP, if we are near our malloc/mget 292 * limit, just drop the request. There is no 293 * NFSERR_RESOURCE or NFSERR_DELAY for NFSv2 and the 294 * client will timeout/retry over UDP in a little while. 295 * 2 - nd_repstat == 0 && nd_mreq == NULL, which 296 * means a normal nfs rpc, so check the cache 297 */ 298 if ((nd->nd_flag & ND_NFSV2) && nd->nd_nam2 != NULL && 299 nfsrv_mallocmget_limit()) { 300 cacherep = RC_DROPIT; 301 } else { 302 /* 303 * For NFSv3, play it safe and assume that the client is 304 * doing retries on the same TCP connection. 305 */ 306 if ((nd->nd_flag & (ND_NFSV4 | ND_STREAMSOCK)) == 307 ND_STREAMSOCK) 308 nd->nd_flag |= ND_SAMETCPCONN; 309 nd->nd_retxid = xid; 310 nd->nd_tcpconntime = NFSD_MONOSEC; 311 nd->nd_sockref = sockref; 312 cacherep = nfsrvd_getcache(nd, so); 313 } 314 315 /* 316 * Handle the request. There are three cases. 317 * RC_DOIT - do the RPC 318 * RC_REPLY - return the reply already created 319 * RC_DROPIT - just throw the request away 320 */ 321 if (cacherep == RC_DOIT) { 322 nfsrvd_dorpc(nd, isdgram, td); 323 if (nd->nd_repstat == NFSERR_DONTREPLY) 324 cacherep = RC_DROPIT; 325 else 326 cacherep = RC_REPLY; 327 *rpp = nfsrvd_updatecache(nd, so); 328 } 329 return (cacherep); 330} 331 332/* 333 * Adds a socket to the list for servicing by nfsds. 334 */ 335int 336nfsrvd_addsock(struct file *fp) 337{ 338 int siz; 339 struct socket *so; 340 int error; 341 SVCXPRT *xprt; 342 static u_int64_t sockref = 0; 343 344 so = fp->f_data; 345 346 siz = sb_max_adj; 347 error = soreserve(so, siz, siz); 348 if (error) { 349 return (error); 350 } 351 352 /* 353 * Steal the socket from userland so that it doesn't close 354 * unexpectedly. 355 */ 356 if (so->so_type == SOCK_DGRAM) 357 xprt = svc_dg_create(nfsrvd_pool, so, 0, 0); 358 else 359 xprt = svc_vc_create(nfsrvd_pool, so, 0, 0); 360 if (xprt) { 361 fp->f_ops = &badfileops; 362 fp->f_data = NULL; 363 xprt->xp_sockref = ++sockref; 364 if (nfs_minvers == NFS_VER2) 365 svc_reg(xprt, NFS_PROG, NFS_VER2, nfssvc_program, 366 NULL); 367 if (nfs_minvers <= NFS_VER3 && nfs_maxvers >= NFS_VER3) 368 svc_reg(xprt, NFS_PROG, NFS_VER3, nfssvc_program, 369 NULL); 370 if (nfs_maxvers >= NFS_VER4) 371 svc_reg(xprt, NFS_PROG, NFS_VER4, nfssvc_program, 372 NULL); 373 } 374 375 return (0); 376} 377 378/* 379 * Called by nfssvc() for nfsds. Just loops around servicing rpc requests 380 * until it is killed by a signal. 381 */ 382int 383nfsrvd_nfsd(struct thread *td, struct nfsd_nfsd_args *args) 384{ 385#ifdef KGSSAPI 386 char principal[MAXHOSTNAMELEN + 5]; 387 int error; 388 bool_t ret2, ret3, ret4; 389#endif 390 391#ifdef KGSSAPI 392 error = copyinstr(args->principal, principal, sizeof (principal), 393 NULL); 394 if (error) 395 return (error); 396#endif 397 398 /* 399 * Only the first nfsd actually does any work. The RPC code 400 * adds threads to it as needed. Any extra processes offered 401 * by nfsd just exit. If nfsd is new enough, it will call us 402 * once with a structure that specifies how many threads to 403 * use. 404 */ 405 NFSD_LOCK(); 406 if (newnfs_numnfsd == 0) { 407 newnfs_numnfsd++; 408 409 NFSD_UNLOCK(); 410 411#ifdef KGSSAPI 412 /* An empty string implies AUTH_SYS only. */ 413 if (principal[0] != '\0') { 414 ret2 = rpc_gss_set_svc_name(principal, "kerberosv5", 415 GSS_C_INDEFINITE, NFS_PROG, NFS_VER2); 416 ret3 = rpc_gss_set_svc_name(principal, "kerberosv5", 417 GSS_C_INDEFINITE, NFS_PROG, NFS_VER3); 418 ret4 = rpc_gss_set_svc_name(principal, "kerberosv5", 419 GSS_C_INDEFINITE, NFS_PROG, NFS_VER4); 420 421 if (!ret2 || !ret3 || !ret4) { 422 NFSD_LOCK(); 423 newnfs_numnfsd--; 424 nfsrvd_init(1); 425 NFSD_UNLOCK(); 426 return (EAUTH); 427 } 428 } 429#endif 430 431 nfsrvd_pool->sp_minthreads = args->minthreads; 432 nfsrvd_pool->sp_maxthreads = args->maxthreads; 433 434 svc_run(nfsrvd_pool); 435 436#ifdef KGSSAPI 437 if (principal[0] != '\0') { 438 rpc_gss_clear_svc_name(NFS_PROG, NFS_VER2); 439 rpc_gss_clear_svc_name(NFS_PROG, NFS_VER3); 440 rpc_gss_clear_svc_name(NFS_PROG, NFS_VER4); 441 } 442#endif 443 444 NFSD_LOCK(); 445 newnfs_numnfsd--; 446 nfsrvd_init(1); 447 } 448 NFSD_UNLOCK(); 449 450 return (0); 451} 452 453/* 454 * Initialize the data structures for the server. 455 * Handshake with any new nfsds starting up to avoid any chance of 456 * corruption. 457 */ 458void 459nfsrvd_init(int terminating) 460{ 461 462 NFSD_LOCK_ASSERT(); 463 464 if (terminating) { 465 NFSD_UNLOCK(); 466 svcpool_destroy(nfsrvd_pool); 467 nfsrvd_pool = NULL; 468 NFSD_LOCK(); 469 } 470 471 NFSD_UNLOCK(); 472 473 nfsrvd_pool = svcpool_create("nfsd", SYSCTL_STATIC_CHILDREN(_vfs_newnfs)); 474 nfsrvd_pool->sp_rcache = NULL; 475 nfsrvd_pool->sp_assign = NULL; 476 nfsrvd_pool->sp_done = NULL; 477 478 NFSD_LOCK(); 479} 480
| 47NFSDLOCKMUTEX; 48 49/* 50 * Mapping of old NFS Version 2 RPC numbers to generic numbers. 51 */ 52static int newnfs_nfsv3_procid[NFS_V3NPROCS] = { 53 NFSPROC_NULL, 54 NFSPROC_GETATTR, 55 NFSPROC_SETATTR, 56 NFSPROC_NOOP, 57 NFSPROC_LOOKUP, 58 NFSPROC_READLINK, 59 NFSPROC_READ, 60 NFSPROC_NOOP, 61 NFSPROC_WRITE, 62 NFSPROC_CREATE, 63 NFSPROC_REMOVE, 64 NFSPROC_RENAME, 65 NFSPROC_LINK, 66 NFSPROC_SYMLINK, 67 NFSPROC_MKDIR, 68 NFSPROC_RMDIR, 69 NFSPROC_READDIR, 70 NFSPROC_FSSTAT, 71 NFSPROC_NOOP, 72 NFSPROC_NOOP, 73 NFSPROC_NOOP, 74 NFSPROC_NOOP, 75}; 76 77 78SYSCTL_DECL(_vfs_newnfs); 79 80SVCPOOL *nfsrvd_pool; 81 82static int nfs_privport = 0; 83SYSCTL_INT(_vfs_newnfs, OID_AUTO, nfs_privport, CTLFLAG_RW, 84 &nfs_privport, 0, 85 "Only allow clients using a privileged port for NFSv2 and 3"); 86 87static int nfs_minvers = NFS_VER2; 88SYSCTL_INT(_vfs_newnfs, OID_AUTO, server_min_nfsvers, CTLFLAG_RW, 89 &nfs_minvers, 0, "The lowest version of NFS handled by the server"); 90 91static int nfs_maxvers = NFS_VER4; 92SYSCTL_INT(_vfs_newnfs, OID_AUTO, server_max_nfsvers, CTLFLAG_RW, 93 &nfs_maxvers, 0, "The highest version of NFS handled by the server"); 94 95static int nfs_proc(struct nfsrv_descript *, u_int32_t, struct socket *, 96 u_int64_t, struct nfsrvcache **); 97 98extern u_long sb_max_adj; 99extern int newnfs_numnfsd; 100 101/* 102 * NFS server system calls 103 */ 104 105static void 106nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt) 107{ 108 struct nfsrv_descript nd; 109 struct nfsrvcache *rp = NULL; 110 int cacherep, credflavor; 111 112 memset(&nd, 0, sizeof(nd)); 113 if (rqst->rq_vers == NFS_VER2) { 114 if (rqst->rq_proc > NFSV2PROC_STATFS) { 115 svcerr_noproc(rqst); 116 svc_freereq(rqst); 117 return; 118 } 119 nd.nd_procnum = newnfs_nfsv3_procid[rqst->rq_proc]; 120 nd.nd_flag = ND_NFSV2; 121 } else if (rqst->rq_vers == NFS_VER3) { 122 if (rqst->rq_proc >= NFS_V3NPROCS) { 123 svcerr_noproc(rqst); 124 svc_freereq(rqst); 125 return; 126 } 127 nd.nd_procnum = rqst->rq_proc; 128 nd.nd_flag = ND_NFSV3; 129 } else { 130 if (rqst->rq_proc != NFSPROC_NULL && 131 rqst->rq_proc != NFSV4PROC_COMPOUND) { 132 svcerr_noproc(rqst); 133 svc_freereq(rqst); 134 return; 135 } 136 nd.nd_procnum = rqst->rq_proc; 137 nd.nd_flag = ND_NFSV4; 138 } 139 140 /* 141 * Note: we want rq_addr, not svc_getrpccaller for nd_nam2 - 142 * NFS_SRVMAXDATA uses a NULL value for nd_nam2 to detect TCP 143 * mounts. 144 */ 145 nd.nd_mrep = rqst->rq_args; 146 rqst->rq_args = NULL; 147 newnfs_realign(&nd.nd_mrep); 148 nd.nd_md = nd.nd_mrep; 149 nd.nd_dpos = mtod(nd.nd_md, caddr_t); 150 nd.nd_nam = svc_getrpccaller(rqst); 151 nd.nd_nam2 = rqst->rq_addr; 152 nd.nd_mreq = NULL; 153 nd.nd_cred = NULL; 154 155 if (nfs_privport && (nd.nd_flag & ND_NFSV4) == 0) { 156 /* Check if source port is privileged */ 157 u_short port; 158 struct sockaddr *nam = nd.nd_nam; 159 struct sockaddr_in *sin; 160 161 sin = (struct sockaddr_in *)nam; 162 /* 163 * INET/INET6 - same code: 164 * sin_port and sin6_port are at same offset 165 */ 166 port = ntohs(sin->sin_port); 167 if (port >= IPPORT_RESERVED && 168 nd.nd_procnum != NFSPROC_NULL) { 169#ifdef INET6 170 char b6[INET6_ADDRSTRLEN]; 171#if defined(KLD_MODULE) 172 /* Do not use ip6_sprintf: the nfs module should work without INET6. */ 173#define ip6_sprintf(buf, a) \ 174 (sprintf((buf), "%x:%x:%x:%x:%x:%x:%x:%x", \ 175 (a)->s6_addr16[0], (a)->s6_addr16[1], \ 176 (a)->s6_addr16[2], (a)->s6_addr16[3], \ 177 (a)->s6_addr16[4], (a)->s6_addr16[5], \ 178 (a)->s6_addr16[6], (a)->s6_addr16[7]), \ 179 (buf)) 180#endif 181#endif 182 printf("NFS request from unprivileged port (%s:%d)\n", 183#ifdef INET6 184 sin->sin_family == AF_INET6 ? 185 ip6_sprintf(b6, &satosin6(sin)->sin6_addr) : 186#if defined(KLD_MODULE) 187#undef ip6_sprintf 188#endif 189#endif 190 inet_ntoa(sin->sin_addr), port); 191 svcerr_weakauth(rqst); 192 svc_freereq(rqst); 193 m_freem(nd.nd_mrep); 194 return; 195 } 196 } 197 198 if (nd.nd_procnum != NFSPROC_NULL) { 199 if (!svc_getcred(rqst, &nd.nd_cred, &credflavor)) { 200 svcerr_weakauth(rqst); 201 svc_freereq(rqst); 202 m_freem(nd.nd_mrep); 203 return; 204 } 205 206 /* Set the flag based on credflavor */ 207 if (credflavor == RPCSEC_GSS_KRB5) { 208 nd.nd_flag |= ND_GSS; 209 } else if (credflavor == RPCSEC_GSS_KRB5I) { 210 nd.nd_flag |= (ND_GSS | ND_GSSINTEGRITY); 211 } else if (credflavor == RPCSEC_GSS_KRB5P) { 212 nd.nd_flag |= (ND_GSS | ND_GSSPRIVACY); 213 } else if (credflavor != AUTH_SYS) { 214 svcerr_weakauth(rqst); 215 svc_freereq(rqst); 216 m_freem(nd.nd_mrep); 217 return; 218 } 219 220#ifdef MAC 221 mac_cred_associate_nfsd(nd.nd_cred); 222#endif 223 if ((nd.nd_flag & ND_NFSV4) != 0) { 224 nd.nd_repstat = nfsvno_v4rootexport(&nd); 225 if (nd.nd_repstat != 0) { 226 svcerr_weakauth(rqst); 227 svc_freereq(rqst); 228 m_freem(nd.nd_mrep); 229 return; 230 } 231 } 232 233 cacherep = nfs_proc(&nd, rqst->rq_xid, xprt->xp_socket, 234 xprt->xp_sockref, &rp); 235 } else { 236 NFSMGET(nd.nd_mreq); 237 nd.nd_mreq->m_len = 0; 238 cacherep = RC_REPLY; 239 } 240 if (nd.nd_mrep != NULL) 241 m_freem(nd.nd_mrep); 242 243 if (nd.nd_cred != NULL) 244 crfree(nd.nd_cred); 245 246 if (cacherep == RC_DROPIT) { 247 if (nd.nd_mreq != NULL) 248 m_freem(nd.nd_mreq); 249 svc_freereq(rqst); 250 return; 251 } 252 253 if (nd.nd_mreq == NULL) { 254 svcerr_decode(rqst); 255 svc_freereq(rqst); 256 return; 257 } 258 259 if (nd.nd_repstat & NFSERR_AUTHERR) { 260 svcerr_auth(rqst, nd.nd_repstat & ~NFSERR_AUTHERR); 261 if (nd.nd_mreq != NULL) 262 m_freem(nd.nd_mreq); 263 } else if (!svc_sendreply_mbuf(rqst, nd.nd_mreq)) { 264 svcerr_systemerr(rqst); 265 } 266 if (rp != NULL) 267 nfsrvd_sentcache(rp, xprt->xp_socket, 0); 268 svc_freereq(rqst); 269} 270 271/* 272 * Check the cache and, optionally, do the RPC. 273 * Return the appropriate cache response. 274 */ 275static int 276nfs_proc(struct nfsrv_descript *nd, u_int32_t xid, struct socket *so, 277 u_int64_t sockref, struct nfsrvcache **rpp) 278{ 279 struct thread *td = curthread; 280 int cacherep = RC_DOIT, isdgram; 281 282 *rpp = NULL; 283 if (nd->nd_nam2 == NULL) { 284 nd->nd_flag |= ND_STREAMSOCK; 285 isdgram = 0; 286 } else { 287 isdgram = 1; 288 } 289 NFSGETTIME(&nd->nd_starttime); 290 291 /* 292 * Two cases: 293 * 1 - For NFSv2 over UDP, if we are near our malloc/mget 294 * limit, just drop the request. There is no 295 * NFSERR_RESOURCE or NFSERR_DELAY for NFSv2 and the 296 * client will timeout/retry over UDP in a little while. 297 * 2 - nd_repstat == 0 && nd_mreq == NULL, which 298 * means a normal nfs rpc, so check the cache 299 */ 300 if ((nd->nd_flag & ND_NFSV2) && nd->nd_nam2 != NULL && 301 nfsrv_mallocmget_limit()) { 302 cacherep = RC_DROPIT; 303 } else { 304 /* 305 * For NFSv3, play it safe and assume that the client is 306 * doing retries on the same TCP connection. 307 */ 308 if ((nd->nd_flag & (ND_NFSV4 | ND_STREAMSOCK)) == 309 ND_STREAMSOCK) 310 nd->nd_flag |= ND_SAMETCPCONN; 311 nd->nd_retxid = xid; 312 nd->nd_tcpconntime = NFSD_MONOSEC; 313 nd->nd_sockref = sockref; 314 cacherep = nfsrvd_getcache(nd, so); 315 } 316 317 /* 318 * Handle the request. There are three cases. 319 * RC_DOIT - do the RPC 320 * RC_REPLY - return the reply already created 321 * RC_DROPIT - just throw the request away 322 */ 323 if (cacherep == RC_DOIT) { 324 nfsrvd_dorpc(nd, isdgram, td); 325 if (nd->nd_repstat == NFSERR_DONTREPLY) 326 cacherep = RC_DROPIT; 327 else 328 cacherep = RC_REPLY; 329 *rpp = nfsrvd_updatecache(nd, so); 330 } 331 return (cacherep); 332} 333 334/* 335 * Adds a socket to the list for servicing by nfsds. 336 */ 337int 338nfsrvd_addsock(struct file *fp) 339{ 340 int siz; 341 struct socket *so; 342 int error; 343 SVCXPRT *xprt; 344 static u_int64_t sockref = 0; 345 346 so = fp->f_data; 347 348 siz = sb_max_adj; 349 error = soreserve(so, siz, siz); 350 if (error) { 351 return (error); 352 } 353 354 /* 355 * Steal the socket from userland so that it doesn't close 356 * unexpectedly. 357 */ 358 if (so->so_type == SOCK_DGRAM) 359 xprt = svc_dg_create(nfsrvd_pool, so, 0, 0); 360 else 361 xprt = svc_vc_create(nfsrvd_pool, so, 0, 0); 362 if (xprt) { 363 fp->f_ops = &badfileops; 364 fp->f_data = NULL; 365 xprt->xp_sockref = ++sockref; 366 if (nfs_minvers == NFS_VER2) 367 svc_reg(xprt, NFS_PROG, NFS_VER2, nfssvc_program, 368 NULL); 369 if (nfs_minvers <= NFS_VER3 && nfs_maxvers >= NFS_VER3) 370 svc_reg(xprt, NFS_PROG, NFS_VER3, nfssvc_program, 371 NULL); 372 if (nfs_maxvers >= NFS_VER4) 373 svc_reg(xprt, NFS_PROG, NFS_VER4, nfssvc_program, 374 NULL); 375 } 376 377 return (0); 378} 379 380/* 381 * Called by nfssvc() for nfsds. Just loops around servicing rpc requests 382 * until it is killed by a signal. 383 */ 384int 385nfsrvd_nfsd(struct thread *td, struct nfsd_nfsd_args *args) 386{ 387#ifdef KGSSAPI 388 char principal[MAXHOSTNAMELEN + 5]; 389 int error; 390 bool_t ret2, ret3, ret4; 391#endif 392 393#ifdef KGSSAPI 394 error = copyinstr(args->principal, principal, sizeof (principal), 395 NULL); 396 if (error) 397 return (error); 398#endif 399 400 /* 401 * Only the first nfsd actually does any work. The RPC code 402 * adds threads to it as needed. Any extra processes offered 403 * by nfsd just exit. If nfsd is new enough, it will call us 404 * once with a structure that specifies how many threads to 405 * use. 406 */ 407 NFSD_LOCK(); 408 if (newnfs_numnfsd == 0) { 409 newnfs_numnfsd++; 410 411 NFSD_UNLOCK(); 412 413#ifdef KGSSAPI 414 /* An empty string implies AUTH_SYS only. */ 415 if (principal[0] != '\0') { 416 ret2 = rpc_gss_set_svc_name(principal, "kerberosv5", 417 GSS_C_INDEFINITE, NFS_PROG, NFS_VER2); 418 ret3 = rpc_gss_set_svc_name(principal, "kerberosv5", 419 GSS_C_INDEFINITE, NFS_PROG, NFS_VER3); 420 ret4 = rpc_gss_set_svc_name(principal, "kerberosv5", 421 GSS_C_INDEFINITE, NFS_PROG, NFS_VER4); 422 423 if (!ret2 || !ret3 || !ret4) { 424 NFSD_LOCK(); 425 newnfs_numnfsd--; 426 nfsrvd_init(1); 427 NFSD_UNLOCK(); 428 return (EAUTH); 429 } 430 } 431#endif 432 433 nfsrvd_pool->sp_minthreads = args->minthreads; 434 nfsrvd_pool->sp_maxthreads = args->maxthreads; 435 436 svc_run(nfsrvd_pool); 437 438#ifdef KGSSAPI 439 if (principal[0] != '\0') { 440 rpc_gss_clear_svc_name(NFS_PROG, NFS_VER2); 441 rpc_gss_clear_svc_name(NFS_PROG, NFS_VER3); 442 rpc_gss_clear_svc_name(NFS_PROG, NFS_VER4); 443 } 444#endif 445 446 NFSD_LOCK(); 447 newnfs_numnfsd--; 448 nfsrvd_init(1); 449 } 450 NFSD_UNLOCK(); 451 452 return (0); 453} 454 455/* 456 * Initialize the data structures for the server. 457 * Handshake with any new nfsds starting up to avoid any chance of 458 * corruption. 459 */ 460void 461nfsrvd_init(int terminating) 462{ 463 464 NFSD_LOCK_ASSERT(); 465 466 if (terminating) { 467 NFSD_UNLOCK(); 468 svcpool_destroy(nfsrvd_pool); 469 nfsrvd_pool = NULL; 470 NFSD_LOCK(); 471 } 472 473 NFSD_UNLOCK(); 474 475 nfsrvd_pool = svcpool_create("nfsd", SYSCTL_STATIC_CHILDREN(_vfs_newnfs)); 476 nfsrvd_pool->sp_rcache = NULL; 477 nfsrvd_pool->sp_assign = NULL; 478 nfsrvd_pool->sp_done = NULL; 479 480 NFSD_LOCK(); 481} 482
|