[BACK]Return to nfs_syscalls.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / nfs

Annotation of src/sys/nfs/nfs_syscalls.c, Revision 1.41

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

CVSweb <webmaster@jp.NetBSD.org>