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