1 /* $NetBSD: nfs_syscalls.c,v 1.27 1997/10/10 01:53:26 fvdl 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.5 (Berkeley) 3/30/95 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 #include <sys/filedesc.h> 60 61 #include <sys/syscallargs.h> 62 63 #include <netinet/in.h> 64 #include <netinet/tcp.h> 65 #ifdef ISO 66 #include <netiso/iso.h> 67 #endif 68 #include <nfs/xdr_subs.h> 69 #include <nfs/rpcv2.h> 70 #include <nfs/nfsproto.h> 71 #include <nfs/nfs.h> 72 #include <nfs/nfsm_subs.h> 73 #include <nfs/nfsrvcache.h> 74 #include <nfs/nfsmount.h> 75 #include <nfs/nfsnode.h> 76 #include <nfs/nqnfs.h> 77 #include <nfs/nfsrtt.h> 78 #include <nfs/nfs_var.h> 79 80 void nfsrv_zapsock __P((struct nfssvc_sock *)); 81 82 /* Global defs. */ 83 extern int32_t (*nfsrv3_procs[NFS_NPROCS]) __P((struct nfsrv_descript *, 84 struct nfssvc_sock *, 85 struct proc *, struct mbuf **)); 86 extern int nfs_numasync; 87 extern time_t nqnfsstarttime; 88 extern int nqsrv_writeslack; 89 extern int nfsrtton; 90 extern struct nfsstats nfsstats; 91 extern int nfsrvw_procrastinate; 92 struct nfssvc_sock *nfs_udpsock, *nfs_cltpsock; 93 int nuidhash_max = NFS_MAXUIDHASH; 94 int nfsd_waiting = 0; 95 #ifdef NFSSERVER 96 static int nfs_numnfsd = 0; 97 static int notstarted = 1; 98 static int modify_flag = 0; 99 static struct nfsdrt nfsdrt; 100 extern struct nfs_public nfs_pub; 101 #endif 102 103 #define TRUE 1 104 #define FALSE 0 105 106 #ifdef NFS 107 static int nfs_asyncdaemon[NFS_MAXASYNCDAEMON]; 108 #endif 109 110 #ifdef NFSSERVER 111 static void nfsd_rt __P((int, struct nfsrv_descript *, int)); 112 #endif 113 114 /* 115 * NFS server system calls 116 * getfh() lives here too, but maybe should move to kern/vfs_syscalls.c 117 */ 118 119 /* 120 * Get file handle system call 121 */ 122 int 123 sys_getfh(p, v, retval) 124 struct proc *p; 125 register void *v; 126 register_t *retval; 127 { 128 register struct sys_getfh_args /* { 129 syscallarg(char *) fname; 130 syscallarg(fhandle_t *) fhp; 131 } */ *uap = v; 132 register struct vnode *vp; 133 fhandle_t fh; 134 int error; 135 struct nameidata nd; 136 137 /* 138 * Must be super user 139 */ 140 error = suser(p->p_ucred, &p->p_acflag); 141 if (error) 142 return (error); 143 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 144 SCARG(uap, fname), p); 145 error = namei(&nd); 146 if (error) 147 return (error); 148 vp = nd.ni_vp; 149 bzero((caddr_t)&fh, sizeof(fh)); 150 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; 151 error = VFS_VPTOFH(vp, &fh.fh_fid); 152 vput(vp); 153 if (error) 154 return (error); 155 error = copyout((caddr_t)&fh, (caddr_t)SCARG(uap, fhp), sizeof (fh)); 156 return (error); 157 } 158 159 /* 160 * Nfs server pseudo system call for the nfsd's 161 * Based on the flag value it either: 162 * - adds a socket to the selection list 163 * - remains in the kernel as an nfsd 164 * - remains in the kernel as an nfsiod 165 */ 166 int 167 sys_nfssvc(p, v, retval) 168 struct proc *p; 169 void *v; 170 register_t *retval; 171 { 172 register struct sys_nfssvc_args /* { 173 syscallarg(int) flag; 174 syscallarg(caddr_t) argp; 175 } */ *uap = v; 176 int error; 177 #ifdef NFS 178 struct nameidata nd; 179 struct nfsmount *nmp; 180 struct nfsd_cargs ncd; 181 #endif 182 #ifdef NFSSERVER 183 struct file *fp; 184 struct mbuf *nam; 185 struct nfsd_args nfsdarg; 186 struct nfsd_srvargs nfsd_srvargs, *nsd = &nfsd_srvargs; 187 struct nfsd *nfsd; 188 struct nfssvc_sock *slp; 189 struct nfsuid *nuidp; 190 #endif 191 192 /* 193 * Must be super user 194 */ 195 error = suser(p->p_ucred, &p->p_acflag); 196 if(error) 197 return (error); 198 while (nfssvc_sockhead_flag & SLP_INIT) { 199 nfssvc_sockhead_flag |= SLP_WANTINIT; 200 (void) tsleep((caddr_t)&nfssvc_sockhead, PSOCK, "nfsd init", 0); 201 } 202 if (SCARG(uap, flag) & NFSSVC_BIOD) { 203 #ifdef NFS 204 error = nfssvc_iod(p); 205 #else 206 error = ENOSYS; 207 #endif 208 } else if (SCARG(uap, flag) & NFSSVC_MNTD) { 209 #ifndef NFS 210 error = ENOSYS; 211 #else 212 error = copyin(SCARG(uap, argp), (caddr_t)&ncd, sizeof (ncd)); 213 if (error) 214 return (error); 215 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 216 ncd.ncd_dirp, p); 217 error = namei(&nd); 218 if (error) 219 return (error); 220 if ((nd.ni_vp->v_flag & VROOT) == 0) 221 error = EINVAL; 222 nmp = VFSTONFS(nd.ni_vp->v_mount); 223 vput(nd.ni_vp); 224 if (error) 225 return (error); 226 if ((nmp->nm_iflag & NFSMNT_MNTD) && 227 (SCARG(uap, flag) & NFSSVC_GOTAUTH) == 0) 228 return (0); 229 nmp->nm_iflag |= NFSMNT_MNTD; 230 error = nqnfs_clientd(nmp, p->p_ucred, &ncd, SCARG(uap, flag), 231 SCARG(uap, argp), p); 232 #endif /* NFS */ 233 } else if (SCARG(uap, flag) & NFSSVC_ADDSOCK) { 234 #ifndef NFSSERVER 235 error = ENOSYS; 236 #else 237 error = copyin(SCARG(uap, argp), (caddr_t)&nfsdarg, 238 sizeof(nfsdarg)); 239 if (error) 240 return (error); 241 error = getsock(p->p_fd, nfsdarg.sock, &fp); 242 if (error) 243 return (error); 244 /* 245 * Get the client address for connected sockets. 246 */ 247 if (nfsdarg.name == NULL || nfsdarg.namelen == 0) 248 nam = (struct mbuf *)0; 249 else { 250 error = sockargs(&nam, nfsdarg.name, nfsdarg.namelen, 251 MT_SONAME); 252 if (error) 253 return (error); 254 } 255 error = nfssvc_addsock(fp, nam); 256 #endif /* !NFSSERVER */ 257 } else { 258 #ifndef NFSSERVER 259 error = ENOSYS; 260 #else 261 error = copyin(SCARG(uap, argp), (caddr_t)nsd, sizeof (*nsd)); 262 if (error) 263 return (error); 264 if ((SCARG(uap, flag) & NFSSVC_AUTHIN) && 265 ((nfsd = nsd->nsd_nfsd)) != NULL && 266 (nfsd->nfsd_slp->ns_flag & SLP_VALID)) { 267 slp = nfsd->nfsd_slp; 268 269 /* 270 * First check to see if another nfsd has already 271 * added this credential. 272 */ 273 for (nuidp = NUIDHASH(slp,nsd->nsd_cr.cr_uid)->lh_first; 274 nuidp != 0; nuidp = nuidp->nu_hash.le_next) { 275 if (nuidp->nu_cr.cr_uid == nsd->nsd_cr.cr_uid && 276 (!nfsd->nfsd_nd->nd_nam2 || 277 netaddr_match(NU_NETFAM(nuidp), 278 &nuidp->nu_haddr, nfsd->nfsd_nd->nd_nam2))) 279 break; 280 } 281 if (nuidp) { 282 nfsrv_setcred(&nuidp->nu_cr,&nfsd->nfsd_nd->nd_cr); 283 nfsd->nfsd_nd->nd_flag |= ND_KERBFULL; 284 } else { 285 /* 286 * Nope, so we will. 287 */ 288 if (slp->ns_numuids < nuidhash_max) { 289 slp->ns_numuids++; 290 nuidp = (struct nfsuid *) 291 malloc(sizeof (struct nfsuid), M_NFSUID, 292 M_WAITOK); 293 } else 294 nuidp = (struct nfsuid *)0; 295 if ((slp->ns_flag & SLP_VALID) == 0) { 296 if (nuidp) 297 free((caddr_t)nuidp, M_NFSUID); 298 } else { 299 if (nuidp == (struct nfsuid *)0) { 300 nuidp = slp->ns_uidlruhead.tqh_first; 301 LIST_REMOVE(nuidp, nu_hash); 302 TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp, 303 nu_lru); 304 if (nuidp->nu_flag & NU_NAM) 305 m_freem(nuidp->nu_nam); 306 } 307 nuidp->nu_flag = 0; 308 nuidp->nu_cr = nsd->nsd_cr; 309 if (nuidp->nu_cr.cr_ngroups > NGROUPS) 310 nuidp->nu_cr.cr_ngroups = NGROUPS; 311 nuidp->nu_cr.cr_ref = 1; 312 nuidp->nu_timestamp = nsd->nsd_timestamp; 313 nuidp->nu_expire = time.tv_sec + nsd->nsd_ttl; 314 /* 315 * and save the session key in nu_key. 316 */ 317 bcopy(nsd->nsd_key, nuidp->nu_key, 318 sizeof (nsd->nsd_key)); 319 if (nfsd->nfsd_nd->nd_nam2) { 320 struct sockaddr_in *saddr; 321 322 saddr = mtod(nfsd->nfsd_nd->nd_nam2, 323 struct sockaddr_in *); 324 switch (saddr->sin_family) { 325 case AF_INET: 326 nuidp->nu_flag |= NU_INETADDR; 327 nuidp->nu_inetaddr = 328 saddr->sin_addr.s_addr; 329 break; 330 case AF_ISO: 331 default: 332 nuidp->nu_flag |= NU_NAM; 333 nuidp->nu_nam = m_copym( 334 nfsd->nfsd_nd->nd_nam2, 0, 335 M_COPYALL, M_WAIT); 336 break; 337 }; 338 } 339 TAILQ_INSERT_TAIL(&slp->ns_uidlruhead, nuidp, 340 nu_lru); 341 LIST_INSERT_HEAD(NUIDHASH(slp, nsd->nsd_uid), 342 nuidp, nu_hash); 343 nfsrv_setcred(&nuidp->nu_cr, 344 &nfsd->nfsd_nd->nd_cr); 345 nfsd->nfsd_nd->nd_flag |= ND_KERBFULL; 346 } 347 } 348 } 349 if ((SCARG(uap, flag) & NFSSVC_AUTHINFAIL) && 350 (nfsd = nsd->nsd_nfsd)) 351 nfsd->nfsd_flag |= NFSD_AUTHFAIL; 352 error = nfssvc_nfsd(nsd, SCARG(uap, argp), p); 353 #endif /* !NFSSERVER */ 354 } 355 if (error == EINTR || error == ERESTART) 356 error = 0; 357 return (error); 358 } 359 360 #ifdef NFSSERVER 361 /* 362 * Adds a socket to the list for servicing by nfsds. 363 */ 364 int 365 nfssvc_addsock(fp, mynam) 366 struct file *fp; 367 struct mbuf *mynam; 368 { 369 register struct mbuf *m; 370 register int siz; 371 register struct nfssvc_sock *slp; 372 register struct socket *so; 373 struct nfssvc_sock *tslp; 374 int error, s; 375 376 so = (struct socket *)fp->f_data; 377 tslp = (struct nfssvc_sock *)0; 378 /* 379 * Add it to the list, as required. 380 */ 381 if (so->so_proto->pr_protocol == IPPROTO_UDP) { 382 tslp = nfs_udpsock; 383 if (tslp->ns_flag & SLP_VALID) { 384 m_freem(mynam); 385 return (EPERM); 386 } 387 #ifdef ISO 388 } else if (so->so_proto->pr_protocol == ISOPROTO_CLTP) { 389 tslp = nfs_cltpsock; 390 if (tslp->ns_flag & SLP_VALID) { 391 m_freem(mynam); 392 return (EPERM); 393 } 394 #endif /* ISO */ 395 } 396 if (so->so_type == SOCK_STREAM) 397 siz = NFS_MAXPACKET + sizeof (u_long); 398 else 399 siz = NFS_MAXPACKET; 400 error = soreserve(so, siz, siz); 401 if (error) { 402 m_freem(mynam); 403 return (error); 404 } 405 406 /* 407 * Set protocol specific options { for now TCP only } and 408 * reserve some space. For datagram sockets, this can get called 409 * repeatedly for the same socket, but that isn't harmful. 410 */ 411 if (so->so_type == SOCK_STREAM) { 412 MGET(m, M_WAIT, MT_SOOPTS); 413 *mtod(m, int32_t *) = 1; 414 m->m_len = sizeof(int32_t); 415 sosetopt(so, SOL_SOCKET, SO_KEEPALIVE, m); 416 } 417 if (so->so_proto->pr_domain->dom_family == AF_INET && 418 so->so_proto->pr_protocol == IPPROTO_TCP) { 419 MGET(m, M_WAIT, MT_SOOPTS); 420 *mtod(m, int32_t *) = 1; 421 m->m_len = sizeof(int32_t); 422 sosetopt(so, IPPROTO_TCP, TCP_NODELAY, m); 423 } 424 so->so_rcv.sb_flags &= ~SB_NOINTR; 425 so->so_rcv.sb_timeo = 0; 426 so->so_snd.sb_flags &= ~SB_NOINTR; 427 so->so_snd.sb_timeo = 0; 428 if (tslp) 429 slp = tslp; 430 else { 431 slp = (struct nfssvc_sock *) 432 malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK); 433 bzero((caddr_t)slp, sizeof (struct nfssvc_sock)); 434 TAILQ_INIT(&slp->ns_uidlruhead); 435 TAILQ_INSERT_TAIL(&nfssvc_sockhead, slp, ns_chain); 436 } 437 slp->ns_so = so; 438 slp->ns_nam = mynam; 439 fp->f_count++; 440 slp->ns_fp = fp; 441 s = splsoftnet(); 442 so->so_upcallarg = (caddr_t)slp; 443 so->so_upcall = nfsrv_rcv; 444 slp->ns_flag = (SLP_VALID | SLP_NEEDQ); 445 nfsrv_wakenfsd(slp); 446 splx(s); 447 return (0); 448 } 449 450 /* 451 * Called by nfssvc() for nfsds. Just loops around servicing rpc requests 452 * until it is killed by a signal. 453 */ 454 int 455 nfssvc_nfsd(nsd, argp, p) 456 struct nfsd_srvargs *nsd; 457 caddr_t argp; 458 struct proc *p; 459 { 460 register struct mbuf *m; 461 register int siz; 462 register struct nfssvc_sock *slp; 463 register struct socket *so; 464 register int *solockp; 465 struct nfsd *nfsd = nsd->nsd_nfsd; 466 struct nfsrv_descript *nd = NULL; 467 struct mbuf *mreq; 468 int error = 0, cacherep, s, sotype, writes_todo; 469 u_quad_t cur_usec; 470 471 #ifndef nolint 472 cacherep = RC_DOIT; 473 writes_todo = 0; 474 #endif 475 s = splsoftnet(); 476 if (nfsd == (struct nfsd *)0) { 477 nsd->nsd_nfsd = nfsd = (struct nfsd *) 478 malloc(sizeof (struct nfsd), M_NFSD, M_WAITOK); 479 bzero((caddr_t)nfsd, sizeof (struct nfsd)); 480 nfsd->nfsd_procp = p; 481 TAILQ_INSERT_TAIL(&nfsd_head, nfsd, nfsd_chain); 482 nfs_numnfsd++; 483 } 484 /* 485 * Loop getting rpc requests until SIGKILL. 486 */ 487 for (;;) { 488 if ((nfsd->nfsd_flag & NFSD_REQINPROG) == 0) { 489 while (nfsd->nfsd_slp == (struct nfssvc_sock *)0 && 490 (nfsd_head_flag & NFSD_CHECKSLP) == 0) { 491 nfsd->nfsd_flag |= NFSD_WAITING; 492 nfsd_waiting++; 493 error = tsleep((caddr_t)nfsd, PSOCK | PCATCH, 494 "nfsd", 0); 495 nfsd_waiting--; 496 if (error) 497 goto done; 498 } 499 if (nfsd->nfsd_slp == (struct nfssvc_sock *)0 && 500 (nfsd_head_flag & NFSD_CHECKSLP) != 0) { 501 for (slp = nfssvc_sockhead.tqh_first; slp != 0; 502 slp = slp->ns_chain.tqe_next) { 503 if ((slp->ns_flag & (SLP_VALID | SLP_DOREC)) 504 == (SLP_VALID | SLP_DOREC)) { 505 slp->ns_flag &= ~SLP_DOREC; 506 slp->ns_sref++; 507 nfsd->nfsd_slp = slp; 508 break; 509 } 510 } 511 if (slp == 0) 512 nfsd_head_flag &= ~NFSD_CHECKSLP; 513 } 514 if ((slp = nfsd->nfsd_slp) == (struct nfssvc_sock *)0) 515 continue; 516 if (slp->ns_flag & SLP_VALID) { 517 if (slp->ns_flag & SLP_DISCONN) 518 nfsrv_zapsock(slp); 519 else if (slp->ns_flag & SLP_NEEDQ) { 520 slp->ns_flag &= ~SLP_NEEDQ; 521 (void) nfs_sndlock(&slp->ns_solock, 522 (struct nfsreq *)0); 523 nfsrv_rcv(slp->ns_so, (caddr_t)slp, 524 M_WAIT); 525 nfs_sndunlock(&slp->ns_solock); 526 } 527 error = nfsrv_dorec(slp, nfsd, &nd); 528 cur_usec = (u_quad_t)time.tv_sec * 1000000 + 529 (u_quad_t)time.tv_usec; 530 if (error && slp->ns_tq.lh_first && 531 slp->ns_tq.lh_first->nd_time <= cur_usec) { 532 error = 0; 533 cacherep = RC_DOIT; 534 writes_todo = 1; 535 } else 536 writes_todo = 0; 537 nfsd->nfsd_flag |= NFSD_REQINPROG; 538 } 539 } else { 540 error = 0; 541 slp = nfsd->nfsd_slp; 542 } 543 if (error || (slp->ns_flag & SLP_VALID) == 0) { 544 if (nd) { 545 free((caddr_t)nd, M_NFSRVDESC); 546 nd = NULL; 547 } 548 nfsd->nfsd_slp = (struct nfssvc_sock *)0; 549 nfsd->nfsd_flag &= ~NFSD_REQINPROG; 550 nfsrv_slpderef(slp); 551 continue; 552 } 553 splx(s); 554 so = slp->ns_so; 555 sotype = so->so_type; 556 if (so->so_proto->pr_flags & PR_CONNREQUIRED) 557 solockp = &slp->ns_solock; 558 else 559 solockp = (int *)0; 560 if (nd) { 561 nd->nd_starttime = time; 562 if (nd->nd_nam2) 563 nd->nd_nam = nd->nd_nam2; 564 else 565 nd->nd_nam = slp->ns_nam; 566 567 /* 568 * Check to see if authorization is needed. 569 */ 570 if (nfsd->nfsd_flag & NFSD_NEEDAUTH) { 571 nfsd->nfsd_flag &= ~NFSD_NEEDAUTH; 572 nsd->nsd_haddr = mtod(nd->nd_nam, 573 struct sockaddr_in *)->sin_addr.s_addr; 574 nsd->nsd_authlen = nfsd->nfsd_authlen; 575 nsd->nsd_verflen = nfsd->nfsd_verflen; 576 if (!copyout(nfsd->nfsd_authstr,nsd->nsd_authstr, 577 nfsd->nfsd_authlen) && 578 !copyout(nfsd->nfsd_verfstr, nsd->nsd_verfstr, 579 nfsd->nfsd_verflen) && 580 !copyout((caddr_t)nsd, argp, sizeof (*nsd))) 581 return (ENEEDAUTH); 582 cacherep = RC_DROPIT; 583 } else 584 cacherep = nfsrv_getcache(nd, slp, &mreq); 585 586 /* 587 * Check for just starting up for NQNFS and send 588 * fake "try again later" replies to the NQNFS clients. 589 */ 590 if (notstarted && nqnfsstarttime <= time.tv_sec) { 591 if (modify_flag) { 592 nqnfsstarttime = time.tv_sec + nqsrv_writeslack; 593 modify_flag = 0; 594 } else 595 notstarted = 0; 596 } 597 if (notstarted) { 598 if ((nd->nd_flag & ND_NQNFS) == 0) 599 cacherep = RC_DROPIT; 600 else if (nd->nd_procnum != NFSPROC_WRITE) { 601 nd->nd_procnum = NFSPROC_NOOP; 602 nd->nd_repstat = NQNFS_TRYLATER; 603 cacherep = RC_DOIT; 604 } else 605 modify_flag = 1; 606 } else if (nfsd->nfsd_flag & NFSD_AUTHFAIL) { 607 nfsd->nfsd_flag &= ~NFSD_AUTHFAIL; 608 nd->nd_procnum = NFSPROC_NOOP; 609 nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK); 610 cacherep = RC_DOIT; 611 } 612 } 613 614 /* 615 * Loop to get all the write rpc relies that have been 616 * gathered together. 617 */ 618 do { 619 switch (cacherep) { 620 case RC_DOIT: 621 if (writes_todo || (nd->nd_procnum == NFSPROC_WRITE && 622 nfsrvw_procrastinate > 0 && !notstarted)) 623 error = nfsrv_writegather(&nd, slp, 624 nfsd->nfsd_procp, &mreq); 625 else 626 error = (*(nfsrv3_procs[nd->nd_procnum]))(nd, 627 slp, nfsd->nfsd_procp, &mreq); 628 if (mreq == NULL) 629 break; 630 if (error) { 631 if (nd->nd_procnum != NQNFSPROC_VACATED) 632 nfsstats.srv_errs++; 633 nfsrv_updatecache(nd, FALSE, mreq); 634 if (nd->nd_nam2) 635 m_freem(nd->nd_nam2); 636 break; 637 } 638 nfsstats.srvrpccnt[nd->nd_procnum]++; 639 nfsrv_updatecache(nd, TRUE, mreq); 640 nd->nd_mrep = (struct mbuf *)0; 641 case RC_REPLY: 642 m = mreq; 643 siz = 0; 644 while (m) { 645 siz += m->m_len; 646 m = m->m_next; 647 } 648 if (siz <= 0 || siz > NFS_MAXPACKET) { 649 printf("mbuf siz=%d\n",siz); 650 panic("Bad nfs svc reply"); 651 } 652 m = mreq; 653 m->m_pkthdr.len = siz; 654 m->m_pkthdr.rcvif = (struct ifnet *)0; 655 /* 656 * For stream protocols, prepend a Sun RPC 657 * Record Mark. 658 */ 659 if (sotype == SOCK_STREAM) { 660 M_PREPEND(m, NFSX_UNSIGNED, M_WAIT); 661 *mtod(m, u_int32_t *) = htonl(0x80000000 | siz); 662 } 663 if (solockp) 664 (void) nfs_sndlock(solockp, (struct nfsreq *)0); 665 if (slp->ns_flag & SLP_VALID) 666 error = nfs_send(so, nd->nd_nam2, m, NULL); 667 else { 668 error = EPIPE; 669 m_freem(m); 670 } 671 if (nfsrtton) 672 nfsd_rt(sotype, nd, cacherep); 673 if (nd->nd_nam2) 674 MFREE(nd->nd_nam2, m); 675 if (nd->nd_mrep) 676 m_freem(nd->nd_mrep); 677 if (error == EPIPE) 678 nfsrv_zapsock(slp); 679 if (solockp) 680 nfs_sndunlock(solockp); 681 if (error == EINTR || error == ERESTART) { 682 free((caddr_t)nd, M_NFSRVDESC); 683 nfsrv_slpderef(slp); 684 s = splsoftnet(); 685 goto done; 686 } 687 break; 688 case RC_DROPIT: 689 if (nfsrtton) 690 nfsd_rt(sotype, nd, cacherep); 691 m_freem(nd->nd_mrep); 692 m_freem(nd->nd_nam2); 693 break; 694 }; 695 if (nd) { 696 FREE((caddr_t)nd, M_NFSRVDESC); 697 nd = NULL; 698 } 699 700 /* 701 * Check to see if there are outstanding writes that 702 * need to be serviced. 703 */ 704 cur_usec = (u_quad_t)time.tv_sec * 1000000 + 705 (u_quad_t)time.tv_usec; 706 s = splsoftclock(); 707 if (slp->ns_tq.lh_first && 708 slp->ns_tq.lh_first->nd_time <= cur_usec) { 709 cacherep = RC_DOIT; 710 writes_todo = 1; 711 } else 712 writes_todo = 0; 713 splx(s); 714 } while (writes_todo); 715 s = splsoftnet(); 716 if (nfsrv_dorec(slp, nfsd, &nd)) { 717 nfsd->nfsd_flag &= ~NFSD_REQINPROG; 718 nfsd->nfsd_slp = NULL; 719 nfsrv_slpderef(slp); 720 } 721 } 722 done: 723 TAILQ_REMOVE(&nfsd_head, nfsd, nfsd_chain); 724 splx(s); 725 free((caddr_t)nfsd, M_NFSD); 726 nsd->nsd_nfsd = (struct nfsd *)0; 727 if (--nfs_numnfsd == 0) 728 nfsrv_init(TRUE); /* Reinitialize everything */ 729 return (error); 730 } 731 732 /* 733 * Shut down a socket associated with an nfssvc_sock structure. 734 * Should be called with the send lock set, if required. 735 * The trick here is to increment the sref at the start, so that the nfsds 736 * will stop using it and clear ns_flag at the end so that it will not be 737 * reassigned during cleanup. 738 */ 739 void 740 nfsrv_zapsock(slp) 741 register struct nfssvc_sock *slp; 742 { 743 register struct nfsuid *nuidp, *nnuidp; 744 register struct nfsrv_descript *nwp, *nnwp; 745 struct socket *so; 746 struct file *fp; 747 struct mbuf *m; 748 int s; 749 750 slp->ns_flag &= ~SLP_ALLFLAGS; 751 fp = slp->ns_fp; 752 if (fp) { 753 slp->ns_fp = (struct file *)0; 754 so = slp->ns_so; 755 so->so_upcall = NULL; 756 soshutdown(so, 2); 757 closef(fp, (struct proc *)0); 758 if (slp->ns_nam) 759 MFREE(slp->ns_nam, m); 760 m_freem(slp->ns_raw); 761 m_freem(slp->ns_rec); 762 for (nuidp = slp->ns_uidlruhead.tqh_first; nuidp != 0; 763 nuidp = nnuidp) { 764 nnuidp = nuidp->nu_lru.tqe_next; 765 LIST_REMOVE(nuidp, nu_hash); 766 TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp, nu_lru); 767 if (nuidp->nu_flag & NU_NAM) 768 m_freem(nuidp->nu_nam); 769 free((caddr_t)nuidp, M_NFSUID); 770 } 771 s = splsoftclock(); 772 for (nwp = slp->ns_tq.lh_first; nwp; nwp = nnwp) { 773 nnwp = nwp->nd_tq.le_next; 774 LIST_REMOVE(nwp, nd_tq); 775 free((caddr_t)nwp, M_NFSRVDESC); 776 } 777 LIST_INIT(&slp->ns_tq); 778 splx(s); 779 } 780 } 781 782 /* 783 * Derefence a server socket structure. If it has no more references and 784 * is no longer valid, you can throw it away. 785 */ 786 void 787 nfsrv_slpderef(slp) 788 register struct nfssvc_sock *slp; 789 { 790 if (--(slp->ns_sref) == 0 && (slp->ns_flag & SLP_VALID) == 0) { 791 TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain); 792 free((caddr_t)slp, M_NFSSVC); 793 } 794 } 795 796 /* 797 * Initialize the data structures for the server. 798 * Handshake with any new nfsds starting up to avoid any chance of 799 * corruption. 800 */ 801 void 802 nfsrv_init(terminating) 803 int terminating; 804 { 805 register struct nfssvc_sock *slp, *nslp; 806 807 if (nfssvc_sockhead_flag & SLP_INIT) 808 panic("nfsd init"); 809 nfssvc_sockhead_flag |= SLP_INIT; 810 if (terminating) { 811 for (slp = nfssvc_sockhead.tqh_first; slp != 0; slp = nslp) { 812 nslp = slp->ns_chain.tqe_next; 813 if (slp->ns_flag & SLP_VALID) 814 nfsrv_zapsock(slp); 815 TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain); 816 free((caddr_t)slp, M_NFSSVC); 817 } 818 nfsrv_cleancache(); /* And clear out server cache */ 819 } else 820 nfs_pub.np_valid = 0; 821 822 TAILQ_INIT(&nfssvc_sockhead); 823 nfssvc_sockhead_flag &= ~SLP_INIT; 824 if (nfssvc_sockhead_flag & SLP_WANTINIT) { 825 nfssvc_sockhead_flag &= ~SLP_WANTINIT; 826 wakeup((caddr_t)&nfssvc_sockhead); 827 } 828 829 TAILQ_INIT(&nfsd_head); 830 nfsd_head_flag &= ~NFSD_CHECKSLP; 831 832 nfs_udpsock = (struct nfssvc_sock *) 833 malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK); 834 bzero((caddr_t)nfs_udpsock, sizeof (struct nfssvc_sock)); 835 TAILQ_INIT(&nfs_udpsock->ns_uidlruhead); 836 TAILQ_INSERT_HEAD(&nfssvc_sockhead, nfs_udpsock, ns_chain); 837 838 nfs_cltpsock = (struct nfssvc_sock *) 839 malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK); 840 bzero((caddr_t)nfs_cltpsock, sizeof (struct nfssvc_sock)); 841 TAILQ_INIT(&nfs_cltpsock->ns_uidlruhead); 842 TAILQ_INSERT_TAIL(&nfssvc_sockhead, nfs_cltpsock, ns_chain); 843 } 844 845 /* 846 * Add entries to the server monitor log. 847 */ 848 static void 849 nfsd_rt(sotype, nd, cacherep) 850 int sotype; 851 register struct nfsrv_descript *nd; 852 int cacherep; 853 { 854 register struct drt *rt; 855 856 rt = &nfsdrt.drt[nfsdrt.pos]; 857 if (cacherep == RC_DOIT) 858 rt->flag = 0; 859 else if (cacherep == RC_REPLY) 860 rt->flag = DRT_CACHEREPLY; 861 else 862 rt->flag = DRT_CACHEDROP; 863 if (sotype == SOCK_STREAM) 864 rt->flag |= DRT_TCP; 865 if (nd->nd_flag & ND_NQNFS) 866 rt->flag |= DRT_NQNFS; 867 else if (nd->nd_flag & ND_NFSV3) 868 rt->flag |= DRT_NFSV3; 869 rt->proc = nd->nd_procnum; 870 if (mtod(nd->nd_nam, struct sockaddr *)->sa_family == AF_INET) 871 rt->ipadr = mtod(nd->nd_nam, struct sockaddr_in *)->sin_addr.s_addr; 872 else 873 rt->ipadr = INADDR_ANY; 874 rt->resptime = ((time.tv_sec - nd->nd_starttime.tv_sec) * 1000000) + 875 (time.tv_usec - nd->nd_starttime.tv_usec); 876 rt->tstamp = time; 877 nfsdrt.pos = (nfsdrt.pos + 1) % NFSRTTLOGSIZ; 878 } 879 #endif /* NFSSERVER */ 880 881 #ifdef NFS 882 883 int nfs_defect = 0; 884 /* 885 * Asynchronous I/O daemons for client nfs. 886 * They do read-ahead and write-behind operations on the block I/O cache. 887 * Never returns unless it fails or gets killed. 888 */ 889 int 890 nfssvc_iod(p) 891 struct proc *p; 892 { 893 register struct buf *bp; 894 register int i, myiod; 895 struct nfsmount *nmp; 896 int error = 0; 897 898 /* 899 * Assign my position or return error if too many already running 900 */ 901 myiod = -1; 902 for (i = 0; i < NFS_MAXASYNCDAEMON; i++) 903 if (nfs_asyncdaemon[i] == 0) { 904 nfs_asyncdaemon[i]++; 905 myiod = i; 906 break; 907 } 908 if (myiod == -1) 909 return (EBUSY); 910 nfs_numasync++; 911 /* 912 * Just loop around doin our stuff until SIGKILL 913 */ 914 for (;;) { 915 while (((nmp = nfs_iodmount[myiod]) == NULL 916 || nmp->nm_bufq.tqh_first == NULL) 917 && error == 0) { 918 if (nmp) 919 nmp->nm_bufqiods--; 920 nfs_iodwant[myiod] = p; 921 nfs_iodmount[myiod] = NULL; 922 error = tsleep((caddr_t)&nfs_iodwant[myiod], 923 PWAIT | PCATCH, "nfsidl", 0); 924 } 925 if (error) { 926 nfs_asyncdaemon[myiod] = 0; 927 if (nmp) 928 nmp->nm_bufqiods--; 929 nfs_iodmount[myiod] = NULL; 930 nfs_numasync--; 931 return (error); 932 } 933 while ((bp = nmp->nm_bufq.tqh_first) != NULL) { 934 /* Take one off the front of the list */ 935 TAILQ_REMOVE(&nmp->nm_bufq, bp, b_freelist); 936 nmp->nm_bufqlen--; 937 if (nmp->nm_bufqwant && nmp->nm_bufqlen < 2 * nfs_numasync) { 938 nmp->nm_bufqwant = FALSE; 939 wakeup(&nmp->nm_bufq); 940 } 941 if (bp->b_flags & B_READ) 942 (void) nfs_doio(bp, bp->b_rcred, (struct proc *)0); 943 else 944 (void) nfs_doio(bp, bp->b_wcred, (struct proc *)0); 945 /* 946 * If there are more than one iod on this mount, then defect 947 * so that the iods can be shared out fairly between the mounts 948 */ 949 if (nfs_defect && nmp->nm_bufqiods > 1) { 950 nfs_iodmount[myiod] = NULL; 951 nmp->nm_bufqiods--; 952 break; 953 } 954 } 955 } 956 } 957 958 959 /* 960 * Get an authorization string for the uid by having the mount_nfs sitting 961 * on this mount point porpous out of the kernel and do it. 962 */ 963 int 964 nfs_getauth(nmp, rep, cred, auth_str, auth_len, verf_str, verf_len, key) 965 register struct nfsmount *nmp; 966 struct nfsreq *rep; 967 struct ucred *cred; 968 char **auth_str; 969 int *auth_len; 970 char *verf_str; 971 int *verf_len; 972 NFSKERBKEY_T key; /* return session key */ 973 { 974 int error = 0; 975 976 while ((nmp->nm_iflag & NFSMNT_WAITAUTH) == 0) { 977 nmp->nm_iflag |= NFSMNT_WANTAUTH; 978 (void) tsleep((caddr_t)&nmp->nm_authtype, PSOCK, 979 "nfsauth1", 2 * hz); 980 error = nfs_sigintr(nmp, rep, rep->r_procp); 981 if (error) { 982 nmp->nm_iflag &= ~NFSMNT_WANTAUTH; 983 return (error); 984 } 985 } 986 nmp->nm_iflag &= ~(NFSMNT_WAITAUTH | NFSMNT_WANTAUTH); 987 nmp->nm_authstr = *auth_str = (char *)malloc(RPCAUTH_MAXSIZ, M_TEMP, M_WAITOK); 988 nmp->nm_authlen = RPCAUTH_MAXSIZ; 989 nmp->nm_verfstr = verf_str; 990 nmp->nm_verflen = *verf_len; 991 nmp->nm_authuid = cred->cr_uid; 992 wakeup((caddr_t)&nmp->nm_authstr); 993 994 /* 995 * And wait for mount_nfs to do its stuff. 996 */ 997 while ((nmp->nm_iflag & NFSMNT_HASAUTH) == 0 && error == 0) { 998 (void) tsleep((caddr_t)&nmp->nm_authlen, PSOCK, 999 "nfsauth2", 2 * hz); 1000 error = nfs_sigintr(nmp, rep, rep->r_procp); 1001 } 1002 if (nmp->nm_iflag & NFSMNT_AUTHERR) { 1003 nmp->nm_iflag &= ~NFSMNT_AUTHERR; 1004 error = EAUTH; 1005 } 1006 if (error) 1007 free((caddr_t)*auth_str, M_TEMP); 1008 else { 1009 *auth_len = nmp->nm_authlen; 1010 *verf_len = nmp->nm_verflen; 1011 bcopy((caddr_t)nmp->nm_key, (caddr_t)key, sizeof (key)); 1012 } 1013 nmp->nm_iflag &= ~NFSMNT_HASAUTH; 1014 nmp->nm_iflag |= NFSMNT_WAITAUTH; 1015 if (nmp->nm_iflag & NFSMNT_WANTAUTH) { 1016 nmp->nm_iflag &= ~NFSMNT_WANTAUTH; 1017 wakeup((caddr_t)&nmp->nm_authtype); 1018 } 1019 return (error); 1020 } 1021 1022 /* 1023 * Get a nickname authenticator and verifier. 1024 */ 1025 int 1026 nfs_getnickauth(nmp, cred, auth_str, auth_len, verf_str, verf_len) 1027 struct nfsmount *nmp; 1028 struct ucred *cred; 1029 char **auth_str; 1030 int *auth_len; 1031 char *verf_str; 1032 int verf_len; 1033 { 1034 register struct nfsuid *nuidp; 1035 register u_int32_t *nickp, *verfp; 1036 struct timeval ktvin, ktvout; 1037 1038 #ifdef DIAGNOSTIC 1039 if (verf_len < (4 * NFSX_UNSIGNED)) 1040 panic("nfs_getnickauth verf too small"); 1041 #endif 1042 for (nuidp = NMUIDHASH(nmp, cred->cr_uid)->lh_first; 1043 nuidp != 0; nuidp = nuidp->nu_hash.le_next) { 1044 if (nuidp->nu_cr.cr_uid == cred->cr_uid) 1045 break; 1046 } 1047 if (!nuidp || nuidp->nu_expire < time.tv_sec) 1048 return (EACCES); 1049 1050 /* 1051 * Move to the end of the lru list (end of lru == most recently used). 1052 */ 1053 TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp, nu_lru); 1054 TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp, nu_lru); 1055 1056 nickp = (u_int32_t *)malloc(2 * NFSX_UNSIGNED, M_TEMP, M_WAITOK); 1057 *nickp++ = txdr_unsigned(RPCAKN_NICKNAME); 1058 *nickp = txdr_unsigned(nuidp->nu_nickname); 1059 *auth_str = (char *)nickp; 1060 *auth_len = 2 * NFSX_UNSIGNED; 1061 1062 /* 1063 * Now we must encrypt the verifier and package it up. 1064 */ 1065 verfp = (u_int32_t *)verf_str; 1066 *verfp++ = txdr_unsigned(RPCAKN_NICKNAME); 1067 if (time.tv_sec > nuidp->nu_timestamp.tv_sec || 1068 (time.tv_sec == nuidp->nu_timestamp.tv_sec && 1069 time.tv_usec > nuidp->nu_timestamp.tv_usec)) 1070 nuidp->nu_timestamp = time; 1071 else 1072 nuidp->nu_timestamp.tv_usec++; 1073 ktvin.tv_sec = txdr_unsigned(nuidp->nu_timestamp.tv_sec); 1074 ktvin.tv_usec = txdr_unsigned(nuidp->nu_timestamp.tv_usec); 1075 1076 /* 1077 * Now encrypt the timestamp verifier in ecb mode using the session 1078 * key. 1079 */ 1080 #ifdef NFSKERB 1081 XXX 1082 #endif 1083 1084 *verfp++ = ktvout.tv_sec; 1085 *verfp++ = ktvout.tv_usec; 1086 *verfp = 0; 1087 return (0); 1088 } 1089 1090 /* 1091 * Save the current nickname in a hash list entry on the mount point. 1092 */ 1093 int 1094 nfs_savenickauth(nmp, cred, len, key, mdp, dposp, mrep) 1095 register struct nfsmount *nmp; 1096 struct ucred *cred; 1097 int len; 1098 NFSKERBKEY_T key; 1099 struct mbuf **mdp; 1100 char **dposp; 1101 struct mbuf *mrep; 1102 { 1103 register struct nfsuid *nuidp; 1104 register u_int32_t *tl; 1105 register int32_t t1; 1106 struct mbuf *md = *mdp; 1107 struct timeval ktvin, ktvout; 1108 u_int32_t nick; 1109 char *dpos = *dposp, *cp2; 1110 int deltasec, error = 0; 1111 1112 if (len == (3 * NFSX_UNSIGNED)) { 1113 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 1114 ktvin.tv_sec = *tl++; 1115 ktvin.tv_usec = *tl++; 1116 nick = fxdr_unsigned(u_int32_t, *tl); 1117 1118 /* 1119 * Decrypt the timestamp in ecb mode. 1120 */ 1121 #ifdef NFSKERB 1122 XXX 1123 #endif 1124 ktvout.tv_sec = fxdr_unsigned(long, ktvout.tv_sec); 1125 ktvout.tv_usec = fxdr_unsigned(long, ktvout.tv_usec); 1126 deltasec = time.tv_sec - ktvout.tv_sec; 1127 if (deltasec < 0) 1128 deltasec = -deltasec; 1129 /* 1130 * If ok, add it to the hash list for the mount point. 1131 */ 1132 if (deltasec <= NFS_KERBCLOCKSKEW) { 1133 if (nmp->nm_numuids < nuidhash_max) { 1134 nmp->nm_numuids++; 1135 nuidp = (struct nfsuid *) 1136 malloc(sizeof (struct nfsuid), M_NFSUID, 1137 M_WAITOK); 1138 } else { 1139 nuidp = nmp->nm_uidlruhead.tqh_first; 1140 LIST_REMOVE(nuidp, nu_hash); 1141 TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp, 1142 nu_lru); 1143 } 1144 nuidp->nu_flag = 0; 1145 nuidp->nu_cr.cr_uid = cred->cr_uid; 1146 nuidp->nu_expire = time.tv_sec + NFS_KERBTTL; 1147 nuidp->nu_timestamp = ktvout; 1148 nuidp->nu_nickname = nick; 1149 bcopy(key, nuidp->nu_key, sizeof (key)); 1150 TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp, 1151 nu_lru); 1152 LIST_INSERT_HEAD(NMUIDHASH(nmp, cred->cr_uid), 1153 nuidp, nu_hash); 1154 } 1155 } else 1156 nfsm_adv(nfsm_rndup(len)); 1157 nfsmout: 1158 *mdp = md; 1159 *dposp = dpos; 1160 return (error); 1161 } 1162 #endif /* NFS */ 1163