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