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