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