|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ ! 23: /* ! 24: * Copyright (c) 1989, 1993 ! 25: * The Regents of the University of California. All rights reserved. ! 26: * ! 27: * This code is derived from software contributed to Berkeley by ! 28: * Rick Macklem at The University of Guelph. ! 29: * ! 30: * Redistribution and use in source and binary forms, with or without ! 31: * modification, are permitted provided that the following conditions ! 32: * are met: ! 33: * 1. Redistributions of source code must retain the above copyright ! 34: * notice, this list of conditions and the following disclaimer. ! 35: * 2. Redistributions in binary form must reproduce the above copyright ! 36: * notice, this list of conditions and the following disclaimer in the ! 37: * documentation and/or other materials provided with the distribution. ! 38: * 3. All advertising materials mentioning features or use of this software ! 39: * must display the following acknowledgement: ! 40: * This product includes software developed by the University of ! 41: * California, Berkeley and its contributors. ! 42: * 4. Neither the name of the University nor the names of its contributors ! 43: * may be used to endorse or promote products derived from this software ! 44: * without specific prior written permission. ! 45: * ! 46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 56: * SUCH DAMAGE. ! 57: * ! 58: * @(#)nfs_syscalls.c 8.5 (Berkeley) 3/30/95 ! 59: * FreeBSD-Id: nfs_syscalls.c,v 1.32 1997/11/07 08:53:25 phk Exp $ ! 60: */ ! 61: ! 62: #include <sys/param.h> ! 63: #include <sys/systm.h> ! 64: /* XXX CSM 11/25/97 FreeBSD's generated syscall prototypes */ ! 65: #ifdef notyet ! 66: #include <sys/sysproto.h> ! 67: #endif ! 68: #include <sys/kernel.h> ! 69: #include <sys/file.h> ! 70: #include <sys/filedesc.h> ! 71: #include <sys/stat.h> ! 72: #include <sys/vnode.h> ! 73: #include <sys/mount.h> ! 74: #include <sys/proc.h> ! 75: #include <sys/sysctl.h> ! 76: #include <sys/uio.h> ! 77: #include <sys/malloc.h> ! 78: #include <sys/buf.h> ! 79: #include <sys/mbuf.h> ! 80: #include <sys/socket.h> ! 81: #include <sys/socketvar.h> ! 82: #include <sys/domain.h> ! 83: #include <sys/protosw.h> ! 84: #include <sys/namei.h> ! 85: #include <sys/syslog.h> ! 86: #include <sys/user.h> ! 87: #include <machine/spl.h> ! 88: ! 89: #include <netinet/in.h> ! 90: #include <netinet/tcp.h> ! 91: #if ISO ! 92: #include <netiso/iso.h> ! 93: #endif ! 94: #include <nfs/xdr_subs.h> ! 95: #include <nfs/rpcv2.h> ! 96: #include <nfs/nfsproto.h> ! 97: #include <nfs/nfs.h> ! 98: #include <nfs/nfsm_subs.h> ! 99: #include <nfs/nfsrvcache.h> ! 100: #include <nfs/nfsmount.h> ! 101: #include <nfs/nfsnode.h> ! 102: #include <nfs/nqnfs.h> ! 103: #include <nfs/nfsrtt.h> ! 104: ! 105: ! 106: /* Global defs. */ ! 107: extern int (*nfsrv3_procs[NFS_NPROCS]) __P((struct nfsrv_descript *nd, ! 108: struct nfssvc_sock *slp, ! 109: struct proc *procp, ! 110: struct mbuf **mreqp)); ! 111: extern int nfs_numasync; ! 112: extern time_t nqnfsstarttime; ! 113: extern int nqsrv_writeslack; ! 114: extern int nfsrtton; ! 115: extern struct nfsstats nfsstats; ! 116: extern int nfsrvw_procrastinate; ! 117: extern int nfsrvw_procrastinate_v3; ! 118: struct nfssvc_sock *nfs_udpsock, *nfs_cltpsock; ! 119: static int nuidhash_max = NFS_MAXUIDHASH; ! 120: ! 121: static void nfsrv_zapsock __P((struct nfssvc_sock *slp)); ! 122: static int nfssvc_iod __P((struct proc *)); ! 123: ! 124: #define TRUE 1 ! 125: #define FALSE 0 ! 126: ! 127: static int nfs_asyncdaemon[NFS_MAXASYNCDAEMON]; ! 128: ! 129: #ifndef NFS_NOSERVER ! 130: int nfsd_waiting = 0; ! 131: static struct nfsdrt nfsdrt; ! 132: static int nfs_numnfsd = 0; ! 133: static int notstarted = 1; ! 134: static int modify_flag = 0; ! 135: static void nfsd_rt __P((int sotype, struct nfsrv_descript *nd, ! 136: int cacherep)); ! 137: static int nfssvc_addsock __P((struct file *, struct mbuf *, ! 138: struct proc *)); ! 139: static int nfssvc_nfsd __P((struct nfsd_srvargs *,caddr_t,struct proc *)); ! 140: ! 141: static int nfs_privport = 0; ! 142: /* XXX CSM 11/25/97 Upgrade sysctl.h someday */ ! 143: #ifdef notyet ! 144: SYSCTL_INT(_vfs_nfs, NFS_NFSPRIVPORT, nfs_privport, CTLFLAG_RW, &nfs_privport, 0, ""); ! 145: SYSCTL_INT(_vfs_nfs, OID_AUTO, gatherdelay, CTLFLAG_RW, &nfsrvw_procrastinate, 0, ""); ! 146: SYSCTL_INT(_vfs_nfs, OID_AUTO, gatherdelay_v3, CTLFLAG_RW, &nfsrvw_procrastinate_v3, 0, ""); ! 147: #endif ! 148: ! 149: /* ! 150: * NFS server system calls ! 151: * getfh() lives here too, but maybe should move to kern/vfs_syscalls.c ! 152: */ ! 153: ! 154: /* ! 155: * Get file handle system call ! 156: */ ! 157: #ifndef _SYS_SYSPROTO_H_ ! 158: struct getfh_args { ! 159: char *fname; ! 160: fhandle_t *fhp; ! 161: }; ! 162: #endif ! 163: int ! 164: getfh(p, uap) ! 165: struct proc *p; ! 166: register struct getfh_args *uap; ! 167: { ! 168: register struct vnode *vp; ! 169: fhandle_t fh; ! 170: int error; ! 171: struct nameidata nd; ! 172: ! 173: /* ! 174: * Must be super user ! 175: */ ! 176: error = suser(p->p_ucred, &p->p_acflag); ! 177: if(error) ! 178: return (error); ! 179: NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); ! 180: error = namei(&nd); ! 181: if (error) ! 182: return (error); ! 183: vp = nd.ni_vp; ! 184: bzero((caddr_t)&fh, sizeof(fh)); ! 185: fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; ! 186: error = VFS_VPTOFH(vp, &fh.fh_fid); ! 187: vput(vp); ! 188: if (error) ! 189: return (error); ! 190: error = copyout((caddr_t)&fh, (caddr_t)uap->fhp, sizeof (fh)); ! 191: return (error); ! 192: } ! 193: ! 194: #endif /* NFS_NOSERVER */ ! 195: /* ! 196: * Nfs server psuedo system call for the nfsd's ! 197: * Based on the flag value it either: ! 198: * - adds a socket to the selection list ! 199: * - remains in the kernel as an nfsd ! 200: * - remains in the kernel as an nfsiod ! 201: */ ! 202: #ifndef _SYS_SYSPROTO_H_ ! 203: struct nfssvc_args { ! 204: int flag; ! 205: caddr_t argp; ! 206: }; ! 207: #endif ! 208: int ! 209: nfssvc(p, uap) ! 210: struct proc *p; ! 211: register struct nfssvc_args *uap; ! 212: { ! 213: #ifndef NFS_NOSERVER ! 214: struct nameidata nd; ! 215: struct file *fp; ! 216: struct mbuf *nam; ! 217: struct nfsd_args nfsdarg; ! 218: struct nfsd_srvargs nfsd_srvargs, *nsd = &nfsd_srvargs; ! 219: struct nfsd_cargs ncd; ! 220: struct nfsd *nfsd; ! 221: struct nfssvc_sock *slp; ! 222: struct nfsuid *nuidp; ! 223: struct nfsmount *nmp; ! 224: #endif /* NFS_NOSERVER */ ! 225: int error; ! 226: ! 227: /* ! 228: * Must be super user ! 229: */ ! 230: error = suser(p->p_ucred, &p->p_acflag); ! 231: if(error) ! 232: return (error); ! 233: while (nfssvc_sockhead_flag & SLP_INIT) { ! 234: nfssvc_sockhead_flag |= SLP_WANTINIT; ! 235: (void) tsleep((caddr_t)&nfssvc_sockhead, PSOCK, "nfsd init", 0); ! 236: } ! 237: if (uap->flag & NFSSVC_BIOD) ! 238: error = nfssvc_iod(p); ! 239: #ifdef NFS_NOSERVER ! 240: else ! 241: error = ENXIO; ! 242: #else /* !NFS_NOSERVER */ ! 243: else if (uap->flag & NFSSVC_MNTD) { ! 244: error = copyin(uap->argp, (caddr_t)&ncd, sizeof (ncd)); ! 245: if (error) ! 246: return (error); ! 247: NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, ! 248: ncd.ncd_dirp, p); ! 249: error = namei(&nd); ! 250: if (error) ! 251: return (error); ! 252: if ((nd.ni_vp->v_flag & VROOT) == 0) ! 253: error = EINVAL; ! 254: nmp = VFSTONFS(nd.ni_vp->v_mount); ! 255: vput(nd.ni_vp); ! 256: if (error) ! 257: return (error); ! 258: if ((nmp->nm_flag & NFSMNT_MNTD) && ! 259: (uap->flag & NFSSVC_GOTAUTH) == 0) ! 260: return (0); ! 261: nmp->nm_flag |= NFSMNT_MNTD; ! 262: error = nqnfs_clientd(nmp, p->p_ucred, &ncd, uap->flag, ! 263: uap->argp, p); ! 264: } else if (uap->flag & NFSSVC_ADDSOCK) { ! 265: error = copyin(uap->argp, (caddr_t)&nfsdarg, sizeof(nfsdarg)); ! 266: if (error) ! 267: return (error); ! 268: error = getsock(p->p_fd, nfsdarg.sock, &fp); ! 269: if (error) ! 270: return (error); ! 271: /* ! 272: * Get the client address for connected sockets. ! 273: */ ! 274: if (nfsdarg.name == NULL || nfsdarg.namelen == 0) ! 275: nam = (struct mbuf *)0; ! 276: else { ! 277: error = sockargs(&nam, nfsdarg.name, nfsdarg.namelen, ! 278: MT_SONAME); ! 279: if (error) ! 280: return (error); ! 281: } ! 282: error = nfssvc_addsock(fp, nam, p); ! 283: } else { ! 284: error = copyin(uap->argp, (caddr_t)nsd, sizeof (*nsd)); ! 285: if (error) ! 286: return (error); ! 287: if ((uap->flag & NFSSVC_AUTHIN) && ((nfsd = nsd->nsd_nfsd)) && ! 288: (nfsd->nfsd_slp->ns_flag & SLP_VALID)) { ! 289: slp = nfsd->nfsd_slp; ! 290: ! 291: /* ! 292: * First check to see if another nfsd has already ! 293: * added this credential. ! 294: */ ! 295: for (nuidp = NUIDHASH(slp,nsd->nsd_cr.cr_uid)->lh_first; ! 296: nuidp != 0; nuidp = nuidp->nu_hash.le_next) { ! 297: if (nuidp->nu_cr.cr_uid == nsd->nsd_cr.cr_uid && ! 298: (!nfsd->nfsd_nd->nd_nam2 || ! 299: netaddr_match(NU_NETFAM(nuidp), ! 300: &nuidp->nu_haddr, nfsd->nfsd_nd->nd_nam2))) ! 301: break; ! 302: } ! 303: if (nuidp) { ! 304: nfsrv_setcred(&nuidp->nu_cr,&nfsd->nfsd_nd->nd_cr); ! 305: nfsd->nfsd_nd->nd_flag |= ND_KERBFULL; ! 306: } else { ! 307: /* ! 308: * Nope, so we will. ! 309: */ ! 310: if (slp->ns_numuids < nuidhash_max) { ! 311: slp->ns_numuids++; ! 312: nuidp = (struct nfsuid *) ! 313: _MALLOC_ZONE(sizeof (struct nfsuid), ! 314: M_NFSUID, M_WAITOK); ! 315: } else ! 316: nuidp = (struct nfsuid *)0; ! 317: if ((slp->ns_flag & SLP_VALID) == 0) { ! 318: if (nuidp) ! 319: _FREE_ZONE((caddr_t)nuidp, ! 320: sizeof (struct nfsuid), M_NFSUID); ! 321: } else { ! 322: if (nuidp == (struct nfsuid *)0) { ! 323: nuidp = slp->ns_uidlruhead.tqh_first; ! 324: LIST_REMOVE(nuidp, nu_hash); ! 325: TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp, ! 326: nu_lru); ! 327: if (nuidp->nu_flag & NU_NAM) ! 328: m_freem(nuidp->nu_nam); ! 329: } ! 330: nuidp->nu_flag = 0; ! 331: nuidp->nu_cr = nsd->nsd_cr; ! 332: if (nuidp->nu_cr.cr_ngroups > NGROUPS) ! 333: nuidp->nu_cr.cr_ngroups = NGROUPS; ! 334: nuidp->nu_cr.cr_ref = 1; ! 335: nuidp->nu_timestamp = nsd->nsd_timestamp; ! 336: nuidp->nu_expire = time.tv_sec + nsd->nsd_ttl; ! 337: /* ! 338: * and save the session key in nu_key. ! 339: */ ! 340: bcopy(nsd->nsd_key, nuidp->nu_key, ! 341: sizeof (nsd->nsd_key)); ! 342: if (nfsd->nfsd_nd->nd_nam2) { ! 343: struct sockaddr_in *saddr; ! 344: ! 345: saddr = mtod(nfsd->nfsd_nd->nd_nam2, ! 346: struct sockaddr_in *); ! 347: switch (saddr->sin_family) { ! 348: case AF_INET: ! 349: nuidp->nu_flag |= NU_INETADDR; ! 350: nuidp->nu_inetaddr = ! 351: saddr->sin_addr.s_addr; ! 352: break; ! 353: case AF_ISO: ! 354: default: ! 355: nuidp->nu_flag |= NU_NAM; ! 356: nuidp->nu_nam = m_copym( ! 357: nfsd->nfsd_nd->nd_nam2, 0, ! 358: M_COPYALL, M_WAIT); ! 359: break; ! 360: }; ! 361: } ! 362: TAILQ_INSERT_TAIL(&slp->ns_uidlruhead, nuidp, ! 363: nu_lru); ! 364: LIST_INSERT_HEAD(NUIDHASH(slp, nsd->nsd_uid), ! 365: nuidp, nu_hash); ! 366: nfsrv_setcred(&nuidp->nu_cr, ! 367: &nfsd->nfsd_nd->nd_cr); ! 368: nfsd->nfsd_nd->nd_flag |= ND_KERBFULL; ! 369: } ! 370: } ! 371: } ! 372: if ((uap->flag & NFSSVC_AUTHINFAIL) && (nfsd = nsd->nsd_nfsd)) ! 373: nfsd->nfsd_flag |= NFSD_AUTHFAIL; ! 374: error = nfssvc_nfsd(nsd, uap->argp, p); ! 375: } ! 376: #endif /* NFS_NOSERVER */ ! 377: if (error == EINTR || error == ERESTART) ! 378: error = 0; ! 379: return (error); ! 380: } ! 381: ! 382: #ifndef NFS_NOSERVER ! 383: /* ! 384: * Adds a socket to the list for servicing by nfsds. ! 385: */ ! 386: static int ! 387: nfssvc_addsock(fp, mynam, p) ! 388: struct file *fp; ! 389: struct mbuf *mynam; ! 390: struct proc *p; ! 391: { ! 392: register struct mbuf *m; ! 393: register int siz; ! 394: register struct nfssvc_sock *slp; ! 395: register struct socket *so; ! 396: struct nfssvc_sock *tslp; ! 397: int error, s; ! 398: ! 399: so = (struct socket *)fp->f_data; ! 400: tslp = (struct nfssvc_sock *)0; ! 401: /* ! 402: * Add it to the list, as required. ! 403: */ ! 404: if (so->so_proto->pr_protocol == IPPROTO_UDP) { ! 405: tslp = nfs_udpsock; ! 406: if (tslp->ns_flag & SLP_VALID) { ! 407: m_freem(mynam); ! 408: return (EPERM); ! 409: } ! 410: #if ISO ! 411: } else if (so->so_proto->pr_protocol == ISOPROTO_CLTP) { ! 412: tslp = nfs_cltpsock; ! 413: if (tslp->ns_flag & SLP_VALID) { ! 414: m_freem(mynam); ! 415: return (EPERM); ! 416: } ! 417: #endif /* ISO */ ! 418: } ! 419: if (so->so_type == SOCK_STREAM) ! 420: siz = NFS_MAXPACKET + sizeof (u_long); ! 421: else ! 422: siz = NFS_MAXPACKET; ! 423: error = soreserve(so, siz, siz); ! 424: if (error) { ! 425: m_freem(mynam); ! 426: return (error); ! 427: } ! 428: ! 429: /* ! 430: * Set protocol specific options { for now TCP only } and ! 431: * reserve some space. For datagram sockets, this can get called ! 432: * repeatedly for the same socket, but that isn't harmful. ! 433: */ ! 434: if (so->so_type == SOCK_STREAM) { ! 435: struct sockopt sopt; ! 436: int val; ! 437: ! 438: bzero(&sopt, sizeof sopt); ! 439: sopt.sopt_level = SOL_SOCKET; ! 440: sopt.sopt_name = SO_KEEPALIVE; ! 441: sopt.sopt_val = &val; ! 442: sopt.sopt_valsize = sizeof val; ! 443: val = 1; ! 444: sosetopt(so, &sopt); ! 445: } ! 446: if (so->so_proto->pr_domain->dom_family == AF_INET && ! 447: so->so_proto->pr_protocol == IPPROTO_TCP) { ! 448: struct sockopt sopt; ! 449: int val; ! 450: ! 451: bzero(&sopt, sizeof sopt); ! 452: sopt.sopt_level = IPPROTO_TCP; ! 453: sopt.sopt_name = TCP_NODELAY; ! 454: sopt.sopt_val = &val; ! 455: sopt.sopt_valsize = sizeof val; ! 456: val = 1; ! 457: sosetopt(so, &sopt); ! 458: } ! 459: ! 460: so->so_rcv.sb_flags &= ~SB_NOINTR; ! 461: so->so_rcv.sb_timeo = 0; ! 462: so->so_snd.sb_flags &= ~SB_NOINTR; ! 463: so->so_snd.sb_timeo = 0; ! 464: if (tslp) ! 465: slp = tslp; ! 466: else { ! 467: MALLOC(slp, struct nfssvc_sock *, sizeof(struct nfssvc_sock), ! 468: M_NFSSVC, M_WAITOK); ! 469: bzero((caddr_t)slp, sizeof (struct nfssvc_sock)); ! 470: TAILQ_INIT(&slp->ns_uidlruhead); ! 471: TAILQ_INSERT_TAIL(&nfssvc_sockhead, slp, ns_chain); ! 472: } ! 473: slp->ns_so = so; ! 474: slp->ns_nam = mynam; ! 475: if (++fp->f_count <= 0) ! 476: panic("nfssvc_addsock f_count"); ! 477: slp->ns_fp = fp; ! 478: s = splnet(); ! 479: so->so_upcallarg = (caddr_t)slp; ! 480: so->so_upcall = nfsrv_rcv; ! 481: so->so_rcv.sb_flags |= SB_UPCALL; /* required for freebsd merge */ ! 482: slp->ns_flag = (SLP_VALID | SLP_NEEDQ); ! 483: nfsrv_wakenfsd(slp); ! 484: splx(s); ! 485: return (0); ! 486: } ! 487: ! 488: /* ! 489: * Called by nfssvc() for nfsds. Just loops around servicing rpc requests ! 490: * until it is killed by a signal. ! 491: */ ! 492: static int ! 493: nfssvc_nfsd(nsd, argp, p) ! 494: struct nfsd_srvargs *nsd; ! 495: caddr_t argp; ! 496: struct proc *p; ! 497: { ! 498: register struct mbuf *m; ! 499: register int siz; ! 500: register struct nfssvc_sock *slp; ! 501: register struct socket *so; ! 502: register int *solockp; ! 503: struct nfsd *nfsd = nsd->nsd_nfsd; ! 504: struct nfsrv_descript *nd = NULL; ! 505: struct mbuf *mreq; ! 506: int error = 0, cacherep, s, sotype, writes_todo; ! 507: int procrastinate; ! 508: u_quad_t cur_usec; ! 509: extern void nfs_aio_thread_init(); ! 510: ! 511: #ifndef nolint ! 512: cacherep = RC_DOIT; ! 513: writes_todo = 0; ! 514: #endif ! 515: s = splnet(); ! 516: if (nfsd == (struct nfsd *)0) { ! 517: MALLOC(nfsd, struct nfsd *, sizeof(struct nfsd), M_NFSD, M_WAITOK); ! 518: nsd->nsd_nfsd = nfsd; ! 519: bzero((caddr_t)nfsd, sizeof (struct nfsd)); ! 520: nfsd->nfsd_procp = p; ! 521: TAILQ_INSERT_TAIL(&nfsd_head, nfsd, nfsd_chain); ! 522: nfs_numnfsd++; ! 523: nfs_aio_thread_init(); ! 524: } ! 525: /* ! 526: * Loop getting rpc requests until SIGKILL. ! 527: */ ! 528: for (;;) { ! 529: if ((nfsd->nfsd_flag & NFSD_REQINPROG) == 0) { ! 530: while (nfsd->nfsd_slp == (struct nfssvc_sock *)0 && ! 531: (nfsd_head_flag & NFSD_CHECKSLP) == 0) { ! 532: nfsd->nfsd_flag |= NFSD_WAITING; ! 533: nfsd_waiting++; ! 534: error = tsleep((caddr_t)nfsd, PSOCK | PCATCH, ! 535: "nfsd", 0); ! 536: nfsd_waiting--; ! 537: if (error) ! 538: goto done; ! 539: } ! 540: if (nfsd->nfsd_slp == (struct nfssvc_sock *)0 && ! 541: (nfsd_head_flag & NFSD_CHECKSLP) != 0) { ! 542: for (slp = nfssvc_sockhead.tqh_first; slp != 0; ! 543: slp = slp->ns_chain.tqe_next) { ! 544: if ((slp->ns_flag & (SLP_VALID | SLP_DOREC)) ! 545: == (SLP_VALID | SLP_DOREC)) { ! 546: slp->ns_flag &= ~SLP_DOREC; ! 547: slp->ns_sref++; ! 548: nfsd->nfsd_slp = slp; ! 549: break; ! 550: } ! 551: } ! 552: if (slp == 0) ! 553: nfsd_head_flag &= ~NFSD_CHECKSLP; ! 554: } ! 555: if ((slp = nfsd->nfsd_slp) == (struct nfssvc_sock *)0) ! 556: continue; ! 557: if (slp->ns_flag & SLP_VALID) { ! 558: if (slp->ns_flag & SLP_DISCONN) ! 559: nfsrv_zapsock(slp); ! 560: else if (slp->ns_flag & SLP_NEEDQ) { ! 561: slp->ns_flag &= ~SLP_NEEDQ; ! 562: (void) nfs_sndlock(&slp->ns_solock, ! 563: (struct nfsreq *)0); ! 564: nfsrv_rcv(slp->ns_so, (caddr_t)slp, ! 565: M_WAIT); ! 566: nfs_sndunlock(&slp->ns_solock); ! 567: } ! 568: error = nfsrv_dorec(slp, nfsd, &nd); ! 569: cur_usec = (u_quad_t)time.tv_sec * 1000000 + ! 570: (u_quad_t)time.tv_usec; ! 571: if (error && slp->ns_tq.lh_first && ! 572: slp->ns_tq.lh_first->nd_time <= cur_usec) { ! 573: error = 0; ! 574: cacherep = RC_DOIT; ! 575: writes_todo = 1; ! 576: } else ! 577: writes_todo = 0; ! 578: nfsd->nfsd_flag |= NFSD_REQINPROG; ! 579: } ! 580: } else { ! 581: error = 0; ! 582: slp = nfsd->nfsd_slp; ! 583: } ! 584: if (error || (slp->ns_flag & SLP_VALID) == 0) { ! 585: if (nd) { ! 586: _FREE_ZONE((caddr_t)nd, ! 587: sizeof *nd, M_NFSRVDESC); ! 588: nd = NULL; ! 589: } ! 590: nfsd->nfsd_slp = (struct nfssvc_sock *)0; ! 591: nfsd->nfsd_flag &= ~NFSD_REQINPROG; ! 592: nfsrv_slpderef(slp); ! 593: continue; ! 594: } ! 595: splx(s); ! 596: so = slp->ns_so; ! 597: sotype = so->so_type; ! 598: if (so->so_proto->pr_flags & PR_CONNREQUIRED) ! 599: solockp = &slp->ns_solock; ! 600: else ! 601: solockp = (int *)0; ! 602: if (nd) { ! 603: nd->nd_starttime = time; ! 604: if (nd->nd_nam2) ! 605: nd->nd_nam = nd->nd_nam2; ! 606: else ! 607: nd->nd_nam = slp->ns_nam; ! 608: ! 609: /* ! 610: * Check to see if authorization is needed. ! 611: */ ! 612: if (nfsd->nfsd_flag & NFSD_NEEDAUTH) { ! 613: nfsd->nfsd_flag &= ~NFSD_NEEDAUTH; ! 614: nsd->nsd_haddr = mtod(nd->nd_nam, ! 615: struct sockaddr_in *)->sin_addr.s_addr; ! 616: nsd->nsd_authlen = nfsd->nfsd_authlen; ! 617: nsd->nsd_verflen = nfsd->nfsd_verflen; ! 618: if (!copyout(nfsd->nfsd_authstr,nsd->nsd_authstr, ! 619: nfsd->nfsd_authlen) && ! 620: !copyout(nfsd->nfsd_verfstr, nsd->nsd_verfstr, ! 621: nfsd->nfsd_verflen) && ! 622: !copyout((caddr_t)nsd, argp, sizeof (*nsd))) ! 623: return (ENEEDAUTH); ! 624: cacherep = RC_DROPIT; ! 625: } else ! 626: cacherep = nfsrv_getcache(nd, slp, &mreq); ! 627: ! 628: /* ! 629: * Check for just starting up for NQNFS and send ! 630: * fake "try again later" replies to the NQNFS clients. ! 631: */ ! 632: if (notstarted && nqnfsstarttime <= time.tv_sec) { ! 633: if (modify_flag) { ! 634: nqnfsstarttime = time.tv_sec + nqsrv_writeslack; ! 635: modify_flag = 0; ! 636: } else ! 637: notstarted = 0; ! 638: } ! 639: if (notstarted) { ! 640: if ((nd->nd_flag & ND_NQNFS) == 0) ! 641: cacherep = RC_DROPIT; ! 642: else if (nd->nd_procnum != NFSPROC_WRITE) { ! 643: nd->nd_procnum = NFSPROC_NOOP; ! 644: nd->nd_repstat = NQNFS_TRYLATER; ! 645: cacherep = RC_DOIT; ! 646: } else ! 647: modify_flag = 1; ! 648: } else if (nfsd->nfsd_flag & NFSD_AUTHFAIL) { ! 649: nfsd->nfsd_flag &= ~NFSD_AUTHFAIL; ! 650: nd->nd_procnum = NFSPROC_NOOP; ! 651: nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK); ! 652: cacherep = RC_DOIT; ! 653: } else if (nfs_privport) { ! 654: /* Check if source port is privileged */ ! 655: u_short port; ! 656: struct sockaddr *nam = nd->nd_nam; ! 657: struct sockaddr_in *sin; ! 658: ! 659: sin = (struct sockaddr_in *)nam; ! 660: port = ntohs(sin->sin_port); ! 661: if (port >= IPPORT_RESERVED && ! 662: nd->nd_procnum != NFSPROC_NULL) { ! 663: nd->nd_procnum = NFSPROC_NOOP; ! 664: nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK); ! 665: cacherep = RC_DOIT; ! 666: printf("NFS request from unprivileged port (%s:%d)\n", ! 667: (char *)(inet_ntoa(sin->sin_addr)), port); ! 668: } ! 669: } ! 670: ! 671: } ! 672: ! 673: /* ! 674: * Loop to get all the write rpc relies that have been ! 675: * gathered together. ! 676: */ ! 677: do { ! 678: switch (cacherep) { ! 679: case RC_DOIT: ! 680: if (nd && (nd->nd_flag & ND_NFSV3)) ! 681: procrastinate = nfsrvw_procrastinate_v3; ! 682: else ! 683: procrastinate = nfsrvw_procrastinate; ! 684: if (writes_todo || (nd->nd_procnum == NFSPROC_WRITE && ! 685: procrastinate > 0 && !notstarted)) ! 686: error = nfsrv_writegather(&nd, slp, ! 687: nfsd->nfsd_procp, &mreq); ! 688: else ! 689: error = (*(nfsrv3_procs[nd->nd_procnum]))(nd, ! 690: slp, nfsd->nfsd_procp, &mreq); ! 691: if (mreq == NULL) ! 692: break; ! 693: if (error) { ! 694: if (nd->nd_procnum != NQNFSPROC_VACATED) ! 695: nfsstats.srv_errs++; ! 696: nfsrv_updatecache(nd, FALSE, mreq); ! 697: if (nd->nd_nam2) ! 698: m_freem(nd->nd_nam2); ! 699: break; ! 700: } ! 701: nfsstats.srvrpccnt[nd->nd_procnum]++; ! 702: nfsrv_updatecache(nd, TRUE, mreq); ! 703: nd->nd_mrep = (struct mbuf *)0; ! 704: case RC_REPLY: ! 705: m = mreq; ! 706: siz = 0; ! 707: while (m) { ! 708: siz += m->m_len; ! 709: m = m->m_next; ! 710: } ! 711: if (siz <= 0 || siz > NFS_MAXPACKET) { ! 712: printf("mbuf siz=%d\n",siz); ! 713: panic("Bad nfs svc reply"); ! 714: } ! 715: m = mreq; ! 716: m->m_pkthdr.len = siz; ! 717: m->m_pkthdr.rcvif = (struct ifnet *)0; ! 718: /* ! 719: * For stream protocols, prepend a Sun RPC ! 720: * Record Mark. ! 721: */ ! 722: if (sotype == SOCK_STREAM) { ! 723: M_PREPEND(m, NFSX_UNSIGNED, M_WAIT); ! 724: *mtod(m, u_long *) = htonl(0x80000000 | siz); ! 725: } ! 726: if (solockp) ! 727: (void) nfs_sndlock(solockp, (struct nfsreq *)0); ! 728: if (slp->ns_flag & SLP_VALID) ! 729: error = nfs_send(so, nd->nd_nam2, m, NULL); ! 730: else { ! 731: error = EPIPE; ! 732: m_freem(m); ! 733: } ! 734: if (nfsrtton) ! 735: nfsd_rt(sotype, nd, cacherep); ! 736: if (nd->nd_nam2) ! 737: MFREE(nd->nd_nam2, m); ! 738: if (nd->nd_mrep) ! 739: m_freem(nd->nd_mrep); ! 740: if (error == EPIPE) ! 741: nfsrv_zapsock(slp); ! 742: if (solockp) ! 743: nfs_sndunlock(solockp); ! 744: if (error == EINTR || error == ERESTART) { ! 745: _FREE_ZONE((caddr_t)nd, ! 746: sizeof *nd, M_NFSRVDESC); ! 747: nfsrv_slpderef(slp); ! 748: s = splnet(); ! 749: goto done; ! 750: } ! 751: break; ! 752: case RC_DROPIT: ! 753: if (nfsrtton) ! 754: nfsd_rt(sotype, nd, cacherep); ! 755: m_freem(nd->nd_mrep); ! 756: m_freem(nd->nd_nam2); ! 757: break; ! 758: }; ! 759: if (nd) { ! 760: FREE_ZONE((caddr_t)nd, sizeof *nd, M_NFSRVDESC); ! 761: nd = NULL; ! 762: } ! 763: ! 764: /* ! 765: * Check to see if there are outstanding writes that ! 766: * need to be serviced. ! 767: */ ! 768: cur_usec = (u_quad_t)time.tv_sec * 1000000 + ! 769: (u_quad_t)time.tv_usec; ! 770: s = splsoftclock(); ! 771: if (slp->ns_tq.lh_first && ! 772: slp->ns_tq.lh_first->nd_time <= cur_usec) { ! 773: cacherep = RC_DOIT; ! 774: writes_todo = 1; ! 775: } else ! 776: writes_todo = 0; ! 777: splx(s); ! 778: } while (writes_todo); ! 779: s = splnet(); ! 780: if (nfsrv_dorec(slp, nfsd, &nd)) { ! 781: nfsd->nfsd_flag &= ~NFSD_REQINPROG; ! 782: nfsd->nfsd_slp = NULL; ! 783: nfsrv_slpderef(slp); ! 784: } ! 785: } ! 786: done: ! 787: TAILQ_REMOVE(&nfsd_head, nfsd, nfsd_chain); ! 788: splx(s); ! 789: _FREE((caddr_t)nfsd, M_NFSD); ! 790: nsd->nsd_nfsd = (struct nfsd *)0; ! 791: if (--nfs_numnfsd == 0) ! 792: nfsrv_init(TRUE); /* Reinitialize everything */ ! 793: return (error); ! 794: } ! 795: #endif /* NFS_NOSERVER */ ! 796: ! 797: int nfs_defect = 0; ! 798: /* XXX CSM 11/25/97 Upgrade sysctl.h someday */ ! 799: #ifdef notyet ! 800: SYSCTL_INT(_vfs_nfs, OID_AUTO, defect, CTLFLAG_RW, &nfs_defect, 0, ""); ! 801: #endif ! 802: ! 803: static int nfssvc_iod_continue(int); ! 804: ! 805: /* ! 806: * Asynchronous I/O daemons for client nfs. ! 807: * They do read-ahead and write-behind operations on the block I/O cache. ! 808: * Never returns unless it fails or gets killed. ! 809: */ ! 810: static int ! 811: nfssvc_iod(p) ! 812: struct proc *p; ! 813: { ! 814: register struct buf *bp; ! 815: register int i, myiod; ! 816: struct nfsmount *nmp; ! 817: int error = 0; ! 818: struct uthread *ut; ! 819: ! 820: /* ! 821: * Assign my position or return error if too many already running ! 822: */ ! 823: myiod = -1; ! 824: for (i = 0; i < NFS_MAXASYNCDAEMON; i++) ! 825: if (nfs_asyncdaemon[i] == 0) { ! 826: nfs_asyncdaemon[i]++; ! 827: myiod = i; ! 828: break; ! 829: } ! 830: if (myiod == -1) ! 831: return (EBUSY); ! 832: nfs_numasync++; ! 833: ! 834: /* stuff myiod into uthread to get off local stack for ! 835: continuation */ ! 836: ! 837: ut = get_bsdthread_info(current_act()); ! 838: ut->uu_state.uu_nfs_myiod = myiod; /* squirrel away for continuation */ ! 839: ! 840: nfssvc_iod_continue(0); ! 841: /* NOTREACHED */ ! 842: ! 843: } ! 844: ! 845: /* ! 846: * Continuation for Asynchronous I/O daemons for client nfs. ! 847: */ ! 848: static int ! 849: nfssvc_iod_continue(error) ! 850: { ! 851: register struct buf *bp; ! 852: register int i, myiod; ! 853: struct nfsmount *nmp; ! 854: struct uthread *ut; ! 855: struct proc *p; ! 856: ! 857: /* ! 858: * real myiod is stored in uthread, recover it ! 859: */ ! 860: ut = get_bsdthread_info(current_act()); ! 861: myiod = ut->uu_state.uu_nfs_myiod; ! 862: p = get_bsdtask_info(current_task()); ! 863: ! 864: /* ! 865: * Just loop around doin our stuff until SIGKILL ! 866: * - actually we don't loop with continuations... ! 867: */ ! 868: for (;;) { ! 869: while (((nmp = nfs_iodmount[myiod]) == NULL ! 870: || nmp->nm_bufq.tqh_first == NULL) ! 871: && error == 0) { ! 872: if (nmp) ! 873: nmp->nm_bufqiods--; ! 874: nfs_iodwant[myiod] = p; ! 875: nfs_iodmount[myiod] = NULL; ! 876: error = tsleep0((caddr_t)&nfs_iodwant[myiod], ! 877: PWAIT | PCATCH, "nfsidl", 0, nfssvc_iod_continue); ! 878: /* NOTREACHED */ ! 879: } ! 880: if (error) { ! 881: nfs_asyncdaemon[myiod] = 0; ! 882: if (nmp) nmp->nm_bufqiods--; ! 883: nfs_iodwant[myiod] = NULL; ! 884: nfs_iodmount[myiod] = NULL; ! 885: nfs_numasync--; ! 886: if (error == EINTR || error == ERESTART) ! 887: error = 0; ! 888: unix_syscall_return(error); ! 889: } ! 890: while ((bp = nmp->nm_bufq.tqh_first) != NULL) { ! 891: /* Take one off the front of the list */ ! 892: TAILQ_REMOVE(&nmp->nm_bufq, bp, b_freelist); ! 893: nmp->nm_bufqlen--; ! 894: if (nmp->nm_bufqwant && nmp->nm_bufqlen < 2 * nfs_numasync) { ! 895: nmp->nm_bufqwant = FALSE; ! 896: wakeup(&nmp->nm_bufq); ! 897: } ! 898: if (bp->b_flags & B_READ) ! 899: (void) nfs_doio(bp, bp->b_rcred, (struct proc *)0); ! 900: else ! 901: (void) nfs_doio(bp, bp->b_wcred, (struct proc *)0); ! 902: ! 903: /* ! 904: * If there are more than one iod on this mount, then defect ! 905: * so that the iods can be shared out fairly between the mounts ! 906: */ ! 907: if (nfs_defect && nmp->nm_bufqiods > 1) { ! 908: NFS_DPF(ASYNCIO, ! 909: ("nfssvc_iod: iod %d defecting from mount %p\n", ! 910: myiod, nmp)); ! 911: nfs_iodmount[myiod] = NULL; ! 912: nmp->nm_bufqiods--; ! 913: break; ! 914: } ! 915: } ! 916: } ! 917: } ! 918: ! 919: /* ! 920: * Shut down a socket associated with an nfssvc_sock structure. ! 921: * Should be called with the send lock set, if required. ! 922: * The trick here is to increment the sref at the start, so that the nfsds ! 923: * will stop using it and clear ns_flag at the end so that it will not be ! 924: * reassigned during cleanup. ! 925: */ ! 926: static void ! 927: nfsrv_zapsock(slp) ! 928: register struct nfssvc_sock *slp; ! 929: { ! 930: register struct nfsuid *nuidp, *nnuidp; ! 931: register struct nfsrv_descript *nwp, *nnwp; ! 932: struct socket *so; ! 933: struct file *fp; ! 934: struct mbuf *m; ! 935: int s; ! 936: ! 937: slp->ns_flag &= ~SLP_ALLFLAGS; ! 938: fp = slp->ns_fp; ! 939: if (fp) { ! 940: slp->ns_fp = (struct file *)0; ! 941: so = slp->ns_so; ! 942: so->so_upcall = NULL; ! 943: so->so_rcv.sb_flags &= ~SB_UPCALL; ! 944: soshutdown(so, 2); ! 945: closef(fp, (struct proc *)0); ! 946: if (slp->ns_nam) ! 947: MFREE(slp->ns_nam, m); ! 948: m_freem(slp->ns_raw); ! 949: m_freem(slp->ns_rec); ! 950: for (nuidp = slp->ns_uidlruhead.tqh_first; nuidp != 0; ! 951: nuidp = nnuidp) { ! 952: nnuidp = nuidp->nu_lru.tqe_next; ! 953: LIST_REMOVE(nuidp, nu_hash); ! 954: TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp, nu_lru); ! 955: if (nuidp->nu_flag & NU_NAM) ! 956: m_freem(nuidp->nu_nam); ! 957: _FREE_ZONE((caddr_t)nuidp, ! 958: sizeof (struct nfsuid), M_NFSUID); ! 959: } ! 960: s = splsoftclock(); ! 961: for (nwp = slp->ns_tq.lh_first; nwp; nwp = nnwp) { ! 962: nnwp = nwp->nd_tq.le_next; ! 963: LIST_REMOVE(nwp, nd_tq); ! 964: _FREE_ZONE((caddr_t)nwp, sizeof *nwp, M_NFSRVDESC); ! 965: } ! 966: LIST_INIT(&slp->ns_tq); ! 967: splx(s); ! 968: } ! 969: } ! 970: ! 971: /* ! 972: * Get an authorization string for the uid by having the mount_nfs sitting ! 973: * on this mount point porpous out of the kernel and do it. ! 974: */ ! 975: int ! 976: nfs_getauth(nmp, rep, cred, auth_str, auth_len, verf_str, verf_len, key) ! 977: register struct nfsmount *nmp; ! 978: struct nfsreq *rep; ! 979: struct ucred *cred; ! 980: char **auth_str; ! 981: int *auth_len; ! 982: char *verf_str; ! 983: int *verf_len; ! 984: NFSKERBKEY_T key; /* return session key */ ! 985: { ! 986: int error = 0; ! 987: ! 988: while ((nmp->nm_flag & NFSMNT_WAITAUTH) == 0) { ! 989: nmp->nm_flag |= NFSMNT_WANTAUTH; ! 990: (void) tsleep((caddr_t)&nmp->nm_authtype, PSOCK, ! 991: "nfsauth1", 2 * hz); ! 992: error = nfs_sigintr(nmp, rep, rep->r_procp); ! 993: if (error) { ! 994: nmp->nm_flag &= ~NFSMNT_WANTAUTH; ! 995: return (error); ! 996: } ! 997: } ! 998: nmp->nm_flag &= ~(NFSMNT_WAITAUTH | NFSMNT_WANTAUTH); ! 999: MALLOC(*auth_str, char *, RPCAUTH_MAXSIZ, M_TEMP, M_WAITOK); ! 1000: nmp->nm_authstr = *auth_str; ! 1001: nmp->nm_authlen = RPCAUTH_MAXSIZ; ! 1002: nmp->nm_verfstr = verf_str; ! 1003: nmp->nm_verflen = *verf_len; ! 1004: nmp->nm_authuid = cred->cr_uid; ! 1005: wakeup((caddr_t)&nmp->nm_authstr); ! 1006: ! 1007: /* ! 1008: * And wait for mount_nfs to do its stuff. ! 1009: */ ! 1010: while ((nmp->nm_flag & NFSMNT_HASAUTH) == 0 && error == 0) { ! 1011: (void) tsleep((caddr_t)&nmp->nm_authlen, PSOCK, ! 1012: "nfsauth2", 2 * hz); ! 1013: error = nfs_sigintr(nmp, rep, rep->r_procp); ! 1014: } ! 1015: if (nmp->nm_flag & NFSMNT_AUTHERR) { ! 1016: nmp->nm_flag &= ~NFSMNT_AUTHERR; ! 1017: error = EAUTH; ! 1018: } ! 1019: if (error) ! 1020: _FREE((caddr_t)*auth_str, M_TEMP); ! 1021: else { ! 1022: *auth_len = nmp->nm_authlen; ! 1023: *verf_len = nmp->nm_verflen; ! 1024: bcopy((caddr_t)nmp->nm_key, (caddr_t)key, sizeof (key)); ! 1025: } ! 1026: nmp->nm_flag &= ~NFSMNT_HASAUTH; ! 1027: nmp->nm_flag |= NFSMNT_WAITAUTH; ! 1028: if (nmp->nm_flag & NFSMNT_WANTAUTH) { ! 1029: nmp->nm_flag &= ~NFSMNT_WANTAUTH; ! 1030: wakeup((caddr_t)&nmp->nm_authtype); ! 1031: } ! 1032: return (error); ! 1033: } ! 1034: ! 1035: /* ! 1036: * Get a nickname authenticator and verifier. ! 1037: */ ! 1038: int ! 1039: nfs_getnickauth(nmp, cred, auth_str, auth_len, verf_str, verf_len) ! 1040: struct nfsmount *nmp; ! 1041: struct ucred *cred; ! 1042: char **auth_str; ! 1043: int *auth_len; ! 1044: char *verf_str; ! 1045: int verf_len; ! 1046: { ! 1047: register struct nfsuid *nuidp; ! 1048: register u_long *nickp, *verfp; ! 1049: struct timeval ktvin, ktvout; ! 1050: ! 1051: #if DIAGNOSTIC ! 1052: if (verf_len < (4 * NFSX_UNSIGNED)) ! 1053: panic("nfs_getnickauth verf too small"); ! 1054: #endif ! 1055: for (nuidp = NMUIDHASH(nmp, cred->cr_uid)->lh_first; ! 1056: nuidp != 0; nuidp = nuidp->nu_hash.le_next) { ! 1057: if (nuidp->nu_cr.cr_uid == cred->cr_uid) ! 1058: break; ! 1059: } ! 1060: if (!nuidp || nuidp->nu_expire < time.tv_sec) ! 1061: return (EACCES); ! 1062: ! 1063: /* ! 1064: * Move to the end of the lru list (end of lru == most recently used). ! 1065: */ ! 1066: TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp, nu_lru); ! 1067: TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp, nu_lru); ! 1068: ! 1069: MALLOC(nickp, u_long *, 2 * NFSX_UNSIGNED, M_TEMP, M_WAITOK); ! 1070: *nickp++ = txdr_unsigned(RPCAKN_NICKNAME); ! 1071: *nickp = txdr_unsigned(nuidp->nu_nickname); ! 1072: *auth_str = (char *)nickp; ! 1073: *auth_len = 2 * NFSX_UNSIGNED; ! 1074: ! 1075: /* ! 1076: * Now we must encrypt the verifier and package it up. ! 1077: */ ! 1078: verfp = (u_long *)verf_str; ! 1079: *verfp++ = txdr_unsigned(RPCAKN_NICKNAME); ! 1080: if (time.tv_sec > nuidp->nu_timestamp.tv_sec || ! 1081: (time.tv_sec == nuidp->nu_timestamp.tv_sec && ! 1082: time.tv_usec > nuidp->nu_timestamp.tv_usec)) ! 1083: nuidp->nu_timestamp = time; ! 1084: else ! 1085: nuidp->nu_timestamp.tv_usec++; ! 1086: ktvin.tv_sec = txdr_unsigned(nuidp->nu_timestamp.tv_sec); ! 1087: ktvin.tv_usec = txdr_unsigned(nuidp->nu_timestamp.tv_usec); ! 1088: ! 1089: /* ! 1090: * Now encrypt the timestamp verifier in ecb mode using the session ! 1091: * key. ! 1092: */ ! 1093: #if NFSKERB ! 1094: XXX ! 1095: #endif ! 1096: ! 1097: *verfp++ = ktvout.tv_sec; ! 1098: *verfp++ = ktvout.tv_usec; ! 1099: *verfp = 0; ! 1100: return (0); ! 1101: } ! 1102: ! 1103: /* ! 1104: * Save the current nickname in a hash list entry on the mount point. ! 1105: */ ! 1106: int ! 1107: nfs_savenickauth(nmp, cred, len, key, mdp, dposp, mrep) ! 1108: register struct nfsmount *nmp; ! 1109: struct ucred *cred; ! 1110: int len; ! 1111: NFSKERBKEY_T key; ! 1112: struct mbuf **mdp; ! 1113: char **dposp; ! 1114: struct mbuf *mrep; ! 1115: { ! 1116: register struct nfsuid *nuidp; ! 1117: register u_long *tl; ! 1118: register long t1; ! 1119: struct mbuf *md = *mdp; ! 1120: struct timeval ktvin, ktvout; ! 1121: u_long nick; ! 1122: char *dpos = *dposp, *cp2; ! 1123: int deltasec, error = 0; ! 1124: ! 1125: if (len == (3 * NFSX_UNSIGNED)) { ! 1126: nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); ! 1127: ktvin.tv_sec = *tl++; ! 1128: ktvin.tv_usec = *tl++; ! 1129: nick = fxdr_unsigned(u_long, *tl); ! 1130: ! 1131: /* ! 1132: * Decrypt the timestamp in ecb mode. ! 1133: */ ! 1134: #if NFSKERB ! 1135: XXX ! 1136: #endif ! 1137: ktvout.tv_sec = fxdr_unsigned(long, ktvout.tv_sec); ! 1138: ktvout.tv_usec = fxdr_unsigned(long, ktvout.tv_usec); ! 1139: deltasec = time.tv_sec - ktvout.tv_sec; ! 1140: if (deltasec < 0) ! 1141: deltasec = -deltasec; ! 1142: /* ! 1143: * If ok, add it to the hash list for the mount point. ! 1144: */ ! 1145: if (deltasec <= NFS_KERBCLOCKSKEW) { ! 1146: if (nmp->nm_numuids < nuidhash_max) { ! 1147: nmp->nm_numuids++; ! 1148: MALLOC_ZONE(nuidp, struct nfsuid *, ! 1149: sizeof (struct nfsuid), ! 1150: M_NFSUID, M_WAITOK); ! 1151: } else { ! 1152: nuidp = nmp->nm_uidlruhead.tqh_first; ! 1153: LIST_REMOVE(nuidp, nu_hash); ! 1154: TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp, ! 1155: nu_lru); ! 1156: } ! 1157: nuidp->nu_flag = 0; ! 1158: nuidp->nu_cr.cr_uid = cred->cr_uid; ! 1159: nuidp->nu_expire = time.tv_sec + NFS_KERBTTL; ! 1160: nuidp->nu_timestamp = ktvout; ! 1161: nuidp->nu_nickname = nick; ! 1162: bcopy(key, nuidp->nu_key, sizeof (key)); ! 1163: TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp, ! 1164: nu_lru); ! 1165: LIST_INSERT_HEAD(NMUIDHASH(nmp, cred->cr_uid), ! 1166: nuidp, nu_hash); ! 1167: } ! 1168: } else ! 1169: nfsm_adv(nfsm_rndup(len)); ! 1170: nfsmout: ! 1171: *mdp = md; ! 1172: *dposp = dpos; ! 1173: return (error); ! 1174: } ! 1175: ! 1176: #ifndef NFS_NOSERVER ! 1177: ! 1178: /* ! 1179: * Derefence a server socket structure. If it has no more references and ! 1180: * is no longer valid, you can throw it away. ! 1181: */ ! 1182: void ! 1183: nfsrv_slpderef(slp) ! 1184: register struct nfssvc_sock *slp; ! 1185: { ! 1186: if (--(slp->ns_sref) == 0 && (slp->ns_flag & SLP_VALID) == 0) { ! 1187: TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain); ! 1188: _FREE((caddr_t)slp, M_NFSSVC); ! 1189: } ! 1190: } ! 1191: ! 1192: /* ! 1193: * Initialize the data structures for the server. ! 1194: * Handshake with any new nfsds starting up to avoid any chance of ! 1195: * corruption. ! 1196: */ ! 1197: void ! 1198: nfsrv_init(terminating) ! 1199: int terminating; ! 1200: { ! 1201: register struct nfssvc_sock *slp, *nslp; ! 1202: ! 1203: if (nfssvc_sockhead_flag & SLP_INIT) ! 1204: panic("nfsd init"); ! 1205: nfssvc_sockhead_flag |= SLP_INIT; ! 1206: if (terminating) { ! 1207: for (slp = nfssvc_sockhead.tqh_first; slp != 0; slp = nslp) { ! 1208: nslp = slp->ns_chain.tqe_next; ! 1209: if (slp->ns_flag & SLP_VALID) ! 1210: nfsrv_zapsock(slp); ! 1211: TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain); ! 1212: _FREE((caddr_t)slp, M_NFSSVC); ! 1213: } ! 1214: nfsrv_cleancache(); /* And clear out server cache */ ! 1215: /* XXX CSM 12/4/97 Revisit when enabling WebNFS */ ! 1216: #ifdef notyet ! 1217: } else ! 1218: nfs_pub.np_valid = 0; ! 1219: #else ! 1220: } ! 1221: #endif ! 1222: ! 1223: TAILQ_INIT(&nfssvc_sockhead); ! 1224: nfssvc_sockhead_flag &= ~SLP_INIT; ! 1225: if (nfssvc_sockhead_flag & SLP_WANTINIT) { ! 1226: nfssvc_sockhead_flag &= ~SLP_WANTINIT; ! 1227: wakeup((caddr_t)&nfssvc_sockhead); ! 1228: } ! 1229: ! 1230: TAILQ_INIT(&nfsd_head); ! 1231: nfsd_head_flag &= ~NFSD_CHECKSLP; ! 1232: ! 1233: MALLOC(nfs_udpsock, struct nfssvc_sock *, sizeof(struct nfssvc_sock), ! 1234: M_NFSSVC, M_WAITOK); ! 1235: bzero((caddr_t)nfs_udpsock, sizeof (struct nfssvc_sock)); ! 1236: TAILQ_INIT(&nfs_udpsock->ns_uidlruhead); ! 1237: TAILQ_INSERT_HEAD(&nfssvc_sockhead, nfs_udpsock, ns_chain); ! 1238: ! 1239: MALLOC(nfs_cltpsock, struct nfssvc_sock *, sizeof(struct nfssvc_sock), ! 1240: M_NFSSVC, M_WAITOK); ! 1241: bzero((caddr_t)nfs_cltpsock, sizeof (struct nfssvc_sock)); ! 1242: TAILQ_INIT(&nfs_cltpsock->ns_uidlruhead); ! 1243: TAILQ_INSERT_TAIL(&nfssvc_sockhead, nfs_cltpsock, ns_chain); ! 1244: } ! 1245: ! 1246: /* ! 1247: * Add entries to the server monitor log. ! 1248: */ ! 1249: static void ! 1250: nfsd_rt(sotype, nd, cacherep) ! 1251: int sotype; ! 1252: register struct nfsrv_descript *nd; ! 1253: int cacherep; ! 1254: { ! 1255: register struct drt *rt; ! 1256: ! 1257: rt = &nfsdrt.drt[nfsdrt.pos]; ! 1258: if (cacherep == RC_DOIT) ! 1259: rt->flag = 0; ! 1260: else if (cacherep == RC_REPLY) ! 1261: rt->flag = DRT_CACHEREPLY; ! 1262: else ! 1263: rt->flag = DRT_CACHEDROP; ! 1264: if (sotype == SOCK_STREAM) ! 1265: rt->flag |= DRT_TCP; ! 1266: if (nd->nd_flag & ND_NQNFS) ! 1267: rt->flag |= DRT_NQNFS; ! 1268: else if (nd->nd_flag & ND_NFSV3) ! 1269: rt->flag |= DRT_NFSV3; ! 1270: rt->proc = nd->nd_procnum; ! 1271: if (mtod(nd->nd_nam, struct sockaddr *)->sa_family == AF_INET) ! 1272: rt->ipadr = mtod(nd->nd_nam, struct sockaddr_in *)->sin_addr.s_addr; ! 1273: else ! 1274: rt->ipadr = INADDR_ANY; ! 1275: rt->resptime = ((time.tv_sec - nd->nd_starttime.tv_sec) * 1000000) + ! 1276: (time.tv_usec - nd->nd_starttime.tv_usec); ! 1277: rt->tstamp = time; ! 1278: nfsdrt.pos = (nfsdrt.pos + 1) % NFSRTTLOGSIZ; ! 1279: } ! 1280: #endif /* NFS_NOSERVER */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.