1 /* $NetBSD: nfs_syscalls.c,v 1.12 1994/08/17 14:43:56 mycroft Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Rick Macklem at The University of Guelph. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)nfs_syscalls.c 8.3 (Berkeley) 1/4/94 39 */ 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/kernel.h> 44 #include <sys/file.h> 45 #include <sys/stat.h> 46 #include <sys/vnode.h> 47 #include <sys/mount.h> 48 #include <sys/proc.h> 49 #include <sys/uio.h> 50 #include <sys/malloc.h> 51 #include <sys/buf.h> 52 #include <sys/mbuf.h> 53 #include <sys/socket.h> 54 #include <sys/socketvar.h> 55 #include <sys/domain.h> 56 #include <sys/protosw.h> 57 #include <sys/namei.h> 58 #include <sys/syslog.h> 59 60 #include <netinet/in.h> 61 #include <netinet/tcp.h> 62 #ifdef ISO 63 #include <netiso/iso.h> 64 #endif 65 #include <nfs/rpcv2.h> 66 #include <nfs/nfsv2.h> 67 #include <nfs/nfs.h> 68 #include <nfs/nfsrvcache.h> 69 #include <nfs/nfsmount.h> 70 #include <nfs/nfsnode.h> 71 #include <nfs/nqnfs.h> 72 #include <nfs/nfsrtt.h> 73 74 /* Global defs. */ 75 extern u_long nfs_prog, nfs_vers; 76 extern int (*nfsrv_procs[NFS_NPROCS])(); 77 extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON]; 78 extern int nfs_numasync; 79 extern time_t nqnfsstarttime; 80 extern int nqsrv_writeslack; 81 extern int nfsrtton; 82 struct nfssvc_sock *nfs_udpsock, *nfs_cltpsock; 83 int nuidhash_max = NFS_MAXUIDHASH; 84 static int nfs_numnfsd = 0; 85 int nfsd_waiting = 0; 86 static int notstarted = 1; 87 static int modify_flag = 0; 88 static struct nfsdrt nfsdrt; 89 void nfsrv_cleancache(), nfsrv_rcv(), nfsrv_wakenfsd(), nfs_sndunlock(); 90 static void nfsd_rt(); 91 void nfsrv_slpderef(), nfsrv_init(); 92 93 #define TRUE 1 94 #define FALSE 0 95 96 static int nfs_asyncdaemon[NFS_MAXASYNCDAEMON]; 97 /* 98 * NFS server system calls 99 * getfh() lives here too, but maybe should move to kern/vfs_syscalls.c 100 */ 101 102 /* 103 * Get file handle system call 104 */ 105 struct getfh_args { 106 char *fname; 107 fhandle_t *fhp; 108 }; 109 getfh(p, uap, retval) 110 struct proc *p; 111 register struct getfh_args *uap; 112 int *retval; 113 { 114 register struct vnode *vp; 115 fhandle_t fh; 116 int error; 117 struct nameidata nd; 118 119 /* 120 * Must be super user 121 */ 122 if (error = suser(p->p_ucred, &p->p_acflag)) 123 return (error); 124 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 125 if (error = namei(&nd)) 126 return (error); 127 vp = nd.ni_vp; 128 bzero((caddr_t)&fh, sizeof(fh)); 129 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; 130 error = VFS_VPTOFH(vp, &fh.fh_fid); 131 vput(vp); 132 if (error) 133 return (error); 134 error = copyout((caddr_t)&fh, (caddr_t)uap->fhp, sizeof (fh)); 135 return (error); 136 } 137 138 /* 139 * Nfs server psuedo system call for the nfsd's 140 * Based on the flag value it either: 141 * - adds a socket to the selection list 142 * - remains in the kernel as an nfsd 143 * - remains in the kernel as an nfsiod 144 */ 145 struct nfssvc_args { 146 int flag; 147 caddr_t argp; 148 }; 149 nfssvc(p, uap, retval) 150 struct proc *p; 151 register struct nfssvc_args *uap; 152 int *retval; 153 { 154 struct nameidata nd; 155 struct file *fp; 156 struct mbuf *nam; 157 struct nfsd_args nfsdarg; 158 struct nfsd_srvargs nfsd_srvargs, *nsd = &nfsd_srvargs; 159 struct nfsd_cargs ncd; 160 struct nfsd *nfsd; 161 struct nfssvc_sock *slp; 162 struct nfsuid *nuidp, **nuh; 163 struct nfsmount *nmp; 164 int error; 165 166 /* 167 * Must be super user 168 */ 169 if (error = suser(p->p_ucred, &p->p_acflag)) 170 return (error); 171 while (nfssvc_sockhead_flag & SLP_INIT) { 172 nfssvc_sockhead_flag |= SLP_WANTINIT; 173 (void) tsleep((caddr_t)&nfssvc_sockhead, PSOCK, "nfsd init", 0); 174 } 175 if (uap->flag & NFSSVC_BIOD) { 176 #ifndef NFSCLIENT 177 error = ENOSYS; 178 #else /* !NFSCLIENT */ 179 error = nfssvc_iod(p); 180 #endif /* !NFSCLIENT */ 181 } else if (uap->flag & NFSSVC_MNTD) { 182 #ifndef NFSCLIENT 183 error = ENOSYS; 184 #else /* !NFSCLIENT */ 185 if (error = copyin(uap->argp, (caddr_t)&ncd, sizeof (ncd))) 186 return (error); 187 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 188 ncd.ncd_dirp, p); 189 if (error = namei(&nd)) 190 return (error); 191 if ((nd.ni_vp->v_flag & VROOT) == 0) 192 error = EINVAL; 193 nmp = VFSTONFS(nd.ni_vp->v_mount); 194 vput(nd.ni_vp); 195 if (error) 196 return (error); 197 if ((nmp->nm_flag & NFSMNT_MNTD) && 198 (uap->flag & NFSSVC_GOTAUTH) == 0) 199 return (0); 200 nmp->nm_flag |= NFSMNT_MNTD; 201 error = nqnfs_clientd(nmp, p->p_ucred, &ncd, uap->flag, 202 uap->argp, p); 203 #endif /* !NFSCLIENT */ 204 } else if (uap->flag & NFSSVC_ADDSOCK) { 205 #ifndef NFSSERVER 206 error = ENOSYS; 207 #else /* !NFSSERVER */ 208 if (error = copyin(uap->argp, (caddr_t)&nfsdarg, 209 sizeof(nfsdarg))) 210 return (error); 211 if (error = getsock(p->p_fd, nfsdarg.sock, &fp)) 212 return (error); 213 /* 214 * Get the client address for connected sockets. 215 */ 216 if (nfsdarg.name == NULL || nfsdarg.namelen == 0) 217 nam = (struct mbuf *)0; 218 else if (error = sockargs(&nam, nfsdarg.name, nfsdarg.namelen, 219 MT_SONAME)) 220 return (error); 221 error = nfssvc_addsock(fp, nam); 222 #endif /* !NFSSERVER */ 223 } else { 224 #ifndef NFSSERVER 225 error = ENOSYS; 226 #else /* !NFSSERVER */ 227 if (error = copyin(uap->argp, (caddr_t)nsd, sizeof (*nsd))) 228 return (error); 229 if ((uap->flag & NFSSVC_AUTHIN) && (nfsd = nsd->nsd_nfsd) && 230 (nfsd->nd_slp->ns_flag & SLP_VALID)) { 231 slp = nfsd->nd_slp; 232 233 /* 234 * First check to see if another nfsd has already 235 * added this credential. 236 */ 237 for (nuidp = NUIDHASH(slp, nsd->nsd_uid)->lh_first; 238 nuidp != 0; nuidp = nuidp->nu_hash.le_next) { 239 if (nuidp->nu_uid == nsd->nsd_uid) 240 break; 241 } 242 if (nuidp == 0) { 243 /* 244 * Nope, so we will. 245 */ 246 if (slp->ns_numuids < nuidhash_max) { 247 slp->ns_numuids++; 248 nuidp = (struct nfsuid *) 249 malloc(sizeof (struct nfsuid), M_NFSUID, 250 M_WAITOK); 251 } else 252 nuidp = (struct nfsuid *)0; 253 if ((slp->ns_flag & SLP_VALID) == 0) { 254 if (nuidp) 255 free((caddr_t)nuidp, M_NFSUID); 256 } else { 257 if (nuidp == (struct nfsuid *)0) { 258 nuidp = slp->ns_uidlruhead.tqh_first; 259 LIST_REMOVE(nuidp, nu_hash); 260 TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp, 261 nu_lru); 262 } 263 nuidp->nu_cr = nsd->nsd_cr; 264 if (nuidp->nu_cr.cr_ngroups > NGROUPS) 265 nuidp->nu_cr.cr_ngroups = NGROUPS; 266 nuidp->nu_cr.cr_ref = 1; 267 nuidp->nu_uid = nsd->nsd_uid; 268 TAILQ_INSERT_TAIL(&slp->ns_uidlruhead, nuidp, 269 nu_lru); 270 LIST_INSERT_HEAD(NUIDHASH(slp, nsd->nsd_uid), 271 nuidp, nu_hash); 272 } 273 } 274 } 275 if ((uap->flag & NFSSVC_AUTHINFAIL) && (nfsd = nsd->nsd_nfsd)) 276 nfsd->nd_flag |= NFSD_AUTHFAIL; 277 error = nfssvc_nfsd(nsd, uap->argp, p); 278 #endif /* !NFSSERVER */ 279 } 280 if (error == EINTR || error == ERESTART) 281 error = 0; 282 return (error); 283 } 284 285 #ifdef NFSSERVER 286 /* 287 * Adds a socket to the list for servicing by nfsds. 288 */ 289 nfssvc_addsock(fp, mynam) 290 struct file *fp; 291 struct mbuf *mynam; 292 { 293 register struct mbuf *m; 294 register int siz; 295 register struct nfssvc_sock *slp; 296 register struct socket *so; 297 struct nfssvc_sock *tslp; 298 int error, s; 299 300 so = (struct socket *)fp->f_data; 301 tslp = (struct nfssvc_sock *)0; 302 /* 303 * Add it to the list, as required. 304 */ 305 if (so->so_proto->pr_protocol == IPPROTO_UDP) { 306 tslp = nfs_udpsock; 307 if (tslp->ns_flag & SLP_VALID) { 308 m_freem(mynam); 309 return (EPERM); 310 } 311 #ifdef ISO 312 } else if (so->so_proto->pr_protocol == ISOPROTO_CLTP) { 313 tslp = nfs_cltpsock; 314 if (tslp->ns_flag & SLP_VALID) { 315 m_freem(mynam); 316 return (EPERM); 317 } 318 #endif /* ISO */ 319 } 320 if (so->so_type == SOCK_STREAM) 321 siz = NFS_MAXPACKET + sizeof (u_long); 322 else 323 siz = NFS_MAXPACKET; 324 if (error = soreserve(so, siz, siz)) { 325 m_freem(mynam); 326 return (error); 327 } 328 329 /* 330 * Set protocol specific options { for now TCP only } and 331 * reserve some space. For datagram sockets, this can get called 332 * repeatedly for the same socket, but that isn't harmful. 333 */ 334 if (so->so_type == SOCK_STREAM) { 335 MGET(m, M_WAIT, MT_SOOPTS); 336 *mtod(m, int *) = 1; 337 m->m_len = sizeof(int); 338 sosetopt(so, SOL_SOCKET, SO_KEEPALIVE, m); 339 } 340 if (so->so_proto->pr_domain->dom_family == AF_INET && 341 so->so_proto->pr_protocol == IPPROTO_TCP) { 342 MGET(m, M_WAIT, MT_SOOPTS); 343 *mtod(m, int *) = 1; 344 m->m_len = sizeof(int); 345 sosetopt(so, IPPROTO_TCP, TCP_NODELAY, m); 346 } 347 so->so_rcv.sb_flags &= ~SB_NOINTR; 348 so->so_rcv.sb_timeo = 0; 349 so->so_snd.sb_flags &= ~SB_NOINTR; 350 so->so_snd.sb_timeo = 0; 351 if (tslp) 352 slp = tslp; 353 else { 354 slp = (struct nfssvc_sock *) 355 malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK); 356 bzero((caddr_t)slp, sizeof (struct nfssvc_sock)); 357 slp->ns_uidhashtbl = 358 hashinit(NUIDHASHSIZ, M_NFSSVC, &slp->ns_uidhash); 359 TAILQ_INIT(&slp->ns_uidlruhead); 360 TAILQ_INSERT_TAIL(&nfssvc_sockhead, slp, ns_chain); 361 } 362 slp->ns_so = so; 363 slp->ns_nam = mynam; 364 fp->f_count++; 365 slp->ns_fp = fp; 366 s = splnet(); 367 so->so_upcallarg = (caddr_t)slp; 368 so->so_upcall = nfsrv_rcv; 369 slp->ns_flag = (SLP_VALID | SLP_NEEDQ); 370 nfsrv_wakenfsd(slp); 371 splx(s); 372 return (0); 373 } 374 375 /* 376 * Called by nfssvc() for nfsds. Just loops around servicing rpc requests 377 * until it is killed by a signal. 378 */ 379 nfssvc_nfsd(nsd, argp, p) 380 struct nfsd_srvargs *nsd; 381 caddr_t argp; 382 struct proc *p; 383 { 384 register struct mbuf *m, *nam2; 385 register int siz; 386 register struct nfssvc_sock *slp; 387 register struct socket *so; 388 register int *solockp; 389 struct nfsd *nd = nsd->nsd_nfsd; 390 struct mbuf *mreq, *nam; 391 struct timeval starttime; 392 struct nfsuid *uidp; 393 int error, cacherep, s; 394 int sotype; 395 396 s = splnet(); 397 if (nd == (struct nfsd *)0) { 398 nsd->nsd_nfsd = nd = (struct nfsd *) 399 malloc(sizeof (struct nfsd), M_NFSD, M_WAITOK); 400 bzero((caddr_t)nd, sizeof (struct nfsd)); 401 nd->nd_procp = p; 402 nd->nd_cr.cr_ref = 1; 403 TAILQ_INSERT_TAIL(&nfsd_head, nd, nd_chain); 404 nd->nd_nqlflag = NQL_NOVAL; 405 nfs_numnfsd++; 406 } 407 /* 408 * Loop getting rpc requests until SIGKILL. 409 */ 410 for (;;) { 411 if ((nd->nd_flag & NFSD_REQINPROG) == 0) { 412 while (nd->nd_slp == (struct nfssvc_sock *)0 && 413 (nfsd_head_flag & NFSD_CHECKSLP) == 0) { 414 nd->nd_flag |= NFSD_WAITING; 415 nfsd_waiting++; 416 error = tsleep((caddr_t)nd, PSOCK | PCATCH, "nfsd", 0); 417 nfsd_waiting--; 418 if (error) 419 goto done; 420 } 421 if (nd->nd_slp == (struct nfssvc_sock *)0 && 422 (nfsd_head_flag & NFSD_CHECKSLP) != 0) { 423 for (slp = nfssvc_sockhead.tqh_first; slp != 0; 424 slp = slp->ns_chain.tqe_next) { 425 if ((slp->ns_flag & (SLP_VALID | SLP_DOREC)) 426 == (SLP_VALID | SLP_DOREC)) { 427 slp->ns_flag &= ~SLP_DOREC; 428 slp->ns_sref++; 429 nd->nd_slp = slp; 430 break; 431 } 432 } 433 if (slp == 0) 434 nfsd_head_flag &= ~NFSD_CHECKSLP; 435 } 436 if ((slp = nd->nd_slp) == (struct nfssvc_sock *)0) 437 continue; 438 if (slp->ns_flag & SLP_VALID) { 439 if (slp->ns_flag & SLP_DISCONN) 440 nfsrv_zapsock(slp); 441 else if (slp->ns_flag & SLP_NEEDQ) { 442 slp->ns_flag &= ~SLP_NEEDQ; 443 (void) nfs_sndlock(&slp->ns_solock, 444 (struct nfsreq *)0); 445 nfsrv_rcv(slp->ns_so, (caddr_t)slp, 446 M_WAIT); 447 nfs_sndunlock(&slp->ns_solock); 448 } 449 error = nfsrv_dorec(slp, nd); 450 nd->nd_flag |= NFSD_REQINPROG; 451 } 452 } else { 453 error = 0; 454 slp = nd->nd_slp; 455 } 456 if (error || (slp->ns_flag & SLP_VALID) == 0) { 457 nd->nd_slp = (struct nfssvc_sock *)0; 458 nd->nd_flag &= ~NFSD_REQINPROG; 459 nfsrv_slpderef(slp); 460 continue; 461 } 462 splx(s); 463 so = slp->ns_so; 464 sotype = so->so_type; 465 starttime = time; 466 if (so->so_proto->pr_flags & PR_CONNREQUIRED) 467 solockp = &slp->ns_solock; 468 else 469 solockp = (int *)0; 470 /* 471 * nam == nam2 for connectionless protocols such as UDP 472 * nam2 == NULL for connection based protocols to disable 473 * recent request caching. 474 */ 475 if (nam2 = nd->nd_nam) { 476 nam = nam2; 477 cacherep = RC_CHECKIT; 478 } else { 479 nam = slp->ns_nam; 480 cacherep = RC_DOIT; 481 } 482 483 /* 484 * Check to see if authorization is needed. 485 */ 486 if (nd->nd_flag & NFSD_NEEDAUTH) { 487 static int logauth = 0; 488 489 nd->nd_flag &= ~NFSD_NEEDAUTH; 490 /* 491 * Check for a mapping already installed. 492 */ 493 for (uidp = NUIDHASH(slp, nd->nd_cr.cr_uid)->lh_first; 494 uidp != 0; uidp = uidp->nu_hash.le_next) { 495 if (uidp->nu_uid == nd->nd_cr.cr_uid) 496 break; 497 } 498 if (uidp == 0) { 499 nsd->nsd_uid = nd->nd_cr.cr_uid; 500 if (nam2 && logauth++ == 0) 501 log(LOG_WARNING, "Kerberized NFS using UDP\n"); 502 nsd->nsd_haddr = 503 mtod(nam, struct sockaddr_in *)->sin_addr.s_addr; 504 nsd->nsd_authlen = nd->nd_authlen; 505 if (copyout(nd->nd_authstr, nsd->nsd_authstr, 506 nd->nd_authlen) == 0 && 507 copyout((caddr_t)nsd, argp, sizeof (*nsd)) == 0) 508 return (ENEEDAUTH); 509 cacherep = RC_DROPIT; 510 } 511 } 512 if (cacherep == RC_CHECKIT) 513 cacherep = nfsrv_getcache(nam2, nd, &mreq); 514 515 /* 516 * Check for just starting up for NQNFS and send 517 * fake "try again later" replies to the NQNFS clients. 518 */ 519 if (notstarted && nqnfsstarttime <= time.tv_sec) { 520 if (modify_flag) { 521 nqnfsstarttime = time.tv_sec + nqsrv_writeslack; 522 modify_flag = 0; 523 } else 524 notstarted = 0; 525 } 526 if (notstarted) { 527 if (nd->nd_nqlflag == NQL_NOVAL) 528 cacherep = RC_DROPIT; 529 else if (nd->nd_procnum != NFSPROC_WRITE) { 530 nd->nd_procnum = NFSPROC_NOOP; 531 nd->nd_repstat = NQNFS_TRYLATER; 532 cacherep = RC_DOIT; 533 } else 534 modify_flag = 1; 535 } else if (nd->nd_flag & NFSD_AUTHFAIL) { 536 nd->nd_flag &= ~NFSD_AUTHFAIL; 537 nd->nd_procnum = NFSPROC_NOOP; 538 nd->nd_repstat = NQNFS_AUTHERR; 539 cacherep = RC_DOIT; 540 } 541 542 switch (cacherep) { 543 case RC_DOIT: 544 error = (*(nfsrv_procs[nd->nd_procnum]))(nd, 545 nd->nd_mrep, nd->nd_md, nd->nd_dpos, &nd->nd_cr, 546 nam, &mreq); 547 if (nd->nd_cr.cr_ref != 1) { 548 printf("nfssvc cref=%d\n", nd->nd_cr.cr_ref); 549 panic("nfssvc cref"); 550 } 551 if (error) { 552 if (nd->nd_procnum != NQNFSPROC_VACATED) 553 nfsstats.srv_errs++; 554 if (nam2) { 555 nfsrv_updatecache(nam2, nd, FALSE, mreq); 556 m_freem(nam2); 557 } 558 break; 559 } 560 nfsstats.srvrpccnt[nd->nd_procnum]++; 561 if (nam2) 562 nfsrv_updatecache(nam2, nd, TRUE, mreq); 563 nd->nd_mrep = (struct mbuf *)0; 564 case RC_REPLY: 565 m = mreq; 566 siz = 0; 567 while (m) { 568 siz += m->m_len; 569 m = m->m_next; 570 } 571 if (siz <= 0 || siz > NFS_MAXPACKET) { 572 printf("mbuf siz=%d\n",siz); 573 panic("Bad nfs svc reply"); 574 } 575 m = mreq; 576 m->m_pkthdr.len = siz; 577 m->m_pkthdr.rcvif = (struct ifnet *)0; 578 /* 579 * For stream protocols, prepend a Sun RPC 580 * Record Mark. 581 */ 582 if (sotype == SOCK_STREAM) { 583 M_PREPEND(m, NFSX_UNSIGNED, M_WAIT); 584 *mtod(m, u_long *) = htonl(0x80000000 | siz); 585 } 586 if (solockp) 587 (void) nfs_sndlock(solockp, (struct nfsreq *)0); 588 if (slp->ns_flag & SLP_VALID) 589 error = nfs_send(so, nam2, m, (struct nfsreq *)0); 590 else { 591 error = EPIPE; 592 m_freem(m); 593 } 594 if (nfsrtton) 595 nfsd_rt(&starttime, sotype, nd, nam, cacherep); 596 if (nam2) 597 MFREE(nam2, m); 598 if (nd->nd_mrep) 599 m_freem(nd->nd_mrep); 600 if (error == EPIPE) 601 nfsrv_zapsock(slp); 602 if (solockp) 603 nfs_sndunlock(solockp); 604 if (error == EINTR || error == ERESTART) { 605 nfsrv_slpderef(slp); 606 s = splnet(); 607 goto done; 608 } 609 break; 610 case RC_DROPIT: 611 if (nfsrtton) 612 nfsd_rt(&starttime, sotype, nd, nam, cacherep); 613 m_freem(nd->nd_mrep); 614 m_freem(nam2); 615 break; 616 }; 617 s = splnet(); 618 if (nfsrv_dorec(slp, nd)) { 619 nd->nd_flag &= ~NFSD_REQINPROG; 620 nd->nd_slp = (struct nfssvc_sock *)0; 621 nfsrv_slpderef(slp); 622 } 623 } 624 done: 625 TAILQ_REMOVE(&nfsd_head, nd, nd_chain); 626 splx(s); 627 free((caddr_t)nd, M_NFSD); 628 nsd->nsd_nfsd = (struct nfsd *)0; 629 if (--nfs_numnfsd == 0) 630 nfsrv_init(TRUE); /* Reinitialize everything */ 631 return (error); 632 } 633 634 /* 635 * Shut down a socket associated with an nfssvc_sock structure. 636 * Should be called with the send lock set, if required. 637 * The trick here is to increment the sref at the start, so that the nfsds 638 * will stop using it and clear ns_flag at the end so that it will not be 639 * reassigned during cleanup. 640 */ 641 nfsrv_zapsock(slp) 642 register struct nfssvc_sock *slp; 643 { 644 register struct nfsuid *nuidp, *nnuidp; 645 register int i; 646 struct socket *so; 647 struct file *fp; 648 struct mbuf *m; 649 650 slp->ns_flag &= ~SLP_ALLFLAGS; 651 if (fp = slp->ns_fp) { 652 slp->ns_fp = (struct file *)0; 653 so = slp->ns_so; 654 so->so_upcall = NULL; 655 soshutdown(so, 2); 656 closef(fp, (struct proc *)0); 657 if (slp->ns_nam) 658 MFREE(slp->ns_nam, m); 659 m_freem(slp->ns_raw); 660 m_freem(slp->ns_rec); 661 for (nuidp = slp->ns_uidlruhead.tqh_first; nuidp != 0; 662 nuidp = nnuidp) { 663 nnuidp = nuidp->nu_lru.tqe_next; 664 LIST_REMOVE(nuidp, nu_hash); 665 TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp, nu_lru); 666 free((caddr_t)nuidp, M_NFSUID); 667 } 668 } 669 } 670 671 /* 672 * Derefence a server socket structure. If it has no more references and 673 * is no longer valid, you can throw it away. 674 */ 675 void 676 nfsrv_slpderef(slp) 677 register struct nfssvc_sock *slp; 678 { 679 if (--(slp->ns_sref) == 0 && (slp->ns_flag & SLP_VALID) == 0) { 680 TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain); 681 free((caddr_t)slp, M_NFSSVC); 682 } 683 } 684 685 /* 686 * Initialize the data structures for the server. 687 * Handshake with any new nfsds starting up to avoid any chance of 688 * corruption. 689 */ 690 void 691 nfsrv_init(terminating) 692 int terminating; 693 { 694 register struct nfssvc_sock *slp, *nslp; 695 696 if (nfssvc_sockhead_flag & SLP_INIT) 697 panic("nfsd init"); 698 nfssvc_sockhead_flag |= SLP_INIT; 699 if (terminating) { 700 for (slp = nfssvc_sockhead.tqh_first; slp != 0; slp = nslp) { 701 nslp = slp->ns_chain.tqe_next; 702 if (slp->ns_flag & SLP_VALID) 703 nfsrv_zapsock(slp); 704 TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain); 705 free((caddr_t)slp, M_NFSSVC); 706 } 707 nfsrv_cleancache(); /* And clear out server cache */ 708 } 709 710 TAILQ_INIT(&nfssvc_sockhead); 711 nfssvc_sockhead_flag &= ~SLP_INIT; 712 if (nfssvc_sockhead_flag & SLP_WANTINIT) { 713 nfssvc_sockhead_flag &= ~SLP_WANTINIT; 714 wakeup((caddr_t)&nfssvc_sockhead); 715 } 716 717 TAILQ_INIT(&nfsd_head); 718 nfsd_head_flag &= ~NFSD_CHECKSLP; 719 720 nfs_udpsock = (struct nfssvc_sock *) 721 malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK); 722 bzero((caddr_t)nfs_udpsock, sizeof (struct nfssvc_sock)); 723 nfs_udpsock->ns_uidhashtbl = 724 hashinit(NUIDHASHSIZ, M_NFSSVC, &nfs_udpsock->ns_uidhash); 725 TAILQ_INIT(&nfs_udpsock->ns_uidlruhead); 726 TAILQ_INSERT_HEAD(&nfssvc_sockhead, nfs_udpsock, ns_chain); 727 728 nfs_cltpsock = (struct nfssvc_sock *) 729 malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK); 730 bzero((caddr_t)nfs_cltpsock, sizeof (struct nfssvc_sock)); 731 nfs_cltpsock->ns_uidhashtbl = 732 hashinit(NUIDHASHSIZ, M_NFSSVC, &nfs_cltpsock->ns_uidhash); 733 TAILQ_INIT(&nfs_cltpsock->ns_uidlruhead); 734 TAILQ_INSERT_TAIL(&nfssvc_sockhead, nfs_cltpsock, ns_chain); 735 } 736 737 /* 738 * Add entries to the server monitor log. 739 */ 740 static void 741 nfsd_rt(startp, sotype, nd, nam, cacherep) 742 struct timeval *startp; 743 int sotype; 744 register struct nfsd *nd; 745 struct mbuf *nam; 746 int cacherep; 747 { 748 register struct drt *rt; 749 750 rt = &nfsdrt.drt[nfsdrt.pos]; 751 if (cacherep == RC_DOIT) 752 rt->flag = 0; 753 else if (cacherep == RC_REPLY) 754 rt->flag = DRT_CACHEREPLY; 755 else 756 rt->flag = DRT_CACHEDROP; 757 if (sotype == SOCK_STREAM) 758 rt->flag |= DRT_TCP; 759 if (nd->nd_nqlflag != NQL_NOVAL) 760 rt->flag |= DRT_NQNFS; 761 rt->proc = nd->nd_procnum; 762 if (mtod(nam, struct sockaddr *)->sa_family == AF_INET) 763 rt->ipadr = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr; 764 else 765 rt->ipadr = INADDR_ANY; 766 rt->resptime = ((time.tv_sec - startp->tv_sec) * 1000000) + 767 (time.tv_usec - startp->tv_usec); 768 rt->tstamp = time; 769 nfsdrt.pos = (nfsdrt.pos + 1) % NFSRTTLOGSIZ; 770 } 771 #endif /* NFSSERVER */ 772 773 #ifdef NFSCLIENT 774 /* 775 * Asynchronous I/O daemons for client nfs. 776 * They do read-ahead and write-behind operations on the block I/O cache. 777 * Never returns unless it fails or gets killed. 778 */ 779 nfssvc_iod(p) 780 struct proc *p; 781 { 782 register struct buf *bp; 783 register int i, myiod; 784 int error = 0; 785 786 /* 787 * Assign my position or return error if too many already running 788 */ 789 myiod = -1; 790 for (i = 0; i < NFS_MAXASYNCDAEMON; i++) 791 if (nfs_asyncdaemon[i] == 0) { 792 nfs_asyncdaemon[i]++; 793 myiod = i; 794 break; 795 } 796 if (myiod == -1) 797 return (EBUSY); 798 nfs_numasync++; 799 /* 800 * Just loop around doin our stuff until SIGKILL 801 */ 802 for (;;) { 803 while (nfs_bufq.tqh_first == NULL && error == 0) { 804 nfs_iodwant[myiod] = p; 805 error = tsleep((caddr_t)&nfs_iodwant[myiod], 806 PWAIT | PCATCH, "nfsidl", 0); 807 } 808 while ((bp = nfs_bufq.tqh_first) != NULL) { 809 /* Take one off the front of the list */ 810 TAILQ_REMOVE(&nfs_bufq, bp, b_freelist); 811 if (bp->b_flags & B_READ) 812 (void) nfs_doio(bp, bp->b_rcred, (struct proc *)0); 813 else 814 (void) nfs_doio(bp, bp->b_wcred, (struct proc *)0); 815 } 816 if (error) { 817 nfs_asyncdaemon[myiod] = 0; 818 nfs_numasync--; 819 return (error); 820 } 821 } 822 } 823 824 /* 825 * Get an authorization string for the uid by having the mount_nfs sitting 826 * on this mount point porpous out of the kernel and do it. 827 */ 828 nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len) 829 register struct nfsmount *nmp; 830 struct nfsreq *rep; 831 struct ucred *cred; 832 int *auth_type; 833 char **auth_str; 834 int *auth_len; 835 { 836 int error = 0; 837 838 while ((nmp->nm_flag & NFSMNT_WAITAUTH) == 0) { 839 nmp->nm_flag |= NFSMNT_WANTAUTH; 840 (void) tsleep((caddr_t)&nmp->nm_authtype, PSOCK, 841 "nfsauth1", 2 * hz); 842 if (error = nfs_sigintr(nmp, rep, rep->r_procp)) { 843 nmp->nm_flag &= ~NFSMNT_WANTAUTH; 844 return (error); 845 } 846 } 847 nmp->nm_flag &= ~(NFSMNT_WAITAUTH | NFSMNT_WANTAUTH); 848 nmp->nm_authstr = *auth_str = (char *)malloc(RPCAUTH_MAXSIZ, M_TEMP, M_WAITOK); 849 nmp->nm_authuid = cred->cr_uid; 850 wakeup((caddr_t)&nmp->nm_authstr); 851 852 /* 853 * And wait for mount_nfs to do its stuff. 854 */ 855 while ((nmp->nm_flag & NFSMNT_HASAUTH) == 0 && error == 0) { 856 (void) tsleep((caddr_t)&nmp->nm_authlen, PSOCK, 857 "nfsauth2", 2 * hz); 858 error = nfs_sigintr(nmp, rep, rep->r_procp); 859 } 860 if (nmp->nm_flag & NFSMNT_AUTHERR) { 861 nmp->nm_flag &= ~NFSMNT_AUTHERR; 862 error = EAUTH; 863 } 864 if (error) 865 free((caddr_t)*auth_str, M_TEMP); 866 else { 867 *auth_type = nmp->nm_authtype; 868 *auth_len = nmp->nm_authlen; 869 } 870 nmp->nm_flag &= ~NFSMNT_HASAUTH; 871 nmp->nm_flag |= NFSMNT_WAITAUTH; 872 if (nmp->nm_flag & NFSMNT_WANTAUTH) { 873 nmp->nm_flag &= ~NFSMNT_WANTAUTH; 874 wakeup((caddr_t)&nmp->nm_authtype); 875 } 876 return (error); 877 } 878 #endif /* NFSCLIENT */ 879