1191783Srmacklem/*- 2191783Srmacklem * Copyright (c) 1989, 1993 3191783Srmacklem * The Regents of the University of California. All rights reserved. 4191783Srmacklem * 5191783Srmacklem * This code is derived from software contributed to Berkeley by 6191783Srmacklem * Rick Macklem at The University of Guelph. 7191783Srmacklem * 8191783Srmacklem * Redistribution and use in source and binary forms, with or without 9191783Srmacklem * modification, are permitted provided that the following conditions 10191783Srmacklem * are met: 11191783Srmacklem * 1. Redistributions of source code must retain the above copyright 12191783Srmacklem * notice, this list of conditions and the following disclaimer. 13191783Srmacklem * 2. Redistributions in binary form must reproduce the above copyright 14191783Srmacklem * notice, this list of conditions and the following disclaimer in the 15191783Srmacklem * documentation and/or other materials provided with the distribution. 16191783Srmacklem * 4. Neither the name of the University nor the names of its contributors 17191783Srmacklem * may be used to endorse or promote products derived from this software 18191783Srmacklem * without specific prior written permission. 19191783Srmacklem * 20191783Srmacklem * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21191783Srmacklem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22191783Srmacklem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23191783Srmacklem * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24191783Srmacklem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25191783Srmacklem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26191783Srmacklem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27191783Srmacklem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28191783Srmacklem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29191783Srmacklem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30191783Srmacklem * SUCH DAMAGE. 31191783Srmacklem * 32191783Srmacklem */ 33191783Srmacklem 34191783Srmacklem#include <sys/cdefs.h> 35191783Srmacklem__FBSDID("$FreeBSD$"); 36191783Srmacklem 37191783Srmacklem/* 38191783Srmacklem * Socket operations for use by the nfs server. 39191783Srmacklem */ 40191783Srmacklem 41191783Srmacklem#ifndef APPLEKEXT 42191783Srmacklem#include <fs/nfs/nfsport.h> 43191783Srmacklem 44191783Srmacklemextern struct nfsstats newnfsstats; 45191783Srmacklemextern struct nfsrvfh nfs_pubfh, nfs_rootfh; 46191783Srmacklemextern int nfs_pubfhset, nfs_rootfhset; 47191783Srmacklemextern struct nfsv4lock nfsv4rootfs_lock; 48191783Srmacklemextern struct nfsrv_stablefirst nfsrv_stablefirst; 49191783Srmacklemextern struct nfsclienthashhead nfsclienthash[NFSCLIENTHASHSIZE]; 50191783Srmacklemextern int nfsrc_floodlevel, nfsrc_tcpsavedreplies; 51191783SrmacklemNFSV4ROOTLOCKMUTEX; 52191783SrmacklemNFSSTATESPINLOCK; 53191783Srmacklem 54191783Srmacklemint (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *, 55191783Srmacklem int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = { 56191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 57191783Srmacklem nfsrvd_getattr, 58191783Srmacklem nfsrvd_setattr, 59191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 60191783Srmacklem nfsrvd_access, 61191783Srmacklem nfsrvd_readlink, 62191783Srmacklem nfsrvd_read, 63191783Srmacklem nfsrvd_write, 64191783Srmacklem nfsrvd_create, 65191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 66191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 67191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 68191783Srmacklem nfsrvd_remove, 69191783Srmacklem nfsrvd_remove, 70191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 71191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 72191783Srmacklem nfsrvd_readdir, 73191783Srmacklem nfsrvd_readdirplus, 74191783Srmacklem nfsrvd_statfs, 75191783Srmacklem nfsrvd_fsinfo, 76191783Srmacklem nfsrvd_pathconf, 77191783Srmacklem nfsrvd_commit, 78191783Srmacklem}; 79191783Srmacklem 80191783Srmacklemint (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *, 81191783Srmacklem int, vnode_t , vnode_t *, fhandle_t *, 82191783Srmacklem NFSPROC_T *, struct nfsexstuff *) = { 83191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 84191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 85191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 86191783Srmacklem nfsrvd_lookup, 87191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 88191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 89191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 90191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 91191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 92191783Srmacklem nfsrvd_mkdir, 93191783Srmacklem nfsrvd_symlink, 94191783Srmacklem nfsrvd_mknod, 95191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 96191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 97191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 98191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 99191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 100191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 101191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 102191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 103191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 104191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 105191783Srmacklem}; 106191783Srmacklem 107191783Srmacklemint (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *, 108191783Srmacklem int, vnode_t , vnode_t , NFSPROC_T *, 109191783Srmacklem struct nfsexstuff *, struct nfsexstuff *) = { 110191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 111191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 112191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 113191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 114191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 115191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 116191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 117191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 118191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 119191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 120191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 121191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 122191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 123191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 124191783Srmacklem nfsrvd_rename, 125191783Srmacklem nfsrvd_link, 126191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 127191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 128191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 129191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 130191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 131191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 132191783Srmacklem}; 133191783Srmacklem 134191783Srmacklemint (*nfsrv4_ops0[NFSV4OP_NOPS])(struct nfsrv_descript *, 135191783Srmacklem int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = { 136191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 137191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 138191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 139191783Srmacklem nfsrvd_access, 140191783Srmacklem nfsrvd_close, 141191783Srmacklem nfsrvd_commit, 142191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 143191783Srmacklem nfsrvd_delegpurge, 144191783Srmacklem nfsrvd_delegreturn, 145191783Srmacklem nfsrvd_getattr, 146191783Srmacklem nfsrvd_getfh, 147191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 148191783Srmacklem nfsrvd_lock, 149191783Srmacklem nfsrvd_lockt, 150191783Srmacklem nfsrvd_locku, 151191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 152191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 153191783Srmacklem nfsrvd_verify, 154191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 155191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 156191783Srmacklem nfsrvd_openconfirm, 157191783Srmacklem nfsrvd_opendowngrade, 158191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 159191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 160191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 161191783Srmacklem nfsrvd_read, 162191783Srmacklem nfsrvd_readdirplus, 163191783Srmacklem nfsrvd_readlink, 164191783Srmacklem nfsrvd_remove, 165191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 166191783Srmacklem nfsrvd_renew, 167191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 168191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 169191783Srmacklem nfsrvd_secinfo, 170191783Srmacklem nfsrvd_setattr, 171191783Srmacklem nfsrvd_setclientid, 172191783Srmacklem nfsrvd_setclientidcfrm, 173191783Srmacklem nfsrvd_verify, 174191783Srmacklem nfsrvd_write, 175191783Srmacklem nfsrvd_releaselckown, 176191783Srmacklem}; 177191783Srmacklem 178191783Srmacklemint (*nfsrv4_ops1[NFSV4OP_NOPS])(struct nfsrv_descript *, 179191783Srmacklem int, vnode_t , vnode_t *, fhandle_t *, 180191783Srmacklem NFSPROC_T *, struct nfsexstuff *) = { 181191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 182191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 183191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 184191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 185191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 186191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 187191783Srmacklem nfsrvd_mknod, 188191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 189191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 190191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 191191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 192191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 193191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 194191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 195191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 196191783Srmacklem nfsrvd_lookup, 197191783Srmacklem nfsrvd_lookup, 198191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 199191783Srmacklem nfsrvd_open, 200191783Srmacklem nfsrvd_openattr, 201191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 202191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 203191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 204191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 205191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 206191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 207191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 208191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 209191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 210191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 211191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 212191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 213191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 214191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 215191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 216191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 217191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 218191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 219191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 220191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 221191783Srmacklem}; 222191783Srmacklem 223191783Srmacklemint (*nfsrv4_ops2[NFSV4OP_NOPS])(struct nfsrv_descript *, 224191783Srmacklem int, vnode_t , vnode_t , NFSPROC_T *, 225191783Srmacklem struct nfsexstuff *, struct nfsexstuff *) = { 226191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 227191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 228191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 229191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 230191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 231191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 232191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 233191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 234191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 235191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 236191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 237191783Srmacklem nfsrvd_link, 238191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 239191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 240191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 241191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 242191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 243191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 244191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 245191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 246191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 247191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 248191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 249191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 250191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 251191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 252191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 253191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 254191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 255191783Srmacklem nfsrvd_rename, 256191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 257191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 258191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 259191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 260191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 261191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 262191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 263191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 264191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 265191783Srmacklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 266191783Srmacklem}; 267191783Srmacklem#endif /* !APPLEKEXT */ 268191783Srmacklem 269191783Srmacklem/* 270191783Srmacklem * Static array that defines which nfs rpc's are nonidempotent 271191783Srmacklem */ 272191783Srmacklemstatic int nfsrv_nonidempotent[NFS_V3NPROCS] = { 273191783Srmacklem FALSE, 274191783Srmacklem FALSE, 275191783Srmacklem TRUE, 276191783Srmacklem FALSE, 277191783Srmacklem FALSE, 278191783Srmacklem FALSE, 279191783Srmacklem FALSE, 280191783Srmacklem TRUE, 281191783Srmacklem TRUE, 282191783Srmacklem TRUE, 283191783Srmacklem TRUE, 284191783Srmacklem TRUE, 285191783Srmacklem TRUE, 286191783Srmacklem TRUE, 287191783Srmacklem TRUE, 288191783Srmacklem TRUE, 289191783Srmacklem FALSE, 290191783Srmacklem FALSE, 291191783Srmacklem FALSE, 292191783Srmacklem FALSE, 293191783Srmacklem FALSE, 294191783Srmacklem FALSE, 295191783Srmacklem}; 296191783Srmacklem 297191783Srmacklem/* 298191783Srmacklem * This static array indicates whether or not the RPC modifies the 299191783Srmacklem * file system. 300191783Srmacklem */ 301191783Srmacklemstatic int nfs_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0, 302191783Srmacklem 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 303191783Srmacklem 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; 304191783Srmacklem 305191783Srmacklem/* local functions */ 306191783Srmacklemstatic void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, 307191783Srmacklem NFSPROC_T *p); 308191783Srmacklem 309191783Srmacklem 310191783Srmacklem/* 311191783Srmacklem * This static array indicates which server procedures require the extra 312191783Srmacklem * arguments to return the current file handle for V2, 3. 313191783Srmacklem */ 314191783Srmacklemstatic int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 315191783Srmacklem 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 }; 316191783Srmacklem 317191783Srmacklemextern struct nfsv4_opflag nfsv4_opflag[NFSV4OP_NOPS]; 318191783Srmacklem 319191783Srmacklemstatic int nfsv3to4op[NFS_V3NPROCS] = { 320191783Srmacklem NFSPROC_NULL, 321191783Srmacklem NFSV4OP_GETATTR, 322191783Srmacklem NFSV4OP_SETATTR, 323191783Srmacklem NFSV4OP_LOOKUP, 324191783Srmacklem NFSV4OP_ACCESS, 325191783Srmacklem NFSV4OP_READLINK, 326191783Srmacklem NFSV4OP_READ, 327191783Srmacklem NFSV4OP_WRITE, 328191783Srmacklem NFSV4OP_V3CREATE, 329191783Srmacklem NFSV4OP_MKDIR, 330191783Srmacklem NFSV4OP_SYMLINK, 331191783Srmacklem NFSV4OP_MKNOD, 332191783Srmacklem NFSV4OP_REMOVE, 333191783Srmacklem NFSV4OP_RMDIR, 334191783Srmacklem NFSV4OP_RENAME, 335191783Srmacklem NFSV4OP_LINK, 336191783Srmacklem NFSV4OP_READDIR, 337191783Srmacklem NFSV4OP_READDIRPLUS, 338191783Srmacklem NFSV4OP_FSSTAT, 339191783Srmacklem NFSV4OP_FSINFO, 340191783Srmacklem NFSV4OP_PATHCONF, 341191783Srmacklem NFSV4OP_COMMIT, 342191783Srmacklem}; 343191783Srmacklem 344191783Srmacklem/* 345191783Srmacklem * Do an RPC. Basically, get the file handles translated to vnode pointers 346191783Srmacklem * and then call the appropriate server routine. The server routines are 347191783Srmacklem * split into groups, based on whether they use a file handle or file 348191783Srmacklem * handle plus name or ... 349191783Srmacklem * The NFS V4 Compound RPC is performed separately by nfsrvd_compound(). 350191783Srmacklem */ 351191783SrmacklemAPPLESTATIC void 352191783Srmacklemnfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, 353191783Srmacklem NFSPROC_T *p) 354191783Srmacklem{ 355216700Srmacklem int error = 0, lktype; 356191783Srmacklem vnode_t vp; 357191783Srmacklem mount_t mp = NULL; 358191783Srmacklem struct nfsrvfh fh; 359191783Srmacklem struct nfsexstuff nes; 360191783Srmacklem 361191783Srmacklem /* 362191783Srmacklem * Get a locked vnode for the first file handle 363191783Srmacklem */ 364191783Srmacklem if (!(nd->nd_flag & ND_NFSV4)) { 365209120Skib KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc")); 366191783Srmacklem /* 367191783Srmacklem * For NFSv3, if the malloc/mget allocation is near limits, 368191783Srmacklem * return NFSERR_DELAY. 369191783Srmacklem */ 370191783Srmacklem if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) { 371191783Srmacklem nd->nd_repstat = NFSERR_DELAY; 372191783Srmacklem vp = NULL; 373191783Srmacklem } else { 374191783Srmacklem error = nfsrv_mtofh(nd, &fh); 375191783Srmacklem if (error) { 376191783Srmacklem if (error != EBADRPC) 377191783Srmacklem printf("nfs dorpc err1=%d\n", error); 378191783Srmacklem nd->nd_repstat = NFSERR_GARBAGE; 379224086Szack goto out; 380191783Srmacklem } 381216700Srmacklem if (nd->nd_procnum == NFSPROC_READ || 382249592Sken nd->nd_procnum == NFSPROC_WRITE || 383216700Srmacklem nd->nd_procnum == NFSPROC_READDIR || 384216700Srmacklem nd->nd_procnum == NFSPROC_READLINK || 385216700Srmacklem nd->nd_procnum == NFSPROC_GETATTR || 386216700Srmacklem nd->nd_procnum == NFSPROC_ACCESS) 387216700Srmacklem lktype = LK_SHARED; 388216700Srmacklem else 389216700Srmacklem lktype = LK_EXCLUSIVE; 390191783Srmacklem if (nd->nd_flag & ND_PUBLOOKUP) 391216700Srmacklem nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes, 392191783Srmacklem &mp, nfs_writerpc[nd->nd_procnum], p); 393191783Srmacklem else 394216700Srmacklem nfsd_fhtovp(nd, &fh, lktype, &vp, &nes, 395191783Srmacklem &mp, nfs_writerpc[nd->nd_procnum], p); 396191783Srmacklem if (nd->nd_repstat == NFSERR_PROGNOTV4) 397224086Szack goto out; 398191783Srmacklem } 399191783Srmacklem } 400191783Srmacklem 401191783Srmacklem /* 402191783Srmacklem * For V2 and 3, set the ND_SAVEREPLY flag for the recent request 403191783Srmacklem * cache, as required. 404191783Srmacklem * For V4, nfsrvd_compound() does this. 405191783Srmacklem */ 406191783Srmacklem if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum]) 407191783Srmacklem nd->nd_flag |= ND_SAVEREPLY; 408191783Srmacklem 409191783Srmacklem nfsrvd_rephead(nd); 410191783Srmacklem /* 411191783Srmacklem * If nd_repstat is non-zero, just fill in the reply status 412191783Srmacklem * to complete the RPC reply for V2. Otherwise, you must do 413191783Srmacklem * the RPC. 414191783Srmacklem */ 415191783Srmacklem if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) { 416191783Srmacklem *nd->nd_errp = nfsd_errmap(nd); 417191783Srmacklem NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]); 418217063Srmacklem if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0) 419217063Srmacklem vn_finished_write(mp); 420224086Szack goto out; 421191783Srmacklem } 422191783Srmacklem 423191783Srmacklem /* 424191783Srmacklem * Now the procedure can be performed. For V4, nfsrvd_compound() 425191783Srmacklem * works through the sub-rpcs, otherwise just call the procedure. 426191783Srmacklem * The procedures are in three groups with different arguments. 427191783Srmacklem * The group is indicated by the value in nfs_retfh[]. 428191783Srmacklem */ 429191783Srmacklem if (nd->nd_flag & ND_NFSV4) { 430191783Srmacklem nfsrvd_compound(nd, isdgram, p); 431191783Srmacklem } else { 432191783Srmacklem if (nfs_retfh[nd->nd_procnum] == 1) { 433191783Srmacklem if (vp) 434224080Szack NFSVOPUNLOCK(vp, 0); 435191783Srmacklem error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram, 436191783Srmacklem vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes); 437191783Srmacklem } else if (nfs_retfh[nd->nd_procnum] == 2) { 438191783Srmacklem error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram, 439191783Srmacklem vp, NULL, p, &nes, NULL); 440191783Srmacklem } else { 441191783Srmacklem error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram, 442191783Srmacklem vp, p, &nes); 443191783Srmacklem } 444217063Srmacklem if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0) 445217063Srmacklem vn_finished_write(mp); 446191783Srmacklem NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]); 447191783Srmacklem } 448191783Srmacklem if (error) { 449191783Srmacklem if (error != EBADRPC) 450191783Srmacklem printf("nfs dorpc err2=%d\n", error); 451191783Srmacklem nd->nd_repstat = NFSERR_GARBAGE; 452191783Srmacklem } 453191783Srmacklem *nd->nd_errp = nfsd_errmap(nd); 454191783Srmacklem 455191783Srmacklem /* 456191783Srmacklem * Don't cache certain reply status values. 457191783Srmacklem */ 458191783Srmacklem if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) && 459191783Srmacklem (nd->nd_repstat == NFSERR_GARBAGE || 460191783Srmacklem nd->nd_repstat == NFSERR_BADXDR || 461191783Srmacklem nd->nd_repstat == NFSERR_MOVED || 462191783Srmacklem nd->nd_repstat == NFSERR_DELAY || 463191783Srmacklem nd->nd_repstat == NFSERR_BADSEQID || 464191783Srmacklem nd->nd_repstat == NFSERR_RESOURCE || 465191783Srmacklem nd->nd_repstat == NFSERR_SERVERFAULT || 466191783Srmacklem nd->nd_repstat == NFSERR_STALECLIENTID || 467191783Srmacklem nd->nd_repstat == NFSERR_STALESTATEID || 468191783Srmacklem nd->nd_repstat == NFSERR_OLDSTATEID || 469191783Srmacklem nd->nd_repstat == NFSERR_BADSTATEID || 470191783Srmacklem nd->nd_repstat == NFSERR_GRACE || 471191783Srmacklem nd->nd_repstat == NFSERR_NOGRACE)) 472191783Srmacklem nd->nd_flag &= ~ND_SAVEREPLY; 473224086Szack 474224086Szackout: 475224086Szack NFSEXITCODE2(0, nd); 476191783Srmacklem} 477191783Srmacklem 478191783Srmacklem/* 479191783Srmacklem * Breaks down a compound RPC request and calls the server routines for 480191783Srmacklem * the subprocedures. 481191783Srmacklem * Some suboperations are performed directly here to simplify file handle<--> 482191783Srmacklem * vnode pointer handling. 483191783Srmacklem */ 484191783Srmacklemstatic void 485191783Srmacklemnfsrvd_compound(struct nfsrv_descript *nd, int isdgram, 486191783Srmacklem NFSPROC_T *p) 487191783Srmacklem{ 488191783Srmacklem int i, op; 489191783Srmacklem u_int32_t *tl; 490191783Srmacklem struct nfsclient *clp, *nclp; 491191783Srmacklem int numops, taglen = -1, error = 0, igotlock; 492191783Srmacklem u_int32_t minorvers, retops = 0, *retopsp = NULL, *repp; 493191783Srmacklem u_char tag[NFSV4_SMALLSTR + 1], *tagstr; 494191783Srmacklem vnode_t vp, nvp, savevp; 495191783Srmacklem struct nfsrvfh fh; 496217063Srmacklem mount_t new_mp, temp_mp = NULL; 497191783Srmacklem struct ucred *credanon; 498191783Srmacklem struct nfsexstuff nes, vpnes, savevpnes; 499217063Srmacklem fsid_t cur_fsid, save_fsid; 500191783Srmacklem static u_int64_t compref = 0; 501191783Srmacklem 502191783Srmacklem NFSVNO_EXINIT(&vpnes); 503191783Srmacklem NFSVNO_EXINIT(&savevpnes); 504191783Srmacklem /* 505191783Srmacklem * Put the seq# of the current compound RPC in nfsrv_descript. 506191783Srmacklem * (This is used by nfsrv_checkgetattr(), to see if the write 507191783Srmacklem * delegation was created by the same compound RPC as the one 508191783Srmacklem * with that Getattr in it.) 509191783Srmacklem * Don't worry about the 64bit number wrapping around. It ain't 510191783Srmacklem * gonna happen before this server gets shut down/rebooted. 511191783Srmacklem */ 512191783Srmacklem nd->nd_compref = compref++; 513191783Srmacklem 514191783Srmacklem /* 515191783Srmacklem * Check for and optionally get a lock on the root. This lock means that 516191783Srmacklem * no nfsd will be fiddling with the V4 file system and state stuff. It 517191783Srmacklem * is required when the V4 root is being changed, the stable storage 518191783Srmacklem * restart file is being updated, or callbacks are being done. 519191783Srmacklem * When any of the nfsd are processing an NFSv4 compound RPC, they must 520191783Srmacklem * either hold a reference count (nfs_usecnt) or the lock. When 521191783Srmacklem * nfsrv_unlock() is called to release the lock, it can optionally 522191783Srmacklem * also get a reference count, which saves the need for a call to 523191783Srmacklem * nfsrv_getref() after nfsrv_unlock(). 524191783Srmacklem */ 525191783Srmacklem /* 526191783Srmacklem * First, check to see if we need to wait for an update lock. 527191783Srmacklem */ 528191783Srmacklem igotlock = 0; 529191783Srmacklem NFSLOCKV4ROOTMUTEX(); 530191783Srmacklem if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK) 531191783Srmacklem igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 532222389Srmacklem NFSV4ROOTLOCKMUTEXPTR, NULL); 533191783Srmacklem else 534191783Srmacklem igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL, 535222389Srmacklem NFSV4ROOTLOCKMUTEXPTR, NULL); 536191783Srmacklem NFSUNLOCKV4ROOTMUTEX(); 537191783Srmacklem if (igotlock) { 538191783Srmacklem /* 539191783Srmacklem * If I got the lock, I can update the stable storage file. 540191783Srmacklem * Done when the grace period is over or a client has long 541191783Srmacklem * since expired. 542191783Srmacklem */ 543191783Srmacklem nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK; 544191783Srmacklem if ((nfsrv_stablefirst.nsf_flags & 545191783Srmacklem (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER) 546191783Srmacklem nfsrv_updatestable(p); 547191783Srmacklem 548191783Srmacklem /* 549191783Srmacklem * If at least one client has long since expired, search 550191783Srmacklem * the client list for them, write a REVOKE record on the 551191783Srmacklem * stable storage file and then remove them from the client 552191783Srmacklem * list. 553191783Srmacklem */ 554191783Srmacklem if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) { 555191783Srmacklem nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT; 556191783Srmacklem for (i = 0; i < NFSCLIENTHASHSIZE; i++) { 557191783Srmacklem LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, 558191783Srmacklem nclp) { 559191783Srmacklem if (clp->lc_flags & LCL_EXPIREIT) { 560191783Srmacklem if (!LIST_EMPTY(&clp->lc_open) || 561191783Srmacklem !LIST_EMPTY(&clp->lc_deleg)) 562191783Srmacklem nfsrv_writestable(clp->lc_id, 563191783Srmacklem clp->lc_idlen, NFSNST_REVOKE, p); 564191783Srmacklem nfsrv_cleanclient(clp, p); 565191783Srmacklem nfsrv_freedeleglist(&clp->lc_deleg); 566191783Srmacklem nfsrv_freedeleglist(&clp->lc_olddeleg); 567191783Srmacklem LIST_REMOVE(clp, lc_hash); 568191783Srmacklem nfsrv_zapclient(clp, p); 569191783Srmacklem } 570191783Srmacklem } 571191783Srmacklem } 572191783Srmacklem } 573191783Srmacklem NFSLOCKV4ROOTMUTEX(); 574191783Srmacklem nfsv4_unlock(&nfsv4rootfs_lock, 1); 575191783Srmacklem NFSUNLOCKV4ROOTMUTEX(); 576191783Srmacklem } else { 577191783Srmacklem /* 578191783Srmacklem * If we didn't get the lock, we need to get a refcnt, 579191783Srmacklem * which also checks for and waits for the lock. 580191783Srmacklem */ 581191783Srmacklem NFSLOCKV4ROOTMUTEX(); 582191783Srmacklem nfsv4_getref(&nfsv4rootfs_lock, NULL, 583222389Srmacklem NFSV4ROOTLOCKMUTEXPTR, NULL); 584191783Srmacklem NFSUNLOCKV4ROOTMUTEX(); 585191783Srmacklem } 586191783Srmacklem 587191783Srmacklem /* 588191783Srmacklem * If flagged, search for open owners that haven't had any opens 589191783Srmacklem * for a long time. 590191783Srmacklem */ 591191783Srmacklem if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) { 592191783Srmacklem nfsrv_throwawayopens(p); 593191783Srmacklem } 594191783Srmacklem 595191783Srmacklem savevp = vp = NULL; 596217063Srmacklem save_fsid.val[0] = save_fsid.val[1] = 0; 597217063Srmacklem cur_fsid.val[0] = cur_fsid.val[1] = 0; 598191783Srmacklem NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 599191783Srmacklem taglen = fxdr_unsigned(int, *tl); 600191783Srmacklem if (taglen < 0) { 601191783Srmacklem error = EBADRPC; 602191783Srmacklem goto nfsmout; 603191783Srmacklem } 604191783Srmacklem if (taglen <= NFSV4_SMALLSTR) 605191783Srmacklem tagstr = tag; 606191783Srmacklem else 607191783Srmacklem tagstr = malloc(taglen + 1, M_TEMP, M_WAITOK); 608191783Srmacklem error = nfsrv_mtostr(nd, tagstr, taglen); 609191783Srmacklem if (error) { 610191783Srmacklem if (taglen > NFSV4_SMALLSTR) 611191783Srmacklem free(tagstr, M_TEMP); 612191783Srmacklem taglen = -1; 613191783Srmacklem goto nfsmout; 614191783Srmacklem } 615191783Srmacklem (void) nfsm_strtom(nd, tag, taglen); 616191783Srmacklem if (taglen > NFSV4_SMALLSTR) { 617191783Srmacklem free(tagstr, M_TEMP); 618191783Srmacklem } 619191783Srmacklem NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED); 620191783Srmacklem NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 621191783Srmacklem minorvers = fxdr_unsigned(u_int32_t, *tl++); 622191783Srmacklem if (minorvers != NFSV4_MINORVERSION) 623191783Srmacklem nd->nd_repstat = NFSERR_MINORVERMISMATCH; 624191783Srmacklem if (nd->nd_repstat) 625191783Srmacklem numops = 0; 626191783Srmacklem else 627191783Srmacklem numops = fxdr_unsigned(int, *tl); 628191783Srmacklem /* 629191783Srmacklem * Loop around doing the sub ops. 630191783Srmacklem * vp - is an unlocked vnode pointer for the CFH 631191783Srmacklem * savevp - is an unlocked vnode pointer for the SAVEDFH 632191783Srmacklem * (at some future date, it might turn out to be more appropriate 633191783Srmacklem * to keep the file handles instead of vnode pointers?) 634191783Srmacklem * savevpnes and vpnes - are the export flags for the above. 635191783Srmacklem */ 636191783Srmacklem for (i = 0; i < numops; i++) { 637191783Srmacklem NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 638191783Srmacklem NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED); 639192781Srmacklem *repp = *tl; 640191783Srmacklem op = fxdr_unsigned(int, *tl); 641191783Srmacklem if (op < NFSV4OP_ACCESS || op >= NFSV4OP_NOPS) { 642192781Srmacklem nd->nd_repstat = NFSERR_OPILLEGAL; 643192781Srmacklem *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL); 644192781Srmacklem *repp = nfsd_errmap(nd); 645192781Srmacklem retops++; 646192781Srmacklem break; 647192781Srmacklem } else { 648192781Srmacklem repp++; 649191783Srmacklem } 650191783Srmacklem 651191783Srmacklem /* 652191783Srmacklem * Check for a referral on the current FH and, if so, return 653191783Srmacklem * NFSERR_MOVED for all ops that allow it, except Getattr. 654191783Srmacklem */ 655191783Srmacklem if (vp != NULL && op != NFSV4OP_GETATTR && 656191783Srmacklem nfsv4root_getreferral(vp, NULL, 0) != NULL && 657191783Srmacklem nfsrv_errmoved(op)) { 658191783Srmacklem nd->nd_repstat = NFSERR_MOVED; 659191783Srmacklem *repp = nfsd_errmap(nd); 660191783Srmacklem retops++; 661191783Srmacklem break; 662191783Srmacklem } 663191783Srmacklem 664191783Srmacklem nd->nd_procnum = op; 665191783Srmacklem /* 666191783Srmacklem * If over flood level, reply NFSERR_RESOURCE, if at the first 667191783Srmacklem * Op. (Since a client recovery from NFSERR_RESOURCE can get 668191783Srmacklem * really nasty for certain Op sequences, I'll play it safe 669191783Srmacklem * and only return the error at the beginning.) The cache 670191783Srmacklem * will still function over flood level, but uses lots of 671191783Srmacklem * mbufs.) 672191783Srmacklem * If nfsrv_mallocmget_limit() returns True, the system is near 673191783Srmacklem * to its limit for memory that malloc()/mget() can allocate. 674191783Srmacklem */ 675191783Srmacklem if (i == 0 && nd->nd_rp->rc_refcnt == 0 && 676191783Srmacklem (nfsrv_mallocmget_limit() || 677191783Srmacklem nfsrc_tcpsavedreplies > nfsrc_floodlevel)) { 678191783Srmacklem if (nfsrc_tcpsavedreplies > nfsrc_floodlevel) { 679191783Srmacklem printf("nfsd server cache flooded, try to"); 680191783Srmacklem printf(" increase nfsrc_floodlevel\n"); 681191783Srmacklem } 682191783Srmacklem nd->nd_repstat = NFSERR_RESOURCE; 683191783Srmacklem *repp = nfsd_errmap(nd); 684191783Srmacklem if (op == NFSV4OP_SETATTR) { 685192781Srmacklem /* 686192781Srmacklem * Setattr replies require a bitmap. 687192781Srmacklem * even for errors like these. 688192781Srmacklem */ 689192781Srmacklem NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 690192781Srmacklem *tl = 0; 691191783Srmacklem } 692191783Srmacklem retops++; 693191783Srmacklem break; 694191783Srmacklem } 695191783Srmacklem if (nfsv4_opflag[op].savereply) 696191783Srmacklem nd->nd_flag |= ND_SAVEREPLY; 697191783Srmacklem NFSINCRGLOBAL(newnfsstats.srvrpccnt[nd->nd_procnum]); 698191783Srmacklem switch (op) { 699191783Srmacklem case NFSV4OP_PUTFH: 700191783Srmacklem error = nfsrv_mtofh(nd, &fh); 701191783Srmacklem if (error) 702191783Srmacklem goto nfsmout; 703217063Srmacklem if (!nd->nd_repstat) 704217063Srmacklem nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes, 705217063Srmacklem NULL, 0, p); 706191783Srmacklem /* For now, allow this for non-export FHs */ 707191783Srmacklem if (!nd->nd_repstat) { 708191783Srmacklem if (vp) 709191783Srmacklem vrele(vp); 710191783Srmacklem vp = nvp; 711217063Srmacklem cur_fsid = vp->v_mount->mnt_stat.f_fsid; 712224082Szack NFSVOPUNLOCK(vp, 0); 713191783Srmacklem vpnes = nes; 714191783Srmacklem } 715191783Srmacklem break; 716191783Srmacklem case NFSV4OP_PUTPUBFH: 717217063Srmacklem if (nfs_pubfhset) 718216700Srmacklem nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp, 719217063Srmacklem &nes, NULL, 0, p); 720217063Srmacklem else 721191783Srmacklem nd->nd_repstat = NFSERR_NOFILEHANDLE; 722191783Srmacklem if (!nd->nd_repstat) { 723191783Srmacklem if (vp) 724191783Srmacklem vrele(vp); 725191783Srmacklem vp = nvp; 726217063Srmacklem cur_fsid = vp->v_mount->mnt_stat.f_fsid; 727224082Szack NFSVOPUNLOCK(vp, 0); 728191783Srmacklem vpnes = nes; 729191783Srmacklem } 730191783Srmacklem break; 731191783Srmacklem case NFSV4OP_PUTROOTFH: 732191783Srmacklem if (nfs_rootfhset) { 733216700Srmacklem nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp, 734217063Srmacklem &nes, NULL, 0, p); 735191783Srmacklem if (!nd->nd_repstat) { 736191783Srmacklem if (vp) 737191783Srmacklem vrele(vp); 738191783Srmacklem vp = nvp; 739217063Srmacklem cur_fsid = vp->v_mount->mnt_stat.f_fsid; 740224082Szack NFSVOPUNLOCK(vp, 0); 741191783Srmacklem vpnes = nes; 742191783Srmacklem } 743216894Srmacklem } else 744191783Srmacklem nd->nd_repstat = NFSERR_NOFILEHANDLE; 745191783Srmacklem break; 746191783Srmacklem case NFSV4OP_SAVEFH: 747191783Srmacklem if (vp && NFSVNO_EXPORTED(&vpnes)) { 748191783Srmacklem nd->nd_repstat = 0; 749191783Srmacklem /* If vp == savevp, a no-op */ 750191783Srmacklem if (vp != savevp) { 751191783Srmacklem if (savevp) 752191783Srmacklem vrele(savevp); 753191783Srmacklem VREF(vp); 754191783Srmacklem savevp = vp; 755191783Srmacklem savevpnes = vpnes; 756217063Srmacklem save_fsid = cur_fsid; 757191783Srmacklem } 758191783Srmacklem } else { 759191783Srmacklem nd->nd_repstat = NFSERR_NOFILEHANDLE; 760191783Srmacklem } 761191783Srmacklem break; 762191783Srmacklem case NFSV4OP_RESTOREFH: 763191783Srmacklem if (savevp) { 764191783Srmacklem nd->nd_repstat = 0; 765191783Srmacklem /* If vp == savevp, a no-op */ 766191783Srmacklem if (vp != savevp) { 767191783Srmacklem VREF(savevp); 768191783Srmacklem vrele(vp); 769191783Srmacklem vp = savevp; 770191783Srmacklem vpnes = savevpnes; 771217063Srmacklem cur_fsid = save_fsid; 772191783Srmacklem } 773191783Srmacklem } else { 774191783Srmacklem nd->nd_repstat = NFSERR_RESTOREFH; 775191783Srmacklem } 776191783Srmacklem break; 777191783Srmacklem default: 778191783Srmacklem /* 779191783Srmacklem * Allow a Lookup, Getattr, GetFH, Secinfo on an 780191783Srmacklem * non-exported directory if 781191783Srmacklem * nfs_rootfhset. Do I need to allow any other Ops? 782191783Srmacklem * (You can only have a non-exported vpnes if 783191783Srmacklem * nfs_rootfhset is true. See nfsd_fhtovp()) 784191783Srmacklem * Allow AUTH_SYS to be used for file systems 785191783Srmacklem * exported GSS only for certain Ops, to allow 786191783Srmacklem * clients to do mounts more easily. 787191783Srmacklem */ 788191783Srmacklem if (nfsv4_opflag[op].needscfh && vp) { 789191783Srmacklem if (!NFSVNO_EXPORTED(&vpnes) && 790191783Srmacklem op != NFSV4OP_LOOKUP && 791191783Srmacklem op != NFSV4OP_GETATTR && 792191783Srmacklem op != NFSV4OP_GETFH && 793223348Srmacklem op != NFSV4OP_ACCESS && 794223348Srmacklem op != NFSV4OP_READLINK && 795191783Srmacklem op != NFSV4OP_SECINFO) 796191783Srmacklem nd->nd_repstat = NFSERR_NOFILEHANDLE; 797192121Srmacklem else if (nfsvno_testexp(nd, &vpnes) && 798191783Srmacklem op != NFSV4OP_LOOKUP && 799191783Srmacklem op != NFSV4OP_GETFH && 800191783Srmacklem op != NFSV4OP_GETATTR && 801191783Srmacklem op != NFSV4OP_SECINFO) 802191783Srmacklem nd->nd_repstat = NFSERR_WRONGSEC; 803191783Srmacklem if (nd->nd_repstat) { 804191783Srmacklem if (op == NFSV4OP_SETATTR) { 805191783Srmacklem /* 806191783Srmacklem * Setattr reply requires a bitmap 807191783Srmacklem * even for errors like these. 808191783Srmacklem */ 809191783Srmacklem NFSM_BUILD(tl, u_int32_t *, 810191783Srmacklem NFSX_UNSIGNED); 811191783Srmacklem *tl = 0; 812191783Srmacklem } 813191783Srmacklem break; 814191783Srmacklem } 815191783Srmacklem } 816191783Srmacklem if (nfsv4_opflag[op].retfh == 1) { 817191783Srmacklem if (!vp) { 818191783Srmacklem nd->nd_repstat = NFSERR_NOFILEHANDLE; 819191783Srmacklem break; 820191783Srmacklem } 821191783Srmacklem VREF(vp); 822191783Srmacklem if (nfsv4_opflag[op].modifyfs) 823217023Srmacklem vn_start_write(vp, &temp_mp, V_WAIT); 824191783Srmacklem error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp, 825191783Srmacklem &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes); 826191783Srmacklem if (!error && !nd->nd_repstat) { 827217063Srmacklem if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) { 828217063Srmacklem new_mp = nvp->v_mount; 829217063Srmacklem if (cur_fsid.val[0] != 830217063Srmacklem new_mp->mnt_stat.f_fsid.val[0] || 831217063Srmacklem cur_fsid.val[1] != 832217063Srmacklem new_mp->mnt_stat.f_fsid.val[1]) { 833217063Srmacklem /* crossed a server mount point */ 834217063Srmacklem nd->nd_repstat = nfsvno_checkexp(new_mp, 835191783Srmacklem nd->nd_nam, &nes, &credanon); 836191783Srmacklem if (!nd->nd_repstat) 837191783Srmacklem nd->nd_repstat = nfsd_excred(nd, 838191783Srmacklem &nes, credanon); 839191940Skan if (credanon != NULL) 840191940Skan crfree(credanon); 841191783Srmacklem if (!nd->nd_repstat) { 842191783Srmacklem vpnes = nes; 843217063Srmacklem cur_fsid = new_mp->mnt_stat.f_fsid; 844191783Srmacklem } 845217063Srmacklem } 846217063Srmacklem /* Lookup ops return a locked vnode */ 847224082Szack NFSVOPUNLOCK(nvp, 0); 848191783Srmacklem } 849191783Srmacklem if (!nd->nd_repstat) { 850191783Srmacklem vrele(vp); 851191783Srmacklem vp = nvp; 852216897Srmacklem } else 853216897Srmacklem vrele(nvp); 854191783Srmacklem } 855191783Srmacklem if (nfsv4_opflag[op].modifyfs) 856217023Srmacklem vn_finished_write(temp_mp); 857191783Srmacklem } else if (nfsv4_opflag[op].retfh == 2) { 858191783Srmacklem if (vp == NULL || savevp == NULL) { 859191783Srmacklem nd->nd_repstat = NFSERR_NOFILEHANDLE; 860191783Srmacklem break; 861217063Srmacklem } else if (cur_fsid.val[0] != save_fsid.val[0] || 862217063Srmacklem cur_fsid.val[1] != save_fsid.val[1]) { 863191783Srmacklem nd->nd_repstat = NFSERR_XDEV; 864191783Srmacklem break; 865191783Srmacklem } 866191783Srmacklem if (nfsv4_opflag[op].modifyfs) 867217023Srmacklem vn_start_write(savevp, &temp_mp, V_WAIT); 868224081Szack if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) { 869216893Srmacklem VREF(vp); 870216893Srmacklem VREF(savevp); 871216893Srmacklem error = (*(nfsrv4_ops2[op]))(nd, isdgram, 872216893Srmacklem savevp, vp, p, &savevpnes, &vpnes); 873216893Srmacklem } else 874216893Srmacklem nd->nd_repstat = NFSERR_PERM; 875191783Srmacklem if (nfsv4_opflag[op].modifyfs) 876217023Srmacklem vn_finished_write(temp_mp); 877191783Srmacklem } else { 878191783Srmacklem if (nfsv4_opflag[op].retfh != 0) 879191783Srmacklem panic("nfsrvd_compound"); 880191783Srmacklem if (nfsv4_opflag[op].needscfh) { 881216700Srmacklem if (vp != NULL) { 882216893Srmacklem if (nfsv4_opflag[op].modifyfs) 883217023Srmacklem vn_start_write(vp, &temp_mp, 884217023Srmacklem V_WAIT); 885224081Szack if (NFSVOPLOCK(vp, nfsv4_opflag[op].lktype) 886216893Srmacklem == 0) 887216893Srmacklem VREF(vp); 888216893Srmacklem else 889216700Srmacklem nd->nd_repstat = NFSERR_PERM; 890216893Srmacklem } else { 891191783Srmacklem nd->nd_repstat = NFSERR_NOFILEHANDLE; 892191783Srmacklem if (op == NFSV4OP_SETATTR) { 893216700Srmacklem /* 894216700Srmacklem * Setattr reply requires a 895216700Srmacklem * bitmap even for errors like 896216700Srmacklem * these. 897216700Srmacklem */ 898216700Srmacklem NFSM_BUILD(tl, u_int32_t *, 899216700Srmacklem NFSX_UNSIGNED); 900216700Srmacklem *tl = 0; 901191783Srmacklem } 902191783Srmacklem break; 903191783Srmacklem } 904216893Srmacklem if (nd->nd_repstat == 0) 905216893Srmacklem error = (*(nfsrv4_ops0[op]))(nd, 906216893Srmacklem isdgram, vp, p, &vpnes); 907216700Srmacklem if (nfsv4_opflag[op].modifyfs) 908217023Srmacklem vn_finished_write(temp_mp); 909191783Srmacklem } else { 910191783Srmacklem error = (*(nfsrv4_ops0[op]))(nd, isdgram, 911191783Srmacklem NULL, p, &vpnes); 912191783Srmacklem } 913191783Srmacklem } 914191783Srmacklem }; 915191783Srmacklem if (error) { 916191783Srmacklem if (error == EBADRPC || error == NFSERR_BADXDR) { 917191783Srmacklem nd->nd_repstat = NFSERR_BADXDR; 918191783Srmacklem } else { 919191783Srmacklem nd->nd_repstat = error; 920191783Srmacklem printf("nfsv4 comperr0=%d\n", error); 921191783Srmacklem } 922191783Srmacklem error = 0; 923191783Srmacklem } 924191783Srmacklem retops++; 925191783Srmacklem if (nd->nd_repstat) { 926191783Srmacklem *repp = nfsd_errmap(nd); 927191783Srmacklem break; 928191783Srmacklem } else { 929191783Srmacklem *repp = 0; /* NFS4_OK */ 930191783Srmacklem } 931191783Srmacklem } 932191783Srmacklemnfsmout: 933191783Srmacklem if (error) { 934191783Srmacklem if (error == EBADRPC || error == NFSERR_BADXDR) 935191783Srmacklem nd->nd_repstat = NFSERR_BADXDR; 936191783Srmacklem else 937191783Srmacklem printf("nfsv4 comperr1=%d\n", error); 938191783Srmacklem } 939191783Srmacklem if (taglen == -1) { 940191783Srmacklem NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 941191783Srmacklem *tl++ = 0; 942191783Srmacklem *tl = 0; 943191783Srmacklem } else { 944191783Srmacklem *retopsp = txdr_unsigned(retops); 945191783Srmacklem } 946191783Srmacklem if (vp) 947191783Srmacklem vrele(vp); 948191783Srmacklem if (savevp) 949191783Srmacklem vrele(savevp); 950191783Srmacklem NFSLOCKV4ROOTMUTEX(); 951191783Srmacklem nfsv4_relref(&nfsv4rootfs_lock); 952191783Srmacklem NFSUNLOCKV4ROOTMUTEX(); 953224086Szack 954224086Szack NFSEXITCODE2(0, nd); 955191783Srmacklem} 956