1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * %sccs.include.redist.c% 9 * 10 * @(#)nfs_syscalls.c 7.27 (Berkeley) 01/14/92 11 */ 12 13 #include "param.h" 14 #include "systm.h" 15 #include "kernel.h" 16 #include "file.h" 17 #include "stat.h" 18 #include "vnode.h" 19 #include "mount.h" 20 #include "proc.h" 21 #include "uio.h" 22 #include "malloc.h" 23 #include "buf.h" 24 #include "mbuf.h" 25 #include "socket.h" 26 #include "socketvar.h" 27 #include "domain.h" 28 #include "protosw.h" 29 #include "namei.h" 30 #include "netinet/in.h" 31 #include "netinet/tcp.h" 32 #ifdef ISO 33 #include "netiso/iso.h" 34 #endif 35 #include "machine/endian.h" 36 #include "rpcv2.h" 37 #include "nfsv2.h" 38 #include "nfs.h" 39 #include "nfsrvcache.h" 40 #include "nfsmount.h" 41 #include "nqnfs.h" 42 43 /* Global defs. */ 44 extern u_long nfs_prog, nfs_vers; 45 extern int (*nfsrv_procs[NFS_NPROCS])(); 46 extern struct buf nfs_bqueue; 47 extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON]; 48 extern int nfs_numasync; 49 extern time_t nqnfsstarttime; 50 extern struct nfsrv_req nsrvq_head; 51 extern struct nfsd nfsd_head; 52 extern int nqsrv_writeslack; 53 struct nfssvc_sock *nfs_udpsock, *nfs_cltpsock; 54 int nuidhash_max = NFS_MAXUIDHASH; 55 static int nfs_numnfsd = 0; 56 int nfsd_waiting = 0; 57 static int notstarted = 1; 58 static int modify_flag = 0; 59 void nfsrv_cleancache(), nfsrv_rcv(), nfsrv_wakenfsd(), nfs_sndunlock(); 60 61 #define TRUE 1 62 #define FALSE 0 63 64 static int nfs_asyncdaemon[NFS_MAXASYNCDAEMON]; 65 /* 66 * NFS server system calls 67 * getfh() lives here too, but maybe should move to kern/vfs_syscalls.c 68 */ 69 70 /* 71 * Get file handle system call 72 */ 73 getfh(p, uap, retval) 74 struct proc *p; 75 register struct args { 76 char *fname; 77 fhandle_t *fhp; 78 } *uap; 79 int *retval; 80 { 81 register struct nameidata *ndp; 82 register struct vnode *vp; 83 fhandle_t fh; 84 int error; 85 struct nameidata nd; 86 87 /* 88 * Must be super user 89 */ 90 if (error = suser(p->p_ucred, &p->p_acflag)) 91 return (error); 92 ndp = &nd; 93 ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 94 ndp->ni_segflg = UIO_USERSPACE; 95 ndp->ni_dirp = uap->fname; 96 if (error = namei(ndp, p)) 97 return (error); 98 vp = ndp->ni_vp; 99 bzero((caddr_t)&fh, sizeof(fh)); 100 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; 101 error = VFS_VPTOFH(vp, &fh.fh_fid); 102 vput(vp); 103 if (error) 104 return (error); 105 error = copyout((caddr_t)&fh, (caddr_t)uap->fhp, sizeof (fh)); 106 return (error); 107 } 108 109 static struct nfssvc_sock nfssvc_sockhead; 110 111 /* 112 * Nfs server psuedo system call for the nfsd's 113 * Based on the flag value it either: 114 * - adds a socket to the selection list 115 * - remains in the kernel as an nfsd 116 * - remains in the kernel as an nfsiod 117 */ 118 nfssvc(p, uap, retval) 119 struct proc *p; 120 register struct args { 121 int flag; 122 caddr_t argp; 123 } *uap; 124 int *retval; 125 { 126 struct nameidata nd; 127 struct file *fp; 128 struct mbuf *nam; 129 struct nfsd_args nfsdarg; 130 struct nfsd_srvargs nfsd_srvargs, *nsd = &nfsd_srvargs; 131 struct nfsd_cargs ncd; 132 struct nfsd *nfsd; 133 struct nfssvc_sock *slp; 134 struct nfsuid *nuidp, **nuh; 135 struct nfsmount *nmp; 136 int error; 137 138 /* 139 * Must be super user 140 */ 141 if (error = suser(p->p_ucred, &p->p_acflag)) 142 return (error); 143 if (nfssvc_sockhead.ns_next == NULL) { 144 nfs_udpsock = (struct nfssvc_sock *) 145 malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK); 146 bzero((caddr_t)nfs_udpsock, sizeof (struct nfssvc_sock)); 147 nfs_cltpsock = (struct nfssvc_sock *) 148 malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK); 149 bzero((caddr_t)nfs_cltpsock, sizeof (struct nfssvc_sock)); 150 nfssvc_sockhead.ns_next = nfs_udpsock; 151 nfs_udpsock->ns_next = nfs_cltpsock; 152 nfs_cltpsock->ns_next = &nfssvc_sockhead; 153 nfssvc_sockhead.ns_prev = nfs_cltpsock; 154 nfs_cltpsock->ns_prev = nfs_udpsock; 155 nfs_udpsock->ns_prev = &nfssvc_sockhead; 156 nfs_udpsock->ns_lrunext = nfs_udpsock->ns_lruprev = 157 (struct nfsuid *)nfs_udpsock; 158 nfs_cltpsock->ns_lrunext = nfs_cltpsock->ns_lruprev = 159 (struct nfsuid *)nfs_cltpsock; 160 nfsd_head.nd_next = nfsd_head.nd_prev = &nfsd_head; 161 nfsd_head.nd_flag = 0; 162 } 163 if (uap->flag & NFSSVC_BIOD) 164 error = nfssvc_iod(p); 165 else if (uap->flag & NFSSVC_MNTD) { 166 if (error = copyin(uap->argp, (caddr_t)&ncd, sizeof (ncd))) 167 return (error); 168 nd.ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 169 nd.ni_segflg = UIO_USERSPACE; 170 nd.ni_dirp = ncd.ncd_dirp; 171 if (error = namei(&nd, p)) 172 return (error); 173 if ((nd.ni_vp->v_flag & VROOT) == 0) 174 error = EINVAL; 175 nmp = VFSTONFS(nd.ni_vp->v_mount); 176 vput(nd.ni_vp); 177 if (error) 178 return (error); 179 else if (nmp->nm_flag & NFSMNT_MNTD) 180 return (0); 181 nmp->nm_flag |= NFSMNT_MNTD; 182 error = nqnfs_clientd(nmp, p->p_ucred, &ncd, uap->flag, uap->argp, p); 183 } else if (uap->flag & NFSSVC_ADDSOCK) { 184 if (error = copyin(uap->argp, (caddr_t)&nfsdarg, sizeof (nfsdarg))) 185 return (error); 186 if (error = getsock(p->p_fd, nfsdarg.sock, &fp)) 187 return (error); 188 /* 189 * Get the client address for connected sockets. 190 */ 191 if (nfsdarg.name == NULL || nfsdarg.namelen == 0) 192 nam = (struct mbuf *)0; 193 else if (error = sockargs(&nam, nfsdarg.name, nfsdarg.namelen, 194 MT_SONAME)) 195 return (error); 196 error = nfssvc_addsock(fp, nam); 197 } else { 198 if (error = copyin(uap->argp, (caddr_t)nsd, sizeof (*nsd))) 199 return (error); 200 if ((uap->flag & NFSSVC_AUTHIN) && (nfsd = nsd->nsd_nfsd) && 201 nfsd->nd_sref == nfsd->nd_slp->ns_sref) { 202 slp = nfsd->nd_slp; 203 if (slp->ns_numuids < nuidhash_max) { 204 slp->ns_numuids++; 205 nuidp = (struct nfsuid *) 206 malloc(sizeof (struct nfsuid), M_NFSUID, M_WAITOK); 207 } else 208 nuidp = (struct nfsuid *)0; 209 if (slp->ns_sref != nfsd->nd_sref) { 210 if (nuidp) 211 free((caddr_t)nuidp, M_NFSUID); 212 } else { 213 if (nuidp == (struct nfsuid *)0) { 214 nuidp = slp->ns_lruprev; 215 remque(nuidp); 216 if (nuidp->nu_hprev) 217 nuidp->nu_hprev->nu_hnext = nuidp->nu_hnext; 218 if (nuidp->nu_hnext) 219 nuidp->nu_hnext->nu_hprev = nuidp->nu_hprev; 220 } 221 nuidp->nu_cr = nsd->nsd_cr; 222 nuidp->nu_cr.cr_ref = 1; 223 nuidp->nu_uid = nsd->nsd_uid; 224 insque(nuidp, (struct nfsuid *)slp); 225 nuh = &slp->ns_uidh[NUIDHASH(nsd->nsd_uid)]; 226 if (nuidp->nu_hnext = *nuh) 227 nuidp->nu_hnext->nu_hprev = nuidp; 228 nuidp->nu_hprev = (struct nfsuid *)0; 229 *nuh = nuidp; 230 } 231 } 232 if ((uap->flag & NFSSVC_AUTHINFAIL) && (nfsd = nsd->nsd_nfsd)) 233 nfsd->nd_flag |= NFSD_AUTHFAIL; 234 error = nfssvc_nfsd(nsd, uap->argp, p); 235 } 236 if (error == EINTR || error == ERESTART) 237 error = 0; 238 return (error); 239 } 240 241 /* 242 * Adds a socket to the list for servicing by nfsds. 243 */ 244 nfssvc_addsock(fp, mynam) 245 struct file *fp; 246 struct mbuf *mynam; 247 { 248 register struct mbuf *m; 249 register int siz; 250 register struct nfssvc_sock *slp; 251 register struct socket *so; 252 struct nfssvc_sock *tslp; 253 int error, s; 254 255 so = (struct socket *)fp->f_data; 256 tslp = (struct nfssvc_sock *)0; 257 /* 258 * Add it to the list, as required. 259 */ 260 if (so->so_proto->pr_protocol == IPPROTO_UDP) { 261 tslp = nfs_udpsock; 262 if (tslp->ns_flag & SLP_VALID) { 263 m_freem(mynam); 264 return (EPERM); 265 } 266 #ifdef ISO 267 } else if (so->so_proto->pr_protocol == ISOPROTO_CLTP) { 268 tslp = nfs_cltpsock; 269 if (tslp->ns_flag & SLP_VALID) { 270 m_freem(mynam); 271 return (EPERM); 272 } 273 #endif /* ISO */ 274 } else { 275 slp = nfs_cltpsock->ns_next; 276 while (slp != &nfssvc_sockhead) { 277 if ((slp->ns_flag & SLP_VALID) == 0) { 278 tslp = slp; 279 break; 280 } 281 slp = slp->ns_next; 282 } 283 } 284 if (so->so_type == SOCK_STREAM) 285 siz = NFS_MAXPACKET + sizeof (u_long); 286 else 287 siz = NFS_MAXPACKET; 288 if (error = soreserve(so, siz, siz)) { 289 m_freem(mynam); 290 return (error); 291 } 292 293 /* 294 * Set protocol specific options { for now TCP only } and 295 * reserve some space. For datagram sockets, this can get called 296 * repeatedly for the same socket, but that isn't harmful. 297 */ 298 if (so->so_type == SOCK_STREAM) { 299 MGET(m, M_WAIT, MT_SOOPTS); 300 *mtod(m, int *) = 1; 301 m->m_len = sizeof(int); 302 sosetopt(so, SOL_SOCKET, SO_KEEPALIVE, m); 303 } 304 if (so->so_proto->pr_domain->dom_family == AF_INET && 305 so->so_proto->pr_protocol == IPPROTO_TCP) { 306 MGET(m, M_WAIT, MT_SOOPTS); 307 *mtod(m, int *) = 1; 308 m->m_len = sizeof(int); 309 sosetopt(so, IPPROTO_TCP, TCP_NODELAY, m); 310 } 311 so->so_rcv.sb_flags &= ~SB_NOINTR; 312 so->so_rcv.sb_timeo = 0; 313 so->so_snd.sb_flags &= ~SB_NOINTR; 314 so->so_snd.sb_timeo = 0; 315 if (tslp) 316 slp = tslp; 317 else { 318 slp = (struct nfssvc_sock *) 319 malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK); 320 bzero((caddr_t)slp, sizeof (struct nfssvc_sock)); 321 slp->ns_prev = nfssvc_sockhead.ns_prev; 322 slp->ns_prev->ns_next = slp; 323 slp->ns_next = &nfssvc_sockhead; 324 nfssvc_sockhead.ns_prev = slp; 325 slp->ns_lrunext = slp->ns_lruprev = (struct nfsuid *)slp; 326 } 327 slp->ns_so = so; 328 slp->ns_nam = mynam; 329 fp->f_count++; 330 slp->ns_fp = fp; 331 s = splnet(); 332 so->so_upcallarg = (caddr_t)slp; 333 so->so_upcall = nfsrv_rcv; 334 slp->ns_flag = (SLP_VALID | SLP_NEEDQ); 335 nfsd_head.nd_flag |= NFSD_CHECKSLP; 336 nfsrv_wakenfsd(slp); 337 splx(s); 338 return (0); 339 } 340 341 /* 342 * Called by nfssvc() for nfsds. Just loops around servicing rpc requests 343 * until it is killed by a signal. 344 */ 345 nfssvc_nfsd(nsd, argp, p) 346 struct nfsd_srvargs *nsd; 347 caddr_t argp; 348 struct proc *p; 349 { 350 register struct mbuf *m, *nam2; 351 register int siz; 352 register struct nfssvc_sock *slp; 353 register struct socket *so; 354 register int *solockp; 355 struct nfsd *nd = nsd->nsd_nfsd; 356 struct mbuf *mreq, *nam; 357 int error, cacherep, s; 358 int sotype; 359 360 if (nd == (struct nfsd *)0) { 361 nsd->nsd_nfsd = nd = (struct nfsd *) 362 malloc(sizeof (struct nfsd), M_NFSD, M_WAITOK); 363 bzero((caddr_t)nd, sizeof (struct nfsd)); 364 nd->nd_cr.cr_ref = 1; 365 nd->nd_procp = p; 366 s = splnet(); 367 insque(nd, &nfsd_head); 368 splx(s); 369 nfs_numnfsd++; 370 } 371 /* 372 * Loop getting rpc requests until SIGKILL. 373 */ 374 for (;;) { 375 if ((nd->nd_flag & NFSD_REQINPROG) == 0) { 376 s = splnet(); 377 while (nd->nd_slp == (struct nfssvc_sock *)0 && 378 (nfsd_head.nd_flag & NFSD_CHECKSLP) == 0) { 379 nd->nd_flag |= NFSD_WAITING; 380 nfsd_waiting++; 381 if (tsleep((caddr_t)nd, PSOCK | PCATCH, "nfsd", 0)) { 382 nfsd_waiting--; 383 splx(s); 384 goto done; 385 } 386 nfsd_waiting--; 387 } 388 if (nd->nd_slp == (struct nfssvc_sock *)0 && 389 (nfsd_head.nd_flag & NFSD_CHECKSLP)) { 390 slp = nfssvc_sockhead.ns_next; 391 while (slp != &nfssvc_sockhead) { 392 if ((slp->ns_flag & SLP_VALID) && 393 (slp->ns_flag & (SLP_NEEDQ | SLP_DISCONN))) { 394 nd->nd_slp = slp; 395 nd->nd_sref = slp->ns_sref; 396 break; 397 } 398 slp = slp->ns_next; 399 } 400 if (slp == &nfssvc_sockhead) 401 nfsd_head.nd_flag &= ~NFSD_CHECKSLP; 402 } 403 if ((slp = nd->nd_slp) == (struct nfssvc_sock *)0) { 404 splx(s); 405 continue; 406 } 407 if (slp->ns_flag & SLP_DISCONN) { 408 slp->ns_flag &= ~SLP_DISCONN; 409 (void) nfs_sndlock(&slp->ns_solock, 410 (struct nfsreq *)0); 411 if (nd->nd_sref == slp->ns_sref) 412 nfsrv_zapsock(slp, p); 413 nfs_sndunlock(&slp->ns_solock); 414 nd->nd_slp = (struct nfssvc_sock *)0; 415 splx(s); 416 continue; 417 } 418 if (slp->ns_flag & SLP_NEEDQ) { 419 slp->ns_flag &= ~SLP_NEEDQ; 420 (void) nfs_sndlock(&slp->ns_solock, 421 (struct nfsreq *)0); 422 if (nd->nd_sref == slp->ns_sref) { 423 if (slp->ns_so->so_rcv.sb_cc > 0) 424 nfsrv_rcv(slp->ns_so, (caddr_t)slp, 425 M_WAIT); 426 else if (slp->ns_so->so_type == SOCK_STREAM) 427 (void) nfsrv_getstream(slp, M_WAIT); 428 } 429 nfs_sndunlock(&slp->ns_solock); 430 } 431 error = nfsrv_dorec(slp, nd); 432 splx(s); 433 if (error) { 434 nd->nd_slp = (struct nfssvc_sock *)0; 435 continue; 436 } 437 nd->nd_flag |= NFSD_REQINPROG; 438 } else 439 slp = nd->nd_slp; 440 so = slp->ns_so; 441 sotype = so->so_type; 442 443 /* 444 * Check to see if authorization is needed. 445 */ 446 if (nd->nd_flag & NFSD_NEEDAUTH) { 447 nd->nd_flag &= ~NFSD_NEEDAUTH; 448 nsd->nsd_uid = nd->nd_cr.cr_uid; 449 nsd->nsd_haddr = 450 mtod(slp->ns_nam, struct sockaddr_in *)->sin_addr.s_addr; 451 nsd->nsd_authlen = nd->nd_authlen; 452 (void) copyout(nd->nd_authstr, nsd->nsd_authstr, 453 nd->nd_authlen); 454 (void) copyout((caddr_t)nsd, argp, sizeof (*nsd)); 455 return (ENEEDAUTH); 456 } 457 if (so->so_proto->pr_flags & PR_CONNREQUIRED) 458 solockp = &slp->ns_solock; 459 else 460 solockp = (int *)0; 461 nd->nd_repstat = 0; 462 /* 463 * nam == nam2 for connectionless protocols such as UDP 464 * nam2 == NULL for connection based protocols to disable 465 * recent request caching. 466 */ 467 nam2 = nd->nd_nam; 468 469 if (nam2) { 470 nam = nam2; 471 cacherep = nfsrv_getcache(nam2, nd, &mreq); 472 } else { 473 nam = slp->ns_nam; 474 cacherep = RC_DOIT; 475 } 476 477 /* 478 * Check for just starting up for NQNFS and send 479 * fake "try again later" replies to the NQNFS clients. 480 */ 481 if (notstarted && nqnfsstarttime <= time.tv_sec) { 482 if (modify_flag) { 483 nqnfsstarttime = time.tv_sec + nqsrv_writeslack; 484 modify_flag = 0; 485 } else 486 notstarted = 0; 487 } 488 if (notstarted) { 489 if (nd->nd_nqlflag == NQL_NOVAL) 490 cacherep = RC_DROPIT; 491 else if (nd->nd_procnum != NFSPROC_WRITE) { 492 nd->nd_procnum = NFSPROC_NOOP; 493 nd->nd_repstat = NQNFS_TRYLATER; 494 cacherep = RC_DOIT; 495 } else 496 modify_flag = 1; 497 } else if (nd->nd_flag & NFSD_AUTHFAIL) { 498 nd->nd_flag &= ~NFSD_AUTHFAIL; 499 nd->nd_procnum = NFSPROC_NOOP; 500 nd->nd_repstat = NQNFS_AUTHERR; 501 cacherep = RC_DOIT; 502 } 503 504 switch (cacherep) { 505 case RC_DOIT: 506 error = (*(nfsrv_procs[nd->nd_procnum]))(nd, 507 nd->nd_mrep, nd->nd_md, nd->nd_dpos, &nd->nd_cr, 508 nam, &mreq); 509 if (error) { 510 if (nd->nd_procnum != NQNFSPROC_VACATED) 511 nfsstats.srv_errs++; 512 if (nam2) { 513 nfsrv_updatecache(nam2, nd, FALSE, mreq); 514 m_freem(nam2); 515 } 516 break; 517 } 518 nfsstats.srvrpccnt[nd->nd_procnum]++; 519 if (nam2) 520 nfsrv_updatecache(nam2, nd, TRUE, mreq); 521 nd->nd_mrep = (struct mbuf *)0; 522 case RC_REPLY: 523 m = mreq; 524 siz = 0; 525 while (m) { 526 siz += m->m_len; 527 m = m->m_next; 528 } 529 if (siz <= 0 || siz > NFS_MAXPACKET) { 530 printf("mbuf siz=%d\n",siz); 531 panic("Bad nfs svc reply"); 532 } 533 m = mreq; 534 m->m_pkthdr.len = siz; 535 m->m_pkthdr.rcvif = (struct ifnet *)0; 536 /* 537 * For stream protocols, prepend a Sun RPC 538 * Record Mark. 539 */ 540 if (sotype == SOCK_STREAM) { 541 M_PREPEND(m, NFSX_UNSIGNED, M_WAIT); 542 *mtod(m, u_long *) = htonl(0x80000000 | siz); 543 } 544 if (solockp) 545 (void) nfs_sndlock(solockp, (struct nfsreq *)0); 546 if (nd->nd_sref == slp->ns_sref) 547 error = nfs_send(so, nam2, m, (struct nfsreq *)0); 548 else { 549 error = EPIPE; 550 m_freem(m); 551 } 552 if (nam2) 553 MFREE(nam2, m); 554 if (nd->nd_mrep) 555 m_freem(nd->nd_mrep); 556 if (error == EPIPE) 557 nfsrv_zapsock(slp, p); 558 if (solockp) 559 nfs_sndunlock(solockp); 560 if (error == EINTR || error == ERESTART) 561 goto done; 562 break; 563 case RC_DROPIT: 564 m_freem(nd->nd_mrep); 565 m_freem(nam2); 566 break; 567 }; 568 nd->nd_flag &= ~NFSD_REQINPROG; 569 nd->nd_slp = (struct nfssvc_sock *)0; 570 } 571 done: 572 s = splnet(); 573 remque(nd); 574 splx(s); 575 free((caddr_t)nd, M_NFSD); 576 nsd->nsd_nfsd = (struct nfsd *)0; 577 if (--nfs_numnfsd == 0) { 578 slp = nfssvc_sockhead.ns_next; 579 while (slp != &nfssvc_sockhead) { 580 if (slp->ns_flag & SLP_VALID) 581 nfsrv_zapsock(slp, p); 582 slp = slp->ns_next; 583 } 584 nfsrv_cleancache(); /* And clear out server cache */ 585 } 586 return (error); 587 } 588 589 /* 590 * Asynchronous I/O daemons for client nfs. 591 * These babies just pretend to be disk interrupt service routines. 592 * They are mainly here for read ahead/write behind. 593 * Never returns unless it fails or gets killed. 594 */ 595 nfssvc_iod(p) 596 struct proc *p; 597 { 598 register struct buf *bp, *dp; 599 register int i, myiod; 600 int error = 0; 601 602 /* 603 * Assign my position or return error if too many already running 604 */ 605 myiod = -1; 606 for (i = 0; i < NFS_MAXASYNCDAEMON; i++) 607 if (nfs_asyncdaemon[i] == 0) { 608 nfs_asyncdaemon[i]++; 609 myiod = i; 610 break; 611 } 612 if (myiod == -1) 613 return (EBUSY); 614 nfs_numasync++; 615 dp = &nfs_bqueue; 616 /* 617 * Just loop around doin our stuff until SIGKILL 618 */ 619 for (;;) { 620 while (dp->b_actf == NULL && error == 0) { 621 nfs_iodwant[myiod] = p; 622 error = tsleep((caddr_t)&nfs_iodwant[myiod], 623 PWAIT | PCATCH, "nfsidl", 0); 624 nfs_iodwant[myiod] = (struct proc *)0; 625 } 626 while (dp->b_actf != NULL) { 627 /* Take one off the end of the list */ 628 bp = dp->b_actl; 629 if (bp->b_actl == dp) { 630 dp->b_actf = dp->b_actl = (struct buf *)0; 631 } else { 632 dp->b_actl = bp->b_actl; 633 bp->b_actl->b_actf = dp; 634 } 635 (void) nfs_doio(bp, (struct proc *)0); 636 } 637 if (error) { 638 nfs_asyncdaemon[myiod] = 0; 639 nfs_numasync--; 640 return (error); 641 } 642 } 643 } 644 645 /* 646 * Shut down a socket associated with an nfssvc_sock structure. 647 * Should be called with the send lock set, if required. 648 * The trick here is to increment the sref at the start, so that the nfsds 649 * will stop using it and clear ns_flag at the end so that it will not be 650 * reassigned during cleanup. 651 */ 652 nfsrv_zapsock(slp, p) 653 register struct nfssvc_sock *slp; 654 struct proc *p; 655 { 656 register struct nfsuid *nuidp, *onuidp; 657 register int i; 658 struct socket *so; 659 struct file *fp; 660 struct mbuf *m; 661 662 if (fp = slp->ns_fp) { 663 slp->ns_fp = (struct file *)0; 664 slp->ns_sref++; 665 so = slp->ns_so; 666 soshutdown(so, 2); 667 closef(fp, p); 668 if (slp->ns_nam) 669 MFREE(slp->ns_nam, m); 670 m_freem(slp->ns_raw); 671 m_freem(slp->ns_rec); 672 nuidp = slp->ns_lrunext; 673 while (nuidp != (struct nfsuid *)slp) { 674 onuidp = nuidp; 675 nuidp = nuidp->nu_lrunext; 676 free((caddr_t)onuidp, M_NFSUID); 677 } 678 slp->ns_lrunext = slp->ns_lruprev = (struct nfsuid *)slp; 679 for (i = 0; i < NUIDHASHSIZ; i++) 680 slp->ns_uidh[i] = (struct nfsuid *)0; 681 slp->ns_flag = 0; 682 } 683 } 684 685 /* 686 * Get an authorization string for the uid by having the mount_nfs sitting 687 * on this mount point porpous out of the kernel and do it. 688 */ 689 nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len) 690 register struct nfsmount *nmp; 691 struct nfsreq *rep; 692 struct ucred *cred; 693 int *auth_type; 694 char **auth_str; 695 int *auth_len; 696 { 697 int error = 0; 698 699 while ((nmp->nm_flag & NFSMNT_WAITAUTH) == 0) { 700 nmp->nm_flag |= NFSMNT_WANTAUTH; 701 (void) tsleep((caddr_t)&nmp->nm_authtype, PSOCK, 702 "nfsauth1", 2 * hz); 703 if (error = nfs_sigintr(nmp, rep, rep->r_procp)) { 704 nmp->nm_flag &= ~NFSMNT_WANTAUTH; 705 return (error); 706 } 707 } 708 nmp->nm_flag &= ~(NFSMNT_WAITAUTH | NFSMNT_WANTAUTH); 709 nmp->nm_authstr = *auth_str = (char *)malloc(RPCAUTH_MAXSIZ, M_TEMP, M_WAITOK); 710 nmp->nm_authuid = cred->cr_uid; 711 wakeup((caddr_t)&nmp->nm_authstr); 712 713 /* 714 * And wait for mount_nfs to do its stuff. 715 */ 716 while ((nmp->nm_flag & NFSMNT_HASAUTH) == 0 && error == 0) { 717 (void) tsleep((caddr_t)&nmp->nm_authlen, PSOCK, 718 "nfsauth2", 2 * hz); 719 error = nfs_sigintr(nmp, rep, rep->r_procp); 720 } 721 if (nmp->nm_flag & NFSMNT_AUTHERR) { 722 nmp->nm_flag &= ~NFSMNT_AUTHERR; 723 error = EAUTH; 724 } 725 if (error) 726 free((caddr_t)*auth_str, M_TEMP); 727 else { 728 *auth_type = nmp->nm_authtype; 729 *auth_len = nmp->nm_authlen; 730 } 731 nmp->nm_flag &= ~NFSMNT_HASAUTH; 732 nmp->nm_flag |= NFSMNT_WAITAUTH; 733 if (nmp->nm_flag & NFSMNT_WANTAUTH) { 734 nmp->nm_flag &= ~NFSMNT_WANTAUTH; 735 wakeup((caddr_t)&nmp->nm_authtype); 736 } 737 return (error); 738 } 739