Home | History | Annotate | Line # | Download | only in server
      1  1.2  pgoyette /*	$NetBSD: nfs_nfsdsocket.c,v 1.2 2016/12/13 21:50:32 pgoyette Exp $	*/
      2  1.1  dholland /*-
      3  1.1  dholland  * Copyright (c) 1989, 1993
      4  1.1  dholland  *	The Regents of the University of California.  All rights reserved.
      5  1.1  dholland  *
      6  1.1  dholland  * This code is derived from software contributed to Berkeley by
      7  1.1  dholland  * Rick Macklem at The University of Guelph.
      8  1.1  dholland  *
      9  1.1  dholland  * Redistribution and use in source and binary forms, with or without
     10  1.1  dholland  * modification, are permitted provided that the following conditions
     11  1.1  dholland  * are met:
     12  1.1  dholland  * 1. Redistributions of source code must retain the above copyright
     13  1.1  dholland  *    notice, this list of conditions and the following disclaimer.
     14  1.1  dholland  * 2. Redistributions in binary form must reproduce the above copyright
     15  1.1  dholland  *    notice, this list of conditions and the following disclaimer in the
     16  1.1  dholland  *    documentation and/or other materials provided with the distribution.
     17  1.1  dholland  * 4. Neither the name of the University nor the names of its contributors
     18  1.1  dholland  *    may be used to endorse or promote products derived from this software
     19  1.1  dholland  *    without specific prior written permission.
     20  1.1  dholland  *
     21  1.1  dholland  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     22  1.1  dholland  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  1.1  dholland  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24  1.1  dholland  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     25  1.1  dholland  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26  1.1  dholland  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27  1.1  dholland  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28  1.1  dholland  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29  1.1  dholland  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30  1.1  dholland  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31  1.1  dholland  * SUCH DAMAGE.
     32  1.1  dholland  *
     33  1.1  dholland  */
     34  1.1  dholland 
     35  1.1  dholland #include <sys/cdefs.h>
     36  1.2  pgoyette /* __FBSDID("FreeBSD: head/sys/fs/nfsserver/nfs_nfsdsocket.c 304026 2016-08-12 22:44:59Z rmacklem "); */
     37  1.2  pgoyette __RCSID("$NetBSD: nfs_nfsdsocket.c,v 1.2 2016/12/13 21:50:32 pgoyette Exp $");
     38  1.1  dholland 
     39  1.1  dholland /*
     40  1.1  dholland  * Socket operations for use by the nfs server.
     41  1.1  dholland  */
     42  1.1  dholland 
     43  1.1  dholland #ifndef APPLEKEXT
     44  1.2  pgoyette #include <fs/nfs/common/nfsport.h>
     45  1.1  dholland 
     46  1.2  pgoyette extern struct nfsstatsv1 nfsstatsv1;
     47  1.1  dholland extern struct nfsrvfh nfs_pubfh, nfs_rootfh;
     48  1.1  dholland extern int nfs_pubfhset, nfs_rootfhset;
     49  1.1  dholland extern struct nfsv4lock nfsv4rootfs_lock;
     50  1.1  dholland extern struct nfsrv_stablefirst nfsrv_stablefirst;
     51  1.2  pgoyette extern struct nfsclienthashhead *nfsclienthash;
     52  1.2  pgoyette extern int nfsrv_clienthashsize;
     53  1.1  dholland extern int nfsrc_floodlevel, nfsrc_tcpsavedreplies;
     54  1.2  pgoyette extern int nfsd_debuglevel;
     55  1.1  dholland NFSV4ROOTLOCKMUTEX;
     56  1.1  dholland NFSSTATESPINLOCK;
     57  1.1  dholland 
     58  1.1  dholland int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *,
     59  1.1  dholland     int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
     60  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
     61  1.1  dholland 	nfsrvd_getattr,
     62  1.1  dholland 	nfsrvd_setattr,
     63  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
     64  1.1  dholland 	nfsrvd_access,
     65  1.1  dholland 	nfsrvd_readlink,
     66  1.1  dholland 	nfsrvd_read,
     67  1.1  dholland 	nfsrvd_write,
     68  1.1  dholland 	nfsrvd_create,
     69  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
     70  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
     71  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
     72  1.1  dholland 	nfsrvd_remove,
     73  1.1  dholland 	nfsrvd_remove,
     74  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
     75  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
     76  1.1  dholland 	nfsrvd_readdir,
     77  1.1  dholland 	nfsrvd_readdirplus,
     78  1.1  dholland 	nfsrvd_statfs,
     79  1.1  dholland 	nfsrvd_fsinfo,
     80  1.1  dholland 	nfsrvd_pathconf,
     81  1.1  dholland 	nfsrvd_commit,
     82  1.1  dholland };
     83  1.1  dholland 
     84  1.1  dholland int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *,
     85  1.1  dholland     int, vnode_t , vnode_t *, fhandle_t *,
     86  1.1  dholland     NFSPROC_T *, struct nfsexstuff *) = {
     87  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
     88  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
     89  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
     90  1.1  dholland 	nfsrvd_lookup,
     91  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
     92  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
     93  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
     94  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
     95  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
     96  1.1  dholland 	nfsrvd_mkdir,
     97  1.1  dholland 	nfsrvd_symlink,
     98  1.1  dholland 	nfsrvd_mknod,
     99  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    100  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    101  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    102  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    103  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    104  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    105  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    106  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    107  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    108  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    109  1.1  dholland };
    110  1.1  dholland 
    111  1.1  dholland int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
    112  1.1  dholland     int, vnode_t , vnode_t , NFSPROC_T *,
    113  1.1  dholland     struct nfsexstuff *, struct nfsexstuff *) = {
    114  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    115  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    116  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    117  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    118  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    119  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    120  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    121  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    122  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    123  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    124  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    125  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    126  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    127  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    128  1.1  dholland 	nfsrvd_rename,
    129  1.1  dholland 	nfsrvd_link,
    130  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    131  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    132  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    133  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    134  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    135  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    136  1.1  dholland };
    137  1.1  dholland 
    138  1.2  pgoyette int (*nfsrv4_ops0[NFSV41_NOPS])(struct nfsrv_descript *,
    139  1.1  dholland     int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
    140  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    141  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    142  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    143  1.1  dholland 	nfsrvd_access,
    144  1.1  dholland 	nfsrvd_close,
    145  1.1  dholland 	nfsrvd_commit,
    146  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    147  1.1  dholland 	nfsrvd_delegpurge,
    148  1.1  dholland 	nfsrvd_delegreturn,
    149  1.1  dholland 	nfsrvd_getattr,
    150  1.1  dholland 	nfsrvd_getfh,
    151  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    152  1.1  dholland 	nfsrvd_lock,
    153  1.1  dholland 	nfsrvd_lockt,
    154  1.1  dholland 	nfsrvd_locku,
    155  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    156  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    157  1.1  dholland 	nfsrvd_verify,
    158  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    159  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    160  1.1  dholland 	nfsrvd_openconfirm,
    161  1.1  dholland 	nfsrvd_opendowngrade,
    162  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    163  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    164  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    165  1.1  dholland 	nfsrvd_read,
    166  1.1  dholland 	nfsrvd_readdirplus,
    167  1.1  dholland 	nfsrvd_readlink,
    168  1.1  dholland 	nfsrvd_remove,
    169  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    170  1.1  dholland 	nfsrvd_renew,
    171  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    172  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    173  1.1  dholland 	nfsrvd_secinfo,
    174  1.1  dholland 	nfsrvd_setattr,
    175  1.1  dholland 	nfsrvd_setclientid,
    176  1.1  dholland 	nfsrvd_setclientidcfrm,
    177  1.1  dholland 	nfsrvd_verify,
    178  1.1  dholland 	nfsrvd_write,
    179  1.1  dholland 	nfsrvd_releaselckown,
    180  1.2  pgoyette 	nfsrvd_notsupp,
    181  1.2  pgoyette 	nfsrvd_notsupp,
    182  1.2  pgoyette 	nfsrvd_exchangeid,
    183  1.2  pgoyette 	nfsrvd_createsession,
    184  1.2  pgoyette 	nfsrvd_destroysession,
    185  1.2  pgoyette 	nfsrvd_freestateid,
    186  1.2  pgoyette 	nfsrvd_notsupp,
    187  1.2  pgoyette 	nfsrvd_notsupp,
    188  1.2  pgoyette 	nfsrvd_notsupp,
    189  1.2  pgoyette 	nfsrvd_notsupp,
    190  1.2  pgoyette 	nfsrvd_notsupp,
    191  1.2  pgoyette 	nfsrvd_notsupp,
    192  1.2  pgoyette 	nfsrvd_notsupp,
    193  1.2  pgoyette 	nfsrvd_sequence,
    194  1.2  pgoyette 	nfsrvd_notsupp,
    195  1.2  pgoyette 	nfsrvd_notsupp,
    196  1.2  pgoyette 	nfsrvd_notsupp,
    197  1.2  pgoyette 	nfsrvd_destroyclientid,
    198  1.2  pgoyette 	nfsrvd_reclaimcomplete,
    199  1.1  dholland };
    200  1.1  dholland 
    201  1.2  pgoyette int (*nfsrv4_ops1[NFSV41_NOPS])(struct nfsrv_descript *,
    202  1.1  dholland     int, vnode_t , vnode_t *, fhandle_t *,
    203  1.1  dholland     NFSPROC_T *, struct nfsexstuff *) = {
    204  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    205  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    206  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    207  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    208  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    209  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    210  1.1  dholland 	nfsrvd_mknod,
    211  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    212  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    213  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    214  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    215  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    216  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    217  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    218  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    219  1.1  dholland 	nfsrvd_lookup,
    220  1.1  dholland 	nfsrvd_lookup,
    221  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    222  1.1  dholland 	nfsrvd_open,
    223  1.1  dholland 	nfsrvd_openattr,
    224  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    225  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    226  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    227  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    228  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    229  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    230  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    231  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    232  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    233  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    234  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    235  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    236  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    237  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    238  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    239  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    240  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    241  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    242  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    243  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    244  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    245  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    246  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    247  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    248  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    249  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    250  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    251  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    252  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    253  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    254  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    255  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    256  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    257  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    258  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    259  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    260  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    261  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    262  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    263  1.1  dholland };
    264  1.1  dholland 
    265  1.2  pgoyette int (*nfsrv4_ops2[NFSV41_NOPS])(struct nfsrv_descript *,
    266  1.1  dholland     int, vnode_t , vnode_t , NFSPROC_T *,
    267  1.1  dholland     struct nfsexstuff *, struct nfsexstuff *) = {
    268  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    269  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    270  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    271  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    272  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    273  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    274  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    275  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    276  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    277  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    278  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    279  1.1  dholland 	nfsrvd_link,
    280  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    281  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    282  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    283  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    284  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    285  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    286  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    287  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    288  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    289  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    290  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    291  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    292  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    293  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    294  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    295  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    296  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    297  1.1  dholland 	nfsrvd_rename,
    298  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    299  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    300  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    301  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    302  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    303  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    304  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    305  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    306  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    307  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    308  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    309  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    310  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    311  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    312  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    313  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    314  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    315  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    316  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    317  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    318  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    319  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    320  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    321  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    322  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    323  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    324  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    325  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    326  1.2  pgoyette 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    327  1.1  dholland };
    328  1.1  dholland #endif	/* !APPLEKEXT */
    329  1.1  dholland 
    330  1.1  dholland /*
    331  1.1  dholland  * Static array that defines which nfs rpc's are nonidempotent
    332  1.1  dholland  */
    333  1.1  dholland static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
    334  1.1  dholland 	FALSE,
    335  1.1  dholland 	FALSE,
    336  1.1  dholland 	TRUE,
    337  1.1  dholland 	FALSE,
    338  1.1  dholland 	FALSE,
    339  1.1  dholland 	FALSE,
    340  1.1  dholland 	FALSE,
    341  1.1  dholland 	TRUE,
    342  1.1  dholland 	TRUE,
    343  1.1  dholland 	TRUE,
    344  1.1  dholland 	TRUE,
    345  1.1  dholland 	TRUE,
    346  1.1  dholland 	TRUE,
    347  1.1  dholland 	TRUE,
    348  1.1  dholland 	TRUE,
    349  1.1  dholland 	TRUE,
    350  1.1  dholland 	FALSE,
    351  1.1  dholland 	FALSE,
    352  1.1  dholland 	FALSE,
    353  1.1  dholland 	FALSE,
    354  1.1  dholland 	FALSE,
    355  1.1  dholland 	FALSE,
    356  1.1  dholland };
    357  1.1  dholland 
    358  1.1  dholland /*
    359  1.1  dholland  * This static array indicates whether or not the RPC modifies the
    360  1.1  dholland  * file system.
    361  1.1  dholland  */
    362  1.1  dholland static int nfs_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
    363  1.1  dholland     1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
    364  1.1  dholland     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
    365  1.1  dholland 
    366  1.1  dholland /* local functions */
    367  1.1  dholland static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
    368  1.2  pgoyette     u_char *tag, int taglen, u_int32_t minorvers, NFSPROC_T *p);
    369  1.1  dholland 
    370  1.1  dholland 
    371  1.1  dholland /*
    372  1.1  dholland  * This static array indicates which server procedures require the extra
    373  1.1  dholland  * arguments to return the current file handle for V2, 3.
    374  1.1  dholland  */
    375  1.1  dholland static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
    376  1.1  dholland 	1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
    377  1.1  dholland 
    378  1.2  pgoyette extern struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS];
    379  1.1  dholland 
    380  1.1  dholland static int nfsv3to4op[NFS_V3NPROCS] = {
    381  1.1  dholland 	NFSPROC_NULL,
    382  1.1  dholland 	NFSV4OP_GETATTR,
    383  1.1  dholland 	NFSV4OP_SETATTR,
    384  1.1  dholland 	NFSV4OP_LOOKUP,
    385  1.1  dholland 	NFSV4OP_ACCESS,
    386  1.1  dholland 	NFSV4OP_READLINK,
    387  1.1  dholland 	NFSV4OP_READ,
    388  1.1  dholland 	NFSV4OP_WRITE,
    389  1.1  dholland 	NFSV4OP_V3CREATE,
    390  1.1  dholland 	NFSV4OP_MKDIR,
    391  1.1  dholland 	NFSV4OP_SYMLINK,
    392  1.1  dholland 	NFSV4OP_MKNOD,
    393  1.1  dholland 	NFSV4OP_REMOVE,
    394  1.1  dholland 	NFSV4OP_RMDIR,
    395  1.1  dholland 	NFSV4OP_RENAME,
    396  1.1  dholland 	NFSV4OP_LINK,
    397  1.1  dholland 	NFSV4OP_READDIR,
    398  1.1  dholland 	NFSV4OP_READDIRPLUS,
    399  1.1  dholland 	NFSV4OP_FSSTAT,
    400  1.1  dholland 	NFSV4OP_FSINFO,
    401  1.1  dholland 	NFSV4OP_PATHCONF,
    402  1.1  dholland 	NFSV4OP_COMMIT,
    403  1.1  dholland };
    404  1.1  dholland 
    405  1.2  pgoyette static struct mtx nfsrvd_statmtx;
    406  1.2  pgoyette MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
    407  1.2  pgoyette 
    408  1.2  pgoyette static void
    409  1.2  pgoyette nfsrvd_statstart(int op, struct bintime *now)
    410  1.2  pgoyette {
    411  1.2  pgoyette 	if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
    412  1.2  pgoyette 		printf("%s: op %d invalid\n", __func__, op);
    413  1.2  pgoyette 		return;
    414  1.2  pgoyette 	}
    415  1.2  pgoyette 
    416  1.2  pgoyette 	mtx_lock(&nfsrvd_statmtx);
    417  1.2  pgoyette 	if (nfsstatsv1.srvstartcnt == nfsstatsv1.srvdonecnt) {
    418  1.2  pgoyette 		if (now != NULL)
    419  1.2  pgoyette 			nfsstatsv1.busyfrom = *now;
    420  1.2  pgoyette 		else
    421  1.2  pgoyette 			binuptime(&nfsstatsv1.busyfrom);
    422  1.2  pgoyette 
    423  1.2  pgoyette 	}
    424  1.2  pgoyette 	nfsstatsv1.srvrpccnt[op]++;
    425  1.2  pgoyette 	nfsstatsv1.srvstartcnt++;
    426  1.2  pgoyette 	mtx_unlock(&nfsrvd_statmtx);
    427  1.2  pgoyette 
    428  1.2  pgoyette }
    429  1.2  pgoyette 
    430  1.2  pgoyette static void
    431  1.2  pgoyette nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
    432  1.2  pgoyette     struct bintime *then)
    433  1.2  pgoyette {
    434  1.2  pgoyette 	struct bintime dt, lnow;
    435  1.2  pgoyette 
    436  1.2  pgoyette 	if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
    437  1.2  pgoyette 		printf("%s: op %d invalid\n", __func__, op);
    438  1.2  pgoyette 		return;
    439  1.2  pgoyette 	}
    440  1.2  pgoyette 
    441  1.2  pgoyette 	if (now == NULL) {
    442  1.2  pgoyette 		now = &lnow;
    443  1.2  pgoyette 		binuptime(now);
    444  1.2  pgoyette 	}
    445  1.2  pgoyette 
    446  1.2  pgoyette 	mtx_lock(&nfsrvd_statmtx);
    447  1.2  pgoyette 
    448  1.2  pgoyette 	nfsstatsv1.srvbytes[op] += bytes;
    449  1.2  pgoyette 	nfsstatsv1.srvops[op]++;
    450  1.2  pgoyette 
    451  1.2  pgoyette 	if (then != NULL) {
    452  1.2  pgoyette 		dt = *now;
    453  1.2  pgoyette 		bintime_sub(&dt, then);
    454  1.2  pgoyette 		bintime_add(&nfsstatsv1.srvduration[op], &dt);
    455  1.2  pgoyette 	}
    456  1.2  pgoyette 
    457  1.2  pgoyette 	dt = *now;
    458  1.2  pgoyette 	bintime_sub(&dt, &nfsstatsv1.busyfrom);
    459  1.2  pgoyette 	bintime_add(&nfsstatsv1.busytime, &dt);
    460  1.2  pgoyette 	nfsstatsv1.busyfrom = *now;
    461  1.2  pgoyette 
    462  1.2  pgoyette 	nfsstatsv1.srvdonecnt++;
    463  1.2  pgoyette 
    464  1.2  pgoyette 	mtx_unlock(&nfsrvd_statmtx);
    465  1.2  pgoyette }
    466  1.2  pgoyette 
    467  1.1  dholland /*
    468  1.1  dholland  * Do an RPC. Basically, get the file handles translated to vnode pointers
    469  1.1  dholland  * and then call the appropriate server routine. The server routines are
    470  1.1  dholland  * split into groups, based on whether they use a file handle or file
    471  1.1  dholland  * handle plus name or ...
    472  1.1  dholland  * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
    473  1.1  dholland  */
    474  1.1  dholland APPLESTATIC void
    475  1.2  pgoyette nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
    476  1.2  pgoyette     u_int32_t minorvers, NFSPROC_T *p)
    477  1.1  dholland {
    478  1.1  dholland 	int error = 0, lktype;
    479  1.1  dholland 	vnode_t vp;
    480  1.1  dholland 	mount_t mp = NULL;
    481  1.1  dholland 	struct nfsrvfh fh;
    482  1.1  dholland 	struct nfsexstuff nes;
    483  1.1  dholland 
    484  1.1  dholland 	/*
    485  1.1  dholland 	 * Get a locked vnode for the first file handle
    486  1.1  dholland 	 */
    487  1.1  dholland 	if (!(nd->nd_flag & ND_NFSV4)) {
    488  1.1  dholland 		KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
    489  1.1  dholland 		/*
    490  1.1  dholland 		 * For NFSv3, if the malloc/mget allocation is near limits,
    491  1.1  dholland 		 * return NFSERR_DELAY.
    492  1.1  dholland 		 */
    493  1.1  dholland 		if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
    494  1.1  dholland 			nd->nd_repstat = NFSERR_DELAY;
    495  1.1  dholland 			vp = NULL;
    496  1.1  dholland 		} else {
    497  1.1  dholland 			error = nfsrv_mtofh(nd, &fh);
    498  1.1  dholland 			if (error) {
    499  1.1  dholland 				if (error != EBADRPC)
    500  1.1  dholland 					printf("nfs dorpc err1=%d\n", error);
    501  1.1  dholland 				nd->nd_repstat = NFSERR_GARBAGE;
    502  1.1  dholland 				goto out;
    503  1.1  dholland 			}
    504  1.1  dholland 			if (nd->nd_procnum == NFSPROC_READ ||
    505  1.1  dholland 			    nd->nd_procnum == NFSPROC_WRITE ||
    506  1.1  dholland 			    nd->nd_procnum == NFSPROC_READDIR ||
    507  1.2  pgoyette 			    nd->nd_procnum == NFSPROC_READDIRPLUS ||
    508  1.1  dholland 			    nd->nd_procnum == NFSPROC_READLINK ||
    509  1.1  dholland 			    nd->nd_procnum == NFSPROC_GETATTR ||
    510  1.2  pgoyette 			    nd->nd_procnum == NFSPROC_ACCESS ||
    511  1.2  pgoyette 			    nd->nd_procnum == NFSPROC_FSSTAT ||
    512  1.2  pgoyette 			    nd->nd_procnum == NFSPROC_FSINFO)
    513  1.1  dholland 				lktype = LK_SHARED;
    514  1.1  dholland 			else
    515  1.1  dholland 				lktype = LK_EXCLUSIVE;
    516  1.1  dholland 			if (nd->nd_flag & ND_PUBLOOKUP)
    517  1.1  dholland 				nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
    518  1.1  dholland 				    &mp, nfs_writerpc[nd->nd_procnum], p);
    519  1.1  dholland 			else
    520  1.1  dholland 				nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
    521  1.1  dholland 				    &mp, nfs_writerpc[nd->nd_procnum], p);
    522  1.1  dholland 			if (nd->nd_repstat == NFSERR_PROGNOTV4)
    523  1.1  dholland 				goto out;
    524  1.1  dholland 		}
    525  1.1  dholland 	}
    526  1.1  dholland 
    527  1.1  dholland 	/*
    528  1.1  dholland 	 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
    529  1.1  dholland 	 * cache, as required.
    530  1.1  dholland 	 * For V4, nfsrvd_compound() does this.
    531  1.1  dholland 	 */
    532  1.1  dholland 	if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
    533  1.1  dholland 		nd->nd_flag |= ND_SAVEREPLY;
    534  1.1  dholland 
    535  1.1  dholland 	nfsrvd_rephead(nd);
    536  1.1  dholland 	/*
    537  1.1  dholland 	 * If nd_repstat is non-zero, just fill in the reply status
    538  1.1  dholland 	 * to complete the RPC reply for V2. Otherwise, you must do
    539  1.1  dholland 	 * the RPC.
    540  1.1  dholland 	 */
    541  1.1  dholland 	if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
    542  1.1  dholland 		*nd->nd_errp = nfsd_errmap(nd);
    543  1.2  pgoyette 		nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL);
    544  1.2  pgoyette 		nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
    545  1.2  pgoyette 		   /*now*/ NULL, /*then*/ NULL);
    546  1.1  dholland 		if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
    547  1.1  dholland 			vn_finished_write(mp);
    548  1.1  dholland 		goto out;
    549  1.1  dholland 	}
    550  1.1  dholland 
    551  1.1  dholland 	/*
    552  1.1  dholland 	 * Now the procedure can be performed. For V4, nfsrvd_compound()
    553  1.1  dholland 	 * works through the sub-rpcs, otherwise just call the procedure.
    554  1.1  dholland 	 * The procedures are in three groups with different arguments.
    555  1.1  dholland 	 * The group is indicated by the value in nfs_retfh[].
    556  1.1  dholland 	 */
    557  1.1  dholland 	if (nd->nd_flag & ND_NFSV4) {
    558  1.2  pgoyette 		nfsrvd_compound(nd, isdgram, tag, taglen, minorvers, p);
    559  1.1  dholland 	} else {
    560  1.2  pgoyette 		struct bintime start_time;
    561  1.2  pgoyette 
    562  1.2  pgoyette 		binuptime(&start_time);
    563  1.2  pgoyette 		nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time);
    564  1.2  pgoyette 
    565  1.1  dholland 		if (nfs_retfh[nd->nd_procnum] == 1) {
    566  1.1  dholland 			if (vp)
    567  1.1  dholland 				NFSVOPUNLOCK(vp, 0);
    568  1.1  dholland 			error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
    569  1.1  dholland 			    vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes);
    570  1.1  dholland 		} else if (nfs_retfh[nd->nd_procnum] == 2) {
    571  1.1  dholland 			error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
    572  1.1  dholland 			    vp, NULL, p, &nes, NULL);
    573  1.1  dholland 		} else {
    574  1.1  dholland 			error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
    575  1.1  dholland 			    vp, p, &nes);
    576  1.1  dholland 		}
    577  1.1  dholland 		if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
    578  1.1  dholland 			vn_finished_write(mp);
    579  1.2  pgoyette 
    580  1.2  pgoyette 		nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
    581  1.2  pgoyette 		    /*now*/ NULL, /*then*/ &start_time);
    582  1.1  dholland 	}
    583  1.1  dholland 	if (error) {
    584  1.1  dholland 		if (error != EBADRPC)
    585  1.1  dholland 			printf("nfs dorpc err2=%d\n", error);
    586  1.1  dholland 		nd->nd_repstat = NFSERR_GARBAGE;
    587  1.1  dholland 	}
    588  1.1  dholland 	*nd->nd_errp = nfsd_errmap(nd);
    589  1.1  dholland 
    590  1.1  dholland 	/*
    591  1.1  dholland 	 * Don't cache certain reply status values.
    592  1.1  dholland 	 */
    593  1.1  dholland 	if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
    594  1.1  dholland 	    (nd->nd_repstat == NFSERR_GARBAGE ||
    595  1.1  dholland 	     nd->nd_repstat == NFSERR_BADXDR ||
    596  1.1  dholland 	     nd->nd_repstat == NFSERR_MOVED ||
    597  1.1  dholland 	     nd->nd_repstat == NFSERR_DELAY ||
    598  1.1  dholland 	     nd->nd_repstat == NFSERR_BADSEQID ||
    599  1.1  dholland 	     nd->nd_repstat == NFSERR_RESOURCE ||
    600  1.1  dholland 	     nd->nd_repstat == NFSERR_SERVERFAULT ||
    601  1.1  dholland 	     nd->nd_repstat == NFSERR_STALECLIENTID ||
    602  1.1  dholland 	     nd->nd_repstat == NFSERR_STALESTATEID ||
    603  1.1  dholland 	     nd->nd_repstat == NFSERR_OLDSTATEID ||
    604  1.1  dholland 	     nd->nd_repstat == NFSERR_BADSTATEID ||
    605  1.1  dholland 	     nd->nd_repstat == NFSERR_GRACE ||
    606  1.1  dholland 	     nd->nd_repstat == NFSERR_NOGRACE))
    607  1.1  dholland 		nd->nd_flag &= ~ND_SAVEREPLY;
    608  1.1  dholland 
    609  1.1  dholland out:
    610  1.1  dholland 	NFSEXITCODE2(0, nd);
    611  1.1  dholland }
    612  1.1  dholland 
    613  1.1  dholland /*
    614  1.1  dholland  * Breaks down a compound RPC request and calls the server routines for
    615  1.1  dholland  * the subprocedures.
    616  1.1  dholland  * Some suboperations are performed directly here to simplify file handle<-->
    617  1.1  dholland  * vnode pointer handling.
    618  1.1  dholland  */
    619  1.1  dholland static void
    620  1.2  pgoyette nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
    621  1.2  pgoyette     int taglen, u_int32_t minorvers, NFSPROC_T *p)
    622  1.1  dholland {
    623  1.2  pgoyette 	int i, lktype, op, op0 = 0, statsinprog = 0;
    624  1.1  dholland 	u_int32_t *tl;
    625  1.1  dholland 	struct nfsclient *clp, *nclp;
    626  1.2  pgoyette 	int numops, error = 0, igotlock;
    627  1.2  pgoyette 	u_int32_t retops = 0, *retopsp = NULL, *repp;
    628  1.1  dholland 	vnode_t vp, nvp, savevp;
    629  1.1  dholland 	struct nfsrvfh fh;
    630  1.1  dholland 	mount_t new_mp, temp_mp = NULL;
    631  1.1  dholland 	struct ucred *credanon;
    632  1.1  dholland 	struct nfsexstuff nes, vpnes, savevpnes;
    633  1.1  dholland 	fsid_t cur_fsid, save_fsid;
    634  1.1  dholland 	static u_int64_t compref = 0;
    635  1.2  pgoyette 	struct bintime start_time;
    636  1.1  dholland 
    637  1.1  dholland 	NFSVNO_EXINIT(&vpnes);
    638  1.1  dholland 	NFSVNO_EXINIT(&savevpnes);
    639  1.1  dholland 	/*
    640  1.1  dholland 	 * Put the seq# of the current compound RPC in nfsrv_descript.
    641  1.1  dholland 	 * (This is used by nfsrv_checkgetattr(), to see if the write
    642  1.1  dholland 	 *  delegation was created by the same compound RPC as the one
    643  1.1  dholland 	 *  with that Getattr in it.)
    644  1.1  dholland 	 * Don't worry about the 64bit number wrapping around. It ain't
    645  1.1  dholland 	 * gonna happen before this server gets shut down/rebooted.
    646  1.1  dholland 	 */
    647  1.1  dholland 	nd->nd_compref = compref++;
    648  1.1  dholland 
    649  1.1  dholland 	/*
    650  1.1  dholland 	 * Check for and optionally get a lock on the root. This lock means that
    651  1.1  dholland 	 * no nfsd will be fiddling with the V4 file system and state stuff. It
    652  1.1  dholland 	 * is required when the V4 root is being changed, the stable storage
    653  1.1  dholland 	 * restart file is being updated, or callbacks are being done.
    654  1.1  dholland 	 * When any of the nfsd are processing an NFSv4 compound RPC, they must
    655  1.1  dholland 	 * either hold a reference count (nfs_usecnt) or the lock. When
    656  1.1  dholland 	 * nfsrv_unlock() is called to release the lock, it can optionally
    657  1.1  dholland 	 * also get a reference count, which saves the need for a call to
    658  1.1  dholland 	 * nfsrv_getref() after nfsrv_unlock().
    659  1.1  dholland 	 */
    660  1.1  dholland 	/*
    661  1.1  dholland 	 * First, check to see if we need to wait for an update lock.
    662  1.1  dholland 	 */
    663  1.1  dholland 	igotlock = 0;
    664  1.1  dholland 	NFSLOCKV4ROOTMUTEX();
    665  1.1  dholland 	if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
    666  1.1  dholland 		igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
    667  1.1  dholland 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
    668  1.1  dholland 	else
    669  1.1  dholland 		igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
    670  1.1  dholland 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
    671  1.1  dholland 	NFSUNLOCKV4ROOTMUTEX();
    672  1.1  dholland 	if (igotlock) {
    673  1.1  dholland 		/*
    674  1.1  dholland 		 * If I got the lock, I can update the stable storage file.
    675  1.1  dholland 		 * Done when the grace period is over or a client has long
    676  1.1  dholland 		 * since expired.
    677  1.1  dholland 		 */
    678  1.1  dholland 		nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
    679  1.1  dholland 		if ((nfsrv_stablefirst.nsf_flags &
    680  1.1  dholland 		    (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
    681  1.1  dholland 			nfsrv_updatestable(p);
    682  1.1  dholland 
    683  1.1  dholland 		/*
    684  1.1  dholland 		 * If at least one client has long since expired, search
    685  1.1  dholland 		 * the client list for them, write a REVOKE record on the
    686  1.1  dholland 		 * stable storage file and then remove them from the client
    687  1.1  dholland 		 * list.
    688  1.1  dholland 		 */
    689  1.1  dholland 		if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
    690  1.1  dholland 			nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
    691  1.2  pgoyette 			for (i = 0; i < nfsrv_clienthashsize; i++) {
    692  1.1  dholland 			    LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
    693  1.1  dholland 				nclp) {
    694  1.1  dholland 				if (clp->lc_flags & LCL_EXPIREIT) {
    695  1.1  dholland 				    if (!LIST_EMPTY(&clp->lc_open) ||
    696  1.1  dholland 					!LIST_EMPTY(&clp->lc_deleg))
    697  1.1  dholland 					nfsrv_writestable(clp->lc_id,
    698  1.1  dholland 					    clp->lc_idlen, NFSNST_REVOKE, p);
    699  1.1  dholland 				    nfsrv_cleanclient(clp, p);
    700  1.1  dholland 				    nfsrv_freedeleglist(&clp->lc_deleg);
    701  1.1  dholland 				    nfsrv_freedeleglist(&clp->lc_olddeleg);
    702  1.1  dholland 				    LIST_REMOVE(clp, lc_hash);
    703  1.1  dholland 				    nfsrv_zapclient(clp, p);
    704  1.1  dholland 				}
    705  1.1  dholland 			    }
    706  1.1  dholland 			}
    707  1.1  dholland 		}
    708  1.1  dholland 		NFSLOCKV4ROOTMUTEX();
    709  1.1  dholland 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
    710  1.1  dholland 		NFSUNLOCKV4ROOTMUTEX();
    711  1.1  dholland 	} else {
    712  1.1  dholland 		/*
    713  1.1  dholland 		 * If we didn't get the lock, we need to get a refcnt,
    714  1.1  dholland 		 * which also checks for and waits for the lock.
    715  1.1  dholland 		 */
    716  1.1  dholland 		NFSLOCKV4ROOTMUTEX();
    717  1.1  dholland 		nfsv4_getref(&nfsv4rootfs_lock, NULL,
    718  1.1  dholland 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
    719  1.1  dholland 		NFSUNLOCKV4ROOTMUTEX();
    720  1.1  dholland 	}
    721  1.1  dholland 
    722  1.1  dholland 	/*
    723  1.1  dholland 	 * If flagged, search for open owners that haven't had any opens
    724  1.1  dholland 	 * for a long time.
    725  1.1  dholland 	 */
    726  1.1  dholland 	if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
    727  1.1  dholland 		nfsrv_throwawayopens(p);
    728  1.1  dholland 	}
    729  1.1  dholland 
    730  1.1  dholland 	savevp = vp = NULL;
    731  1.1  dholland 	save_fsid.val[0] = save_fsid.val[1] = 0;
    732  1.1  dholland 	cur_fsid.val[0] = cur_fsid.val[1] = 0;
    733  1.2  pgoyette 
    734  1.2  pgoyette 	/* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
    735  1.1  dholland 	if (taglen < 0) {
    736  1.1  dholland 		error = EBADRPC;
    737  1.1  dholland 		goto nfsmout;
    738  1.1  dholland 	}
    739  1.2  pgoyette 
    740  1.1  dholland 	(void) nfsm_strtom(nd, tag, taglen);
    741  1.1  dholland 	NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
    742  1.2  pgoyette 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
    743  1.2  pgoyette 	if (minorvers != NFSV4_MINORVERSION && minorvers != NFSV41_MINORVERSION)
    744  1.1  dholland 		nd->nd_repstat = NFSERR_MINORVERMISMATCH;
    745  1.1  dholland 	if (nd->nd_repstat)
    746  1.1  dholland 		numops = 0;
    747  1.1  dholland 	else
    748  1.1  dholland 		numops = fxdr_unsigned(int, *tl);
    749  1.1  dholland 	/*
    750  1.1  dholland 	 * Loop around doing the sub ops.
    751  1.1  dholland 	 * vp - is an unlocked vnode pointer for the CFH
    752  1.1  dholland 	 * savevp - is an unlocked vnode pointer for the SAVEDFH
    753  1.1  dholland 	 * (at some future date, it might turn out to be more appropriate
    754  1.1  dholland 	 *  to keep the file handles instead of vnode pointers?)
    755  1.1  dholland 	 * savevpnes and vpnes - are the export flags for the above.
    756  1.1  dholland 	 */
    757  1.1  dholland 	for (i = 0; i < numops; i++) {
    758  1.1  dholland 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
    759  1.1  dholland 		NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
    760  1.1  dholland 		*repp = *tl;
    761  1.1  dholland 		op = fxdr_unsigned(int, *tl);
    762  1.2  pgoyette 		NFSD_DEBUG(4, "op=%d\n", op);
    763  1.2  pgoyette 
    764  1.2  pgoyette 		binuptime(&start_time);
    765  1.2  pgoyette 		nfsrvd_statstart(op, &start_time);
    766  1.2  pgoyette 		statsinprog = 1;
    767  1.2  pgoyette 
    768  1.2  pgoyette 		if (op < NFSV4OP_ACCESS ||
    769  1.2  pgoyette 		    (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
    770  1.2  pgoyette 		    (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV41) != 0)) {
    771  1.1  dholland 			nd->nd_repstat = NFSERR_OPILLEGAL;
    772  1.1  dholland 			*repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
    773  1.1  dholland 			*repp = nfsd_errmap(nd);
    774  1.1  dholland 			retops++;
    775  1.1  dholland 			break;
    776  1.1  dholland 		} else {
    777  1.1  dholland 			repp++;
    778  1.1  dholland 		}
    779  1.2  pgoyette 		if (i == 0)
    780  1.2  pgoyette 			op0 = op;
    781  1.2  pgoyette 		if (i == numops - 1)
    782  1.2  pgoyette 			nd->nd_flag |= ND_LASTOP;
    783  1.1  dholland 
    784  1.1  dholland 		/*
    785  1.1  dholland 		 * Check for a referral on the current FH and, if so, return
    786  1.1  dholland 		 * NFSERR_MOVED for all ops that allow it, except Getattr.
    787  1.1  dholland 		 */
    788  1.1  dholland 		if (vp != NULL && op != NFSV4OP_GETATTR &&
    789  1.1  dholland 		    nfsv4root_getreferral(vp, NULL, 0) != NULL &&
    790  1.1  dholland 		    nfsrv_errmoved(op)) {
    791  1.1  dholland 			nd->nd_repstat = NFSERR_MOVED;
    792  1.1  dholland 			*repp = nfsd_errmap(nd);
    793  1.1  dholland 			retops++;
    794  1.1  dholland 			break;
    795  1.1  dholland 		}
    796  1.1  dholland 
    797  1.2  pgoyette 		/*
    798  1.2  pgoyette 		 * For NFSv4.1, check for a Sequence Operation being first
    799  1.2  pgoyette 		 * or one of the other allowed operations by itself.
    800  1.2  pgoyette 		 */
    801  1.2  pgoyette 		if ((nd->nd_flag & ND_NFSV41) != 0) {
    802  1.2  pgoyette 			if (i != 0 && op == NFSV4OP_SEQUENCE)
    803  1.2  pgoyette 				nd->nd_repstat = NFSERR_SEQUENCEPOS;
    804  1.2  pgoyette 			else if (i == 0 && op != NFSV4OP_SEQUENCE &&
    805  1.2  pgoyette 			    op != NFSV4OP_EXCHANGEID &&
    806  1.2  pgoyette 			    op != NFSV4OP_CREATESESSION &&
    807  1.2  pgoyette 			    op != NFSV4OP_BINDCONNTOSESS &&
    808  1.2  pgoyette 			    op != NFSV4OP_DESTROYCLIENTID &&
    809  1.2  pgoyette 			    op != NFSV4OP_DESTROYSESSION)
    810  1.2  pgoyette 				nd->nd_repstat = NFSERR_OPNOTINSESS;
    811  1.2  pgoyette 			else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
    812  1.2  pgoyette 				nd->nd_repstat = NFSERR_NOTONLYOP;
    813  1.2  pgoyette 			if (nd->nd_repstat != 0) {
    814  1.2  pgoyette 				*repp = nfsd_errmap(nd);
    815  1.2  pgoyette 				retops++;
    816  1.2  pgoyette 				break;
    817  1.2  pgoyette 			}
    818  1.2  pgoyette 		}
    819  1.2  pgoyette 
    820  1.1  dholland 		nd->nd_procnum = op;
    821  1.1  dholland 		/*
    822  1.1  dholland 		 * If over flood level, reply NFSERR_RESOURCE, if at the first
    823  1.1  dholland 		 * Op. (Since a client recovery from NFSERR_RESOURCE can get
    824  1.1  dholland 		 * really nasty for certain Op sequences, I'll play it safe
    825  1.1  dholland 		 * and only return the error at the beginning.) The cache
    826  1.1  dholland 		 * will still function over flood level, but uses lots of
    827  1.1  dholland 		 * mbufs.)
    828  1.1  dholland 		 * If nfsrv_mallocmget_limit() returns True, the system is near
    829  1.1  dholland 		 * to its limit for memory that malloc()/mget() can allocate.
    830  1.1  dholland 		 */
    831  1.2  pgoyette 		if (i == 0 && (nd->nd_rp == NULL ||
    832  1.2  pgoyette 		    nd->nd_rp->rc_refcnt == 0) &&
    833  1.1  dholland 		    (nfsrv_mallocmget_limit() ||
    834  1.1  dholland 		     nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
    835  1.2  pgoyette 			if (nfsrc_tcpsavedreplies > nfsrc_floodlevel)
    836  1.2  pgoyette 				printf("nfsd server cache flooded, try "
    837  1.2  pgoyette 				    "increasing vfs.nfsd.tcphighwater\n");
    838  1.1  dholland 			nd->nd_repstat = NFSERR_RESOURCE;
    839  1.1  dholland 			*repp = nfsd_errmap(nd);
    840  1.1  dholland 			if (op == NFSV4OP_SETATTR) {
    841  1.1  dholland 				/*
    842  1.1  dholland 				 * Setattr replies require a bitmap.
    843  1.1  dholland 				 * even for errors like these.
    844  1.1  dholland 				 */
    845  1.1  dholland 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
    846  1.1  dholland 				*tl = 0;
    847  1.1  dholland 			}
    848  1.1  dholland 			retops++;
    849  1.1  dholland 			break;
    850  1.1  dholland 		}
    851  1.1  dholland 		if (nfsv4_opflag[op].savereply)
    852  1.1  dholland 			nd->nd_flag |= ND_SAVEREPLY;
    853  1.1  dholland 		switch (op) {
    854  1.1  dholland 		case NFSV4OP_PUTFH:
    855  1.1  dholland 			error = nfsrv_mtofh(nd, &fh);
    856  1.1  dholland 			if (error)
    857  1.1  dholland 				goto nfsmout;
    858  1.1  dholland 			if (!nd->nd_repstat)
    859  1.1  dholland 				nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
    860  1.1  dholland 				    NULL, 0, p);
    861  1.1  dholland 			/* For now, allow this for non-export FHs */
    862  1.1  dholland 			if (!nd->nd_repstat) {
    863  1.1  dholland 				if (vp)
    864  1.1  dholland 					vrele(vp);
    865  1.1  dholland 				vp = nvp;
    866  1.1  dholland 				cur_fsid = vp->v_mount->mnt_stat.f_fsid;
    867  1.1  dholland 				NFSVOPUNLOCK(vp, 0);
    868  1.1  dholland 				vpnes = nes;
    869  1.1  dholland 			}
    870  1.1  dholland 			break;
    871  1.1  dholland 		case NFSV4OP_PUTPUBFH:
    872  1.1  dholland 			if (nfs_pubfhset)
    873  1.1  dholland 			    nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
    874  1.1  dholland 				&nes, NULL, 0, p);
    875  1.1  dholland 			else
    876  1.1  dholland 			    nd->nd_repstat = NFSERR_NOFILEHANDLE;
    877  1.1  dholland 			if (!nd->nd_repstat) {
    878  1.1  dholland 				if (vp)
    879  1.1  dholland 					vrele(vp);
    880  1.1  dholland 				vp = nvp;
    881  1.1  dholland 				cur_fsid = vp->v_mount->mnt_stat.f_fsid;
    882  1.1  dholland 				NFSVOPUNLOCK(vp, 0);
    883  1.1  dholland 				vpnes = nes;
    884  1.1  dholland 			}
    885  1.1  dholland 			break;
    886  1.1  dholland 		case NFSV4OP_PUTROOTFH:
    887  1.1  dholland 			if (nfs_rootfhset) {
    888  1.1  dholland 				nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
    889  1.1  dholland 				    &nes, NULL, 0, p);
    890  1.1  dholland 				if (!nd->nd_repstat) {
    891  1.1  dholland 					if (vp)
    892  1.1  dholland 						vrele(vp);
    893  1.1  dholland 					vp = nvp;
    894  1.1  dholland 					cur_fsid = vp->v_mount->mnt_stat.f_fsid;
    895  1.1  dholland 					NFSVOPUNLOCK(vp, 0);
    896  1.1  dholland 					vpnes = nes;
    897  1.1  dholland 				}
    898  1.1  dholland 			} else
    899  1.1  dholland 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
    900  1.1  dholland 			break;
    901  1.1  dholland 		case NFSV4OP_SAVEFH:
    902  1.1  dholland 			if (vp && NFSVNO_EXPORTED(&vpnes)) {
    903  1.1  dholland 				nd->nd_repstat = 0;
    904  1.1  dholland 				/* If vp == savevp, a no-op */
    905  1.1  dholland 				if (vp != savevp) {
    906  1.1  dholland 					if (savevp)
    907  1.1  dholland 						vrele(savevp);
    908  1.1  dholland 					VREF(vp);
    909  1.1  dholland 					savevp = vp;
    910  1.1  dholland 					savevpnes = vpnes;
    911  1.1  dholland 					save_fsid = cur_fsid;
    912  1.1  dholland 				}
    913  1.1  dholland 			} else {
    914  1.1  dholland 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
    915  1.1  dholland 			}
    916  1.1  dholland 			break;
    917  1.1  dholland 		case NFSV4OP_RESTOREFH:
    918  1.1  dholland 			if (savevp) {
    919  1.1  dholland 				nd->nd_repstat = 0;
    920  1.1  dholland 				/* If vp == savevp, a no-op */
    921  1.1  dholland 				if (vp != savevp) {
    922  1.1  dholland 					VREF(savevp);
    923  1.1  dholland 					vrele(vp);
    924  1.1  dholland 					vp = savevp;
    925  1.1  dholland 					vpnes = savevpnes;
    926  1.1  dholland 					cur_fsid = save_fsid;
    927  1.1  dholland 				}
    928  1.1  dholland 			} else {
    929  1.1  dholland 				nd->nd_repstat = NFSERR_RESTOREFH;
    930  1.1  dholland 			}
    931  1.1  dholland 			break;
    932  1.1  dholland 		default:
    933  1.1  dholland 		    /*
    934  1.1  dholland 		     * Allow a Lookup, Getattr, GetFH, Secinfo on an
    935  1.1  dholland 		     * non-exported directory if
    936  1.1  dholland 		     * nfs_rootfhset. Do I need to allow any other Ops?
    937  1.1  dholland 		     * (You can only have a non-exported vpnes if
    938  1.1  dholland 		     *  nfs_rootfhset is true. See nfsd_fhtovp())
    939  1.1  dholland 		     * Allow AUTH_SYS to be used for file systems
    940  1.1  dholland 		     * exported GSS only for certain Ops, to allow
    941  1.1  dholland 		     * clients to do mounts more easily.
    942  1.1  dholland 		     */
    943  1.1  dholland 		    if (nfsv4_opflag[op].needscfh && vp) {
    944  1.1  dholland 			if (!NFSVNO_EXPORTED(&vpnes) &&
    945  1.1  dholland 			    op != NFSV4OP_LOOKUP &&
    946  1.1  dholland 			    op != NFSV4OP_GETATTR &&
    947  1.1  dholland 			    op != NFSV4OP_GETFH &&
    948  1.1  dholland 			    op != NFSV4OP_ACCESS &&
    949  1.1  dholland 			    op != NFSV4OP_READLINK &&
    950  1.1  dholland 			    op != NFSV4OP_SECINFO)
    951  1.1  dholland 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
    952  1.1  dholland 			else if (nfsvno_testexp(nd, &vpnes) &&
    953  1.1  dholland 			    op != NFSV4OP_LOOKUP &&
    954  1.1  dholland 			    op != NFSV4OP_GETFH &&
    955  1.1  dholland 			    op != NFSV4OP_GETATTR &&
    956  1.1  dholland 			    op != NFSV4OP_SECINFO)
    957  1.1  dholland 				nd->nd_repstat = NFSERR_WRONGSEC;
    958  1.1  dholland 			if (nd->nd_repstat) {
    959  1.1  dholland 				if (op == NFSV4OP_SETATTR) {
    960  1.1  dholland 				    /*
    961  1.1  dholland 				     * Setattr reply requires a bitmap
    962  1.1  dholland 				     * even for errors like these.
    963  1.1  dholland 				     */
    964  1.1  dholland 				    NFSM_BUILD(tl, u_int32_t *,
    965  1.1  dholland 					NFSX_UNSIGNED);
    966  1.1  dholland 				    *tl = 0;
    967  1.1  dholland 				}
    968  1.1  dholland 				break;
    969  1.1  dholland 			}
    970  1.1  dholland 		    }
    971  1.1  dholland 		    if (nfsv4_opflag[op].retfh == 1) {
    972  1.1  dholland 			if (!vp) {
    973  1.1  dholland 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
    974  1.1  dholland 				break;
    975  1.1  dholland 			}
    976  1.1  dholland 			VREF(vp);
    977  1.1  dholland 			if (nfsv4_opflag[op].modifyfs)
    978  1.1  dholland 				vn_start_write(vp, &temp_mp, V_WAIT);
    979  1.1  dholland 			error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
    980  1.1  dholland 			    &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes);
    981  1.1  dholland 			if (!error && !nd->nd_repstat) {
    982  1.1  dholland 			    if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
    983  1.1  dholland 				new_mp = nvp->v_mount;
    984  1.1  dholland 				if (cur_fsid.val[0] !=
    985  1.1  dholland 				    new_mp->mnt_stat.f_fsid.val[0] ||
    986  1.1  dholland 				    cur_fsid.val[1] !=
    987  1.1  dholland 				    new_mp->mnt_stat.f_fsid.val[1]) {
    988  1.1  dholland 				    /* crossed a server mount point */
    989  1.1  dholland 				    nd->nd_repstat = nfsvno_checkexp(new_mp,
    990  1.1  dholland 					nd->nd_nam, &nes, &credanon);
    991  1.1  dholland 				    if (!nd->nd_repstat)
    992  1.1  dholland 					nd->nd_repstat = nfsd_excred(nd,
    993  1.1  dholland 					    &nes, credanon);
    994  1.1  dholland 				    if (credanon != NULL)
    995  1.1  dholland 					crfree(credanon);
    996  1.1  dholland 				    if (!nd->nd_repstat) {
    997  1.1  dholland 					vpnes = nes;
    998  1.1  dholland 					cur_fsid = new_mp->mnt_stat.f_fsid;
    999  1.1  dholland 				    }
   1000  1.1  dholland 				}
   1001  1.1  dholland 				/* Lookup ops return a locked vnode */
   1002  1.1  dholland 				NFSVOPUNLOCK(nvp, 0);
   1003  1.1  dholland 			    }
   1004  1.1  dholland 			    if (!nd->nd_repstat) {
   1005  1.1  dholland 				    vrele(vp);
   1006  1.1  dholland 				    vp = nvp;
   1007  1.1  dholland 			    } else
   1008  1.1  dholland 				    vrele(nvp);
   1009  1.1  dholland 			}
   1010  1.1  dholland 			if (nfsv4_opflag[op].modifyfs)
   1011  1.1  dholland 				vn_finished_write(temp_mp);
   1012  1.1  dholland 		    } else if (nfsv4_opflag[op].retfh == 2) {
   1013  1.1  dholland 			if (vp == NULL || savevp == NULL) {
   1014  1.1  dholland 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
   1015  1.1  dholland 				break;
   1016  1.1  dholland 			} else if (cur_fsid.val[0] != save_fsid.val[0] ||
   1017  1.1  dholland 			    cur_fsid.val[1] != save_fsid.val[1]) {
   1018  1.1  dholland 				nd->nd_repstat = NFSERR_XDEV;
   1019  1.1  dholland 				break;
   1020  1.1  dholland 			}
   1021  1.1  dholland 			if (nfsv4_opflag[op].modifyfs)
   1022  1.1  dholland 				vn_start_write(savevp, &temp_mp, V_WAIT);
   1023  1.1  dholland 			if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
   1024  1.1  dholland 				VREF(vp);
   1025  1.1  dholland 				VREF(savevp);
   1026  1.1  dholland 				error = (*(nfsrv4_ops2[op]))(nd, isdgram,
   1027  1.1  dholland 				    savevp, vp, p, &savevpnes, &vpnes);
   1028  1.1  dholland 			} else
   1029  1.1  dholland 				nd->nd_repstat = NFSERR_PERM;
   1030  1.1  dholland 			if (nfsv4_opflag[op].modifyfs)
   1031  1.1  dholland 				vn_finished_write(temp_mp);
   1032  1.1  dholland 		    } else {
   1033  1.1  dholland 			if (nfsv4_opflag[op].retfh != 0)
   1034  1.1  dholland 				panic("nfsrvd_compound");
   1035  1.1  dholland 			if (nfsv4_opflag[op].needscfh) {
   1036  1.1  dholland 				if (vp != NULL) {
   1037  1.2  pgoyette 					lktype = nfsv4_opflag[op].lktype;
   1038  1.2  pgoyette 					if (nfsv4_opflag[op].modifyfs) {
   1039  1.1  dholland 						vn_start_write(vp, &temp_mp,
   1040  1.1  dholland 						    V_WAIT);
   1041  1.2  pgoyette 						if (op == NFSV4OP_WRITE &&
   1042  1.2  pgoyette 						    MNT_SHARED_WRITES(temp_mp))
   1043  1.2  pgoyette 							lktype = LK_SHARED;
   1044  1.2  pgoyette 					}
   1045  1.2  pgoyette 					if (NFSVOPLOCK(vp, lktype) == 0)
   1046  1.1  dholland 						VREF(vp);
   1047  1.1  dholland 					else
   1048  1.1  dholland 						nd->nd_repstat = NFSERR_PERM;
   1049  1.1  dholland 				} else {
   1050  1.1  dholland 					nd->nd_repstat = NFSERR_NOFILEHANDLE;
   1051  1.1  dholland 					if (op == NFSV4OP_SETATTR) {
   1052  1.1  dholland 						/*
   1053  1.1  dholland 						 * Setattr reply requires a
   1054  1.1  dholland 						 * bitmap even for errors like
   1055  1.1  dholland 						 * these.
   1056  1.1  dholland 						 */
   1057  1.1  dholland 						NFSM_BUILD(tl, u_int32_t *,
   1058  1.1  dholland 						    NFSX_UNSIGNED);
   1059  1.1  dholland 						*tl = 0;
   1060  1.1  dholland 					}
   1061  1.1  dholland 					break;
   1062  1.1  dholland 				}
   1063  1.1  dholland 				if (nd->nd_repstat == 0)
   1064  1.1  dholland 					error = (*(nfsrv4_ops0[op]))(nd,
   1065  1.1  dholland 					    isdgram, vp, p, &vpnes);
   1066  1.1  dholland 				if (nfsv4_opflag[op].modifyfs)
   1067  1.1  dholland 					vn_finished_write(temp_mp);
   1068  1.1  dholland 			} else {
   1069  1.1  dholland 				error = (*(nfsrv4_ops0[op]))(nd, isdgram,
   1070  1.1  dholland 				    NULL, p, &vpnes);
   1071  1.1  dholland 			}
   1072  1.1  dholland 		    }
   1073  1.2  pgoyette 		}
   1074  1.1  dholland 		if (error) {
   1075  1.1  dholland 			if (error == EBADRPC || error == NFSERR_BADXDR) {
   1076  1.1  dholland 				nd->nd_repstat = NFSERR_BADXDR;
   1077  1.1  dholland 			} else {
   1078  1.1  dholland 				nd->nd_repstat = error;
   1079  1.1  dholland 				printf("nfsv4 comperr0=%d\n", error);
   1080  1.1  dholland 			}
   1081  1.1  dholland 			error = 0;
   1082  1.1  dholland 		}
   1083  1.2  pgoyette 
   1084  1.2  pgoyette 		if (statsinprog != 0) {
   1085  1.2  pgoyette 			nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
   1086  1.2  pgoyette 			    /*then*/ &start_time);
   1087  1.2  pgoyette 			statsinprog = 0;
   1088  1.2  pgoyette 		}
   1089  1.2  pgoyette 
   1090  1.1  dholland 		retops++;
   1091  1.1  dholland 		if (nd->nd_repstat) {
   1092  1.1  dholland 			*repp = nfsd_errmap(nd);
   1093  1.1  dholland 			break;
   1094  1.1  dholland 		} else {
   1095  1.1  dholland 			*repp = 0;	/* NFS4_OK */
   1096  1.1  dholland 		}
   1097  1.1  dholland 	}
   1098  1.1  dholland nfsmout:
   1099  1.2  pgoyette 	if (statsinprog != 0) {
   1100  1.2  pgoyette 		nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
   1101  1.2  pgoyette 		    /*then*/ &start_time);
   1102  1.2  pgoyette 		statsinprog = 0;
   1103  1.2  pgoyette 	}
   1104  1.1  dholland 	if (error) {
   1105  1.1  dholland 		if (error == EBADRPC || error == NFSERR_BADXDR)
   1106  1.1  dholland 			nd->nd_repstat = NFSERR_BADXDR;
   1107  1.1  dholland 		else
   1108  1.1  dholland 			printf("nfsv4 comperr1=%d\n", error);
   1109  1.1  dholland 	}
   1110  1.1  dholland 	if (taglen == -1) {
   1111  1.1  dholland 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
   1112  1.1  dholland 		*tl++ = 0;
   1113  1.1  dholland 		*tl = 0;
   1114  1.1  dholland 	} else {
   1115  1.1  dholland 		*retopsp = txdr_unsigned(retops);
   1116  1.1  dholland 	}
   1117  1.1  dholland 	if (vp)
   1118  1.1  dholland 		vrele(vp);
   1119  1.1  dholland 	if (savevp)
   1120  1.1  dholland 		vrele(savevp);
   1121  1.1  dholland 	NFSLOCKV4ROOTMUTEX();
   1122  1.1  dholland 	nfsv4_relref(&nfsv4rootfs_lock);
   1123  1.1  dholland 	NFSUNLOCKV4ROOTMUTEX();
   1124  1.1  dholland 
   1125  1.1  dholland 	NFSEXITCODE2(0, nd);
   1126  1.1  dholland }
   1127