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