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