The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/nfs/nfs_syscalls.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 169835ecfe4741fbb646129693896f56


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.