19ec7b004SRick Macklem /*- 29ec7b004SRick Macklem * Copyright (c) 1989, 1993 39ec7b004SRick Macklem * The Regents of the University of California. All rights reserved. 49ec7b004SRick Macklem * 59ec7b004SRick Macklem * This code is derived from software contributed to Berkeley by 69ec7b004SRick Macklem * Rick Macklem at The University of Guelph. 79ec7b004SRick Macklem * 89ec7b004SRick Macklem * Redistribution and use in source and binary forms, with or without 99ec7b004SRick Macklem * modification, are permitted provided that the following conditions 109ec7b004SRick Macklem * are met: 119ec7b004SRick Macklem * 1. Redistributions of source code must retain the above copyright 129ec7b004SRick Macklem * notice, this list of conditions and the following disclaimer. 139ec7b004SRick Macklem * 2. Redistributions in binary form must reproduce the above copyright 149ec7b004SRick Macklem * notice, this list of conditions and the following disclaimer in the 159ec7b004SRick Macklem * documentation and/or other materials provided with the distribution. 169ec7b004SRick Macklem * 4. Neither the name of the University nor the names of its contributors 179ec7b004SRick Macklem * may be used to endorse or promote products derived from this software 189ec7b004SRick Macklem * without specific prior written permission. 199ec7b004SRick Macklem * 209ec7b004SRick Macklem * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 219ec7b004SRick Macklem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 229ec7b004SRick Macklem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 239ec7b004SRick Macklem * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 249ec7b004SRick Macklem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 259ec7b004SRick Macklem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 269ec7b004SRick Macklem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 279ec7b004SRick Macklem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 289ec7b004SRick Macklem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 299ec7b004SRick Macklem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 309ec7b004SRick Macklem * SUCH DAMAGE. 319ec7b004SRick Macklem * 329ec7b004SRick Macklem */ 339ec7b004SRick Macklem 349ec7b004SRick Macklem #include <sys/cdefs.h> 359ec7b004SRick Macklem __FBSDID("$FreeBSD$"); 369ec7b004SRick Macklem 379ec7b004SRick Macklem /* 389ec7b004SRick Macklem * Socket operations for use by the nfs server. 399ec7b004SRick Macklem */ 409ec7b004SRick Macklem 419ec7b004SRick Macklem #ifndef APPLEKEXT 429ec7b004SRick Macklem #include <fs/nfs/nfsport.h> 439ec7b004SRick Macklem 449ec7b004SRick Macklem extern struct nfsstats newnfsstats; 459ec7b004SRick Macklem extern struct nfsrvfh nfs_pubfh, nfs_rootfh; 469ec7b004SRick Macklem extern int nfs_pubfhset, nfs_rootfhset; 479ec7b004SRick Macklem extern struct nfsv4lock nfsv4rootfs_lock; 489ec7b004SRick Macklem extern struct nfsrv_stablefirst nfsrv_stablefirst; 499ec7b004SRick Macklem extern struct nfsclienthashhead nfsclienthash[NFSCLIENTHASHSIZE]; 509ec7b004SRick Macklem extern int nfsrc_floodlevel, nfsrc_tcpsavedreplies; 519ec7b004SRick Macklem NFSV4ROOTLOCKMUTEX; 529ec7b004SRick Macklem NFSSTATESPINLOCK; 539ec7b004SRick Macklem vnode_t nfsv4root_vp = NULL; 549ec7b004SRick Macklem int nfsv4root_set = 0; 559ec7b004SRick Macklem 569ec7b004SRick Macklem int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *, 579ec7b004SRick Macklem int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = { 589ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 599ec7b004SRick Macklem nfsrvd_getattr, 609ec7b004SRick Macklem nfsrvd_setattr, 619ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 629ec7b004SRick Macklem nfsrvd_access, 639ec7b004SRick Macklem nfsrvd_readlink, 649ec7b004SRick Macklem nfsrvd_read, 659ec7b004SRick Macklem nfsrvd_write, 669ec7b004SRick Macklem nfsrvd_create, 679ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 689ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 699ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 709ec7b004SRick Macklem nfsrvd_remove, 719ec7b004SRick Macklem nfsrvd_remove, 729ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 739ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 749ec7b004SRick Macklem nfsrvd_readdir, 759ec7b004SRick Macklem nfsrvd_readdirplus, 769ec7b004SRick Macklem nfsrvd_statfs, 779ec7b004SRick Macklem nfsrvd_fsinfo, 789ec7b004SRick Macklem nfsrvd_pathconf, 799ec7b004SRick Macklem nfsrvd_commit, 809ec7b004SRick Macklem }; 819ec7b004SRick Macklem 829ec7b004SRick Macklem int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *, 839ec7b004SRick Macklem int, vnode_t , vnode_t *, fhandle_t *, 849ec7b004SRick Macklem NFSPROC_T *, struct nfsexstuff *) = { 859ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 869ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 879ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 889ec7b004SRick Macklem nfsrvd_lookup, 899ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 909ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 919ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 929ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 939ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 949ec7b004SRick Macklem nfsrvd_mkdir, 959ec7b004SRick Macklem nfsrvd_symlink, 969ec7b004SRick Macklem nfsrvd_mknod, 979ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 989ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 999ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1009ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1019ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1029ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1039ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1049ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1059ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1069ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1079ec7b004SRick Macklem }; 1089ec7b004SRick Macklem 1099ec7b004SRick Macklem int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *, 1109ec7b004SRick Macklem int, vnode_t , vnode_t , NFSPROC_T *, 1119ec7b004SRick Macklem struct nfsexstuff *, struct nfsexstuff *) = { 1129ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 1139ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 1149ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 1159ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 1169ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 1179ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 1189ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 1199ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 1209ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 1219ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 1229ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 1239ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 1249ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 1259ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 1269ec7b004SRick Macklem nfsrvd_rename, 1279ec7b004SRick Macklem nfsrvd_link, 1289ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 1299ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 1309ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 1319ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 1329ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 1339ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 1349ec7b004SRick Macklem }; 1359ec7b004SRick Macklem 1369ec7b004SRick Macklem int (*nfsrv4_ops0[NFSV4OP_NOPS])(struct nfsrv_descript *, 1379ec7b004SRick Macklem int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = { 1389ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 1399ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 1409ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 1419ec7b004SRick Macklem nfsrvd_access, 1429ec7b004SRick Macklem nfsrvd_close, 1439ec7b004SRick Macklem nfsrvd_commit, 1449ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 1459ec7b004SRick Macklem nfsrvd_delegpurge, 1469ec7b004SRick Macklem nfsrvd_delegreturn, 1479ec7b004SRick Macklem nfsrvd_getattr, 1489ec7b004SRick Macklem nfsrvd_getfh, 1499ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 1509ec7b004SRick Macklem nfsrvd_lock, 1519ec7b004SRick Macklem nfsrvd_lockt, 1529ec7b004SRick Macklem nfsrvd_locku, 1539ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 1549ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 1559ec7b004SRick Macklem nfsrvd_verify, 1569ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 1579ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 1589ec7b004SRick Macklem nfsrvd_openconfirm, 1599ec7b004SRick Macklem nfsrvd_opendowngrade, 1609ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 1619ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 1629ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 1639ec7b004SRick Macklem nfsrvd_read, 1649ec7b004SRick Macklem nfsrvd_readdirplus, 1659ec7b004SRick Macklem nfsrvd_readlink, 1669ec7b004SRick Macklem nfsrvd_remove, 1679ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 1689ec7b004SRick Macklem nfsrvd_renew, 1699ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 1709ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0, 1719ec7b004SRick Macklem nfsrvd_secinfo, 1729ec7b004SRick Macklem nfsrvd_setattr, 1739ec7b004SRick Macklem nfsrvd_setclientid, 1749ec7b004SRick Macklem nfsrvd_setclientidcfrm, 1759ec7b004SRick Macklem nfsrvd_verify, 1769ec7b004SRick Macklem nfsrvd_write, 1779ec7b004SRick Macklem nfsrvd_releaselckown, 1789ec7b004SRick Macklem }; 1799ec7b004SRick Macklem 1809ec7b004SRick Macklem int (*nfsrv4_ops1[NFSV4OP_NOPS])(struct nfsrv_descript *, 1819ec7b004SRick Macklem int, vnode_t , vnode_t *, fhandle_t *, 1829ec7b004SRick Macklem NFSPROC_T *, struct nfsexstuff *) = { 1839ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1849ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1859ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1869ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1879ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1889ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1899ec7b004SRick Macklem nfsrvd_mknod, 1909ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1919ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1929ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1939ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1949ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1959ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1969ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1979ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 1989ec7b004SRick Macklem nfsrvd_lookup, 1999ec7b004SRick Macklem nfsrvd_lookup, 2009ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 2019ec7b004SRick Macklem nfsrvd_open, 2029ec7b004SRick Macklem nfsrvd_openattr, 2039ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 2049ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 2059ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 2069ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 2079ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 2089ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 2099ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 2109ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 2119ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 2129ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 2139ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 2149ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 2159ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 2169ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 2179ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 2189ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 2199ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 2209ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 2219ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 2229ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 2239ec7b004SRick Macklem }; 2249ec7b004SRick Macklem 2259ec7b004SRick Macklem int (*nfsrv4_ops2[NFSV4OP_NOPS])(struct nfsrv_descript *, 2269ec7b004SRick Macklem int, vnode_t , vnode_t , NFSPROC_T *, 2279ec7b004SRick Macklem struct nfsexstuff *, struct nfsexstuff *) = { 2289ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2299ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2309ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2319ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2329ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2339ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2349ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2359ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2369ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2379ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2389ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2399ec7b004SRick Macklem nfsrvd_link, 2409ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2419ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2429ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2439ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2449ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2459ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2469ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2479ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2489ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2499ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2509ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2519ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2529ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2539ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2549ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2559ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2569ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2579ec7b004SRick Macklem nfsrvd_rename, 2589ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2599ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2609ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2619ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2629ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2639ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2649ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2659ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2669ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2679ec7b004SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 2689ec7b004SRick Macklem }; 2699ec7b004SRick Macklem #endif /* !APPLEKEXT */ 2709ec7b004SRick Macklem 2719ec7b004SRick Macklem /* 2729ec7b004SRick Macklem * Static array that defines which nfs rpc's are nonidempotent 2739ec7b004SRick Macklem */ 2749ec7b004SRick Macklem static int nfsrv_nonidempotent[NFS_V3NPROCS] = { 2759ec7b004SRick Macklem FALSE, 2769ec7b004SRick Macklem FALSE, 2779ec7b004SRick Macklem TRUE, 2789ec7b004SRick Macklem FALSE, 2799ec7b004SRick Macklem FALSE, 2809ec7b004SRick Macklem FALSE, 2819ec7b004SRick Macklem FALSE, 2829ec7b004SRick Macklem TRUE, 2839ec7b004SRick Macklem TRUE, 2849ec7b004SRick Macklem TRUE, 2859ec7b004SRick Macklem TRUE, 2869ec7b004SRick Macklem TRUE, 2879ec7b004SRick Macklem TRUE, 2889ec7b004SRick Macklem TRUE, 2899ec7b004SRick Macklem TRUE, 2909ec7b004SRick Macklem TRUE, 2919ec7b004SRick Macklem FALSE, 2929ec7b004SRick Macklem FALSE, 2939ec7b004SRick Macklem FALSE, 2949ec7b004SRick Macklem FALSE, 2959ec7b004SRick Macklem FALSE, 2969ec7b004SRick Macklem FALSE, 2979ec7b004SRick Macklem }; 2989ec7b004SRick Macklem 2999ec7b004SRick Macklem /* 3009ec7b004SRick Macklem * This static array indicates whether or not the RPC modifies the 3019ec7b004SRick Macklem * file system. 3029ec7b004SRick Macklem */ 3039ec7b004SRick Macklem static int nfs_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0, 3049ec7b004SRick Macklem 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3059ec7b004SRick Macklem 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; 3069ec7b004SRick Macklem 3079ec7b004SRick Macklem /* local functions */ 3089ec7b004SRick Macklem static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, 3099ec7b004SRick Macklem NFSPROC_T *p); 3109ec7b004SRick Macklem 3119ec7b004SRick Macklem 3129ec7b004SRick Macklem /* 3139ec7b004SRick Macklem * This static array indicates which server procedures require the extra 3149ec7b004SRick Macklem * arguments to return the current file handle for V2, 3. 3159ec7b004SRick Macklem */ 3169ec7b004SRick Macklem static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 3179ec7b004SRick Macklem 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 }; 3189ec7b004SRick Macklem 3199ec7b004SRick Macklem extern struct nfsv4_opflag nfsv4_opflag[NFSV4OP_NOPS]; 3209ec7b004SRick Macklem 3219ec7b004SRick Macklem static int nfsv3to4op[NFS_V3NPROCS] = { 3229ec7b004SRick Macklem NFSPROC_NULL, 3239ec7b004SRick Macklem NFSV4OP_GETATTR, 3249ec7b004SRick Macklem NFSV4OP_SETATTR, 3259ec7b004SRick Macklem NFSV4OP_LOOKUP, 3269ec7b004SRick Macklem NFSV4OP_ACCESS, 3279ec7b004SRick Macklem NFSV4OP_READLINK, 3289ec7b004SRick Macklem NFSV4OP_READ, 3299ec7b004SRick Macklem NFSV4OP_WRITE, 3309ec7b004SRick Macklem NFSV4OP_V3CREATE, 3319ec7b004SRick Macklem NFSV4OP_MKDIR, 3329ec7b004SRick Macklem NFSV4OP_SYMLINK, 3339ec7b004SRick Macklem NFSV4OP_MKNOD, 3349ec7b004SRick Macklem NFSV4OP_REMOVE, 3359ec7b004SRick Macklem NFSV4OP_RMDIR, 3369ec7b004SRick Macklem NFSV4OP_RENAME, 3379ec7b004SRick Macklem NFSV4OP_LINK, 3389ec7b004SRick Macklem NFSV4OP_READDIR, 3399ec7b004SRick Macklem NFSV4OP_READDIRPLUS, 3409ec7b004SRick Macklem NFSV4OP_FSSTAT, 3419ec7b004SRick Macklem NFSV4OP_FSINFO, 3429ec7b004SRick Macklem NFSV4OP_PATHCONF, 3439ec7b004SRick Macklem NFSV4OP_COMMIT, 3449ec7b004SRick Macklem }; 3459ec7b004SRick Macklem 3469ec7b004SRick Macklem /* 3479ec7b004SRick Macklem * Do an RPC. Basically, get the file handles translated to vnode pointers 3489ec7b004SRick Macklem * and then call the appropriate server routine. The server routines are 3499ec7b004SRick Macklem * split into groups, based on whether they use a file handle or file 3509ec7b004SRick Macklem * handle plus name or ... 3519ec7b004SRick Macklem * The NFS V4 Compound RPC is performed separately by nfsrvd_compound(). 3529ec7b004SRick Macklem */ 3539ec7b004SRick Macklem APPLESTATIC void 3549ec7b004SRick Macklem nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, 3559ec7b004SRick Macklem NFSPROC_T *p) 3569ec7b004SRick Macklem { 35717891d00SRick Macklem int error = 0, lktype; 3589ec7b004SRick Macklem vnode_t vp; 3599ec7b004SRick Macklem mount_t mp = NULL; 3609ec7b004SRick Macklem struct nfsrvfh fh; 3619ec7b004SRick Macklem struct nfsexstuff nes; 3629ec7b004SRick Macklem 3639ec7b004SRick Macklem /* 3649ec7b004SRick Macklem * Get a locked vnode for the first file handle 3659ec7b004SRick Macklem */ 3669ec7b004SRick Macklem if (!(nd->nd_flag & ND_NFSV4)) { 367b38f7723SKonstantin Belousov KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc")); 3689ec7b004SRick Macklem /* 3699ec7b004SRick Macklem * For NFSv3, if the malloc/mget allocation is near limits, 3709ec7b004SRick Macklem * return NFSERR_DELAY. 3719ec7b004SRick Macklem */ 3729ec7b004SRick Macklem if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) { 3739ec7b004SRick Macklem nd->nd_repstat = NFSERR_DELAY; 3749ec7b004SRick Macklem vp = NULL; 3759ec7b004SRick Macklem } else { 3769ec7b004SRick Macklem error = nfsrv_mtofh(nd, &fh); 3779ec7b004SRick Macklem if (error) { 3789ec7b004SRick Macklem if (error != EBADRPC) 3799ec7b004SRick Macklem printf("nfs dorpc err1=%d\n", error); 3809ec7b004SRick Macklem nd->nd_repstat = NFSERR_GARBAGE; 3819ec7b004SRick Macklem return; 3829ec7b004SRick Macklem } 38317891d00SRick Macklem if (nd->nd_procnum == NFSPROC_READ || 38417891d00SRick Macklem nd->nd_procnum == NFSPROC_READDIR || 38517891d00SRick Macklem nd->nd_procnum == NFSPROC_READLINK || 38617891d00SRick Macklem nd->nd_procnum == NFSPROC_GETATTR || 38717891d00SRick Macklem nd->nd_procnum == NFSPROC_ACCESS) 38817891d00SRick Macklem lktype = LK_SHARED; 38917891d00SRick Macklem else 39017891d00SRick Macklem lktype = LK_EXCLUSIVE; 3919ec7b004SRick Macklem nes.nes_vfslocked = 0; 3929ec7b004SRick Macklem if (nd->nd_flag & ND_PUBLOOKUP) 39317891d00SRick Macklem nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes, 3949ec7b004SRick Macklem &mp, nfs_writerpc[nd->nd_procnum], p); 3959ec7b004SRick Macklem else 39617891d00SRick Macklem nfsd_fhtovp(nd, &fh, lktype, &vp, &nes, 3979ec7b004SRick Macklem &mp, nfs_writerpc[nd->nd_procnum], p); 3989ec7b004SRick Macklem if (nd->nd_repstat == NFSERR_PROGNOTV4) 3999ec7b004SRick Macklem return; 4009ec7b004SRick Macklem } 4019ec7b004SRick Macklem } 4029ec7b004SRick Macklem 4039ec7b004SRick Macklem /* 4049ec7b004SRick Macklem * For V2 and 3, set the ND_SAVEREPLY flag for the recent request 4059ec7b004SRick Macklem * cache, as required. 4069ec7b004SRick Macklem * For V4, nfsrvd_compound() does this. 4079ec7b004SRick Macklem */ 4089ec7b004SRick Macklem if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum]) 4099ec7b004SRick Macklem nd->nd_flag |= ND_SAVEREPLY; 4109ec7b004SRick Macklem 4119ec7b004SRick Macklem nfsrvd_rephead(nd); 4129ec7b004SRick Macklem /* 4139ec7b004SRick Macklem * If nd_repstat is non-zero, just fill in the reply status 4149ec7b004SRick Macklem * to complete the RPC reply for V2. Otherwise, you must do 4159ec7b004SRick Macklem * the RPC. 4169ec7b004SRick Macklem */ 4179ec7b004SRick Macklem if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) { 4189ec7b004SRick Macklem *nd->nd_errp = nfsd_errmap(nd); 4199ec7b004SRick Macklem NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]); 4209ec7b004SRick Macklem if (mp != NULL) { 4219ec7b004SRick Macklem if (nfs_writerpc[nd->nd_procnum]) 4229ec7b004SRick Macklem NFS_ENDWRITE(mp); 4239ec7b004SRick Macklem if (nes.nes_vfslocked) 4249ec7b004SRick Macklem nfsvno_unlockvfs(mp); 4259ec7b004SRick Macklem } 4269ec7b004SRick Macklem return; 4279ec7b004SRick Macklem } 4289ec7b004SRick Macklem 4299ec7b004SRick Macklem /* 4309ec7b004SRick Macklem * Now the procedure can be performed. For V4, nfsrvd_compound() 4319ec7b004SRick Macklem * works through the sub-rpcs, otherwise just call the procedure. 4329ec7b004SRick Macklem * The procedures are in three groups with different arguments. 4339ec7b004SRick Macklem * The group is indicated by the value in nfs_retfh[]. 4349ec7b004SRick Macklem */ 4359ec7b004SRick Macklem if (nd->nd_flag & ND_NFSV4) { 4369ec7b004SRick Macklem nfsrvd_compound(nd, isdgram, p); 4379ec7b004SRick Macklem } else { 4389ec7b004SRick Macklem if (nfs_retfh[nd->nd_procnum] == 1) { 4399ec7b004SRick Macklem if (vp) 4409ec7b004SRick Macklem NFSVOPUNLOCK(vp, 0, p); 4419ec7b004SRick Macklem error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram, 4429ec7b004SRick Macklem vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes); 4439ec7b004SRick Macklem } else if (nfs_retfh[nd->nd_procnum] == 2) { 4449ec7b004SRick Macklem error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram, 4459ec7b004SRick Macklem vp, NULL, p, &nes, NULL); 4469ec7b004SRick Macklem } else { 4479ec7b004SRick Macklem error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram, 4489ec7b004SRick Macklem vp, p, &nes); 4499ec7b004SRick Macklem } 4509ec7b004SRick Macklem if (mp) { 4519ec7b004SRick Macklem if (nfs_writerpc[nd->nd_procnum]) 4529ec7b004SRick Macklem NFS_ENDWRITE(mp); 4539ec7b004SRick Macklem if (nes.nes_vfslocked) 4549ec7b004SRick Macklem nfsvno_unlockvfs(mp); 4559ec7b004SRick Macklem } 4569ec7b004SRick Macklem NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]); 4579ec7b004SRick Macklem } 4589ec7b004SRick Macklem if (error) { 4599ec7b004SRick Macklem if (error != EBADRPC) 4609ec7b004SRick Macklem printf("nfs dorpc err2=%d\n", error); 4619ec7b004SRick Macklem nd->nd_repstat = NFSERR_GARBAGE; 4629ec7b004SRick Macklem } 4639ec7b004SRick Macklem *nd->nd_errp = nfsd_errmap(nd); 4649ec7b004SRick Macklem 4659ec7b004SRick Macklem /* 4669ec7b004SRick Macklem * Don't cache certain reply status values. 4679ec7b004SRick Macklem */ 4689ec7b004SRick Macklem if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) && 4699ec7b004SRick Macklem (nd->nd_repstat == NFSERR_GARBAGE || 4709ec7b004SRick Macklem nd->nd_repstat == NFSERR_BADXDR || 4719ec7b004SRick Macklem nd->nd_repstat == NFSERR_MOVED || 4729ec7b004SRick Macklem nd->nd_repstat == NFSERR_DELAY || 4739ec7b004SRick Macklem nd->nd_repstat == NFSERR_BADSEQID || 4749ec7b004SRick Macklem nd->nd_repstat == NFSERR_RESOURCE || 4759ec7b004SRick Macklem nd->nd_repstat == NFSERR_SERVERFAULT || 4769ec7b004SRick Macklem nd->nd_repstat == NFSERR_STALECLIENTID || 4779ec7b004SRick Macklem nd->nd_repstat == NFSERR_STALESTATEID || 4789ec7b004SRick Macklem nd->nd_repstat == NFSERR_OLDSTATEID || 4799ec7b004SRick Macklem nd->nd_repstat == NFSERR_BADSTATEID || 4809ec7b004SRick Macklem nd->nd_repstat == NFSERR_GRACE || 4819ec7b004SRick Macklem nd->nd_repstat == NFSERR_NOGRACE)) 4829ec7b004SRick Macklem nd->nd_flag &= ~ND_SAVEREPLY; 4839ec7b004SRick Macklem } 4849ec7b004SRick Macklem 4859ec7b004SRick Macklem /* 4869ec7b004SRick Macklem * Breaks down a compound RPC request and calls the server routines for 4879ec7b004SRick Macklem * the subprocedures. 4889ec7b004SRick Macklem * Some suboperations are performed directly here to simplify file handle<--> 4899ec7b004SRick Macklem * vnode pointer handling. 4909ec7b004SRick Macklem */ 4919ec7b004SRick Macklem static void 4929ec7b004SRick Macklem nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, 4939ec7b004SRick Macklem NFSPROC_T *p) 4949ec7b004SRick Macklem { 4959ec7b004SRick Macklem int i, op; 4969ec7b004SRick Macklem u_int32_t *tl; 4979ec7b004SRick Macklem struct nfsclient *clp, *nclp; 4989ec7b004SRick Macklem int numops, taglen = -1, error = 0, igotlock; 4999ec7b004SRick Macklem u_int32_t minorvers, retops = 0, *retopsp = NULL, *repp; 5009ec7b004SRick Macklem u_char tag[NFSV4_SMALLSTR + 1], *tagstr; 5019ec7b004SRick Macklem vnode_t vp, nvp, savevp; 5029ec7b004SRick Macklem struct nfsrvfh fh; 5039ec7b004SRick Macklem mount_t mp, savemp; 5049ec7b004SRick Macklem struct ucred *credanon; 5059ec7b004SRick Macklem struct nfsexstuff nes, vpnes, savevpnes; 5069ec7b004SRick Macklem static u_int64_t compref = 0; 5079ec7b004SRick Macklem 5089ec7b004SRick Macklem NFSVNO_EXINIT(&vpnes); 5099ec7b004SRick Macklem NFSVNO_EXINIT(&savevpnes); 5109ec7b004SRick Macklem /* 5119ec7b004SRick Macklem * Put the seq# of the current compound RPC in nfsrv_descript. 5129ec7b004SRick Macklem * (This is used by nfsrv_checkgetattr(), to see if the write 5139ec7b004SRick Macklem * delegation was created by the same compound RPC as the one 5149ec7b004SRick Macklem * with that Getattr in it.) 5159ec7b004SRick Macklem * Don't worry about the 64bit number wrapping around. It ain't 5169ec7b004SRick Macklem * gonna happen before this server gets shut down/rebooted. 5179ec7b004SRick Macklem */ 5189ec7b004SRick Macklem nd->nd_compref = compref++; 5199ec7b004SRick Macklem 5209ec7b004SRick Macklem /* 5219ec7b004SRick Macklem * Check for and optionally get a lock on the root. This lock means that 5229ec7b004SRick Macklem * no nfsd will be fiddling with the V4 file system and state stuff. It 5239ec7b004SRick Macklem * is required when the V4 root is being changed, the stable storage 5249ec7b004SRick Macklem * restart file is being updated, or callbacks are being done. 5259ec7b004SRick Macklem * When any of the nfsd are processing an NFSv4 compound RPC, they must 5269ec7b004SRick Macklem * either hold a reference count (nfs_usecnt) or the lock. When 5279ec7b004SRick Macklem * nfsrv_unlock() is called to release the lock, it can optionally 5289ec7b004SRick Macklem * also get a reference count, which saves the need for a call to 5299ec7b004SRick Macklem * nfsrv_getref() after nfsrv_unlock(). 5309ec7b004SRick Macklem */ 5319ec7b004SRick Macklem /* 5329ec7b004SRick Macklem * First, check to see if we need to wait for an update lock. 5339ec7b004SRick Macklem */ 5349ec7b004SRick Macklem igotlock = 0; 5359ec7b004SRick Macklem NFSLOCKV4ROOTMUTEX(); 5369ec7b004SRick Macklem if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK) 5379ec7b004SRick Macklem igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 5389ec7b004SRick Macklem NFSV4ROOTLOCKMUTEXPTR); 5399ec7b004SRick Macklem else 5409ec7b004SRick Macklem igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL, 5419ec7b004SRick Macklem NFSV4ROOTLOCKMUTEXPTR); 5429ec7b004SRick Macklem NFSUNLOCKV4ROOTMUTEX(); 5439ec7b004SRick Macklem if (igotlock) { 5449ec7b004SRick Macklem /* 5459ec7b004SRick Macklem * If I got the lock, I can update the stable storage file. 5469ec7b004SRick Macklem * Done when the grace period is over or a client has long 5479ec7b004SRick Macklem * since expired. 5489ec7b004SRick Macklem */ 5499ec7b004SRick Macklem nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK; 5509ec7b004SRick Macklem if ((nfsrv_stablefirst.nsf_flags & 5519ec7b004SRick Macklem (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER) 5529ec7b004SRick Macklem nfsrv_updatestable(p); 5539ec7b004SRick Macklem 5549ec7b004SRick Macklem /* 5559ec7b004SRick Macklem * If at least one client has long since expired, search 5569ec7b004SRick Macklem * the client list for them, write a REVOKE record on the 5579ec7b004SRick Macklem * stable storage file and then remove them from the client 5589ec7b004SRick Macklem * list. 5599ec7b004SRick Macklem */ 5609ec7b004SRick Macklem if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) { 5619ec7b004SRick Macklem nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT; 5629ec7b004SRick Macklem for (i = 0; i < NFSCLIENTHASHSIZE; i++) { 5639ec7b004SRick Macklem LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, 5649ec7b004SRick Macklem nclp) { 5659ec7b004SRick Macklem if (clp->lc_flags & LCL_EXPIREIT) { 5669ec7b004SRick Macklem if (!LIST_EMPTY(&clp->lc_open) || 5679ec7b004SRick Macklem !LIST_EMPTY(&clp->lc_deleg)) 5689ec7b004SRick Macklem nfsrv_writestable(clp->lc_id, 5699ec7b004SRick Macklem clp->lc_idlen, NFSNST_REVOKE, p); 5709ec7b004SRick Macklem nfsrv_cleanclient(clp, p); 5719ec7b004SRick Macklem nfsrv_freedeleglist(&clp->lc_deleg); 5729ec7b004SRick Macklem nfsrv_freedeleglist(&clp->lc_olddeleg); 5739ec7b004SRick Macklem LIST_REMOVE(clp, lc_hash); 5749ec7b004SRick Macklem nfsrv_zapclient(clp, p); 5759ec7b004SRick Macklem } 5769ec7b004SRick Macklem } 5779ec7b004SRick Macklem } 5789ec7b004SRick Macklem } 5799ec7b004SRick Macklem NFSLOCKV4ROOTMUTEX(); 5809ec7b004SRick Macklem nfsv4_unlock(&nfsv4rootfs_lock, 1); 5819ec7b004SRick Macklem NFSUNLOCKV4ROOTMUTEX(); 5829ec7b004SRick Macklem } else { 5839ec7b004SRick Macklem /* 5849ec7b004SRick Macklem * If we didn't get the lock, we need to get a refcnt, 5859ec7b004SRick Macklem * which also checks for and waits for the lock. 5869ec7b004SRick Macklem */ 5879ec7b004SRick Macklem NFSLOCKV4ROOTMUTEX(); 5889ec7b004SRick Macklem nfsv4_getref(&nfsv4rootfs_lock, NULL, 5899ec7b004SRick Macklem NFSV4ROOTLOCKMUTEXPTR); 5909ec7b004SRick Macklem NFSUNLOCKV4ROOTMUTEX(); 5919ec7b004SRick Macklem } 5929ec7b004SRick Macklem 5939ec7b004SRick Macklem /* 5949ec7b004SRick Macklem * If flagged, search for open owners that haven't had any opens 5959ec7b004SRick Macklem * for a long time. 5969ec7b004SRick Macklem */ 5979ec7b004SRick Macklem if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) { 5989ec7b004SRick Macklem nfsrv_throwawayopens(p); 5999ec7b004SRick Macklem } 6009ec7b004SRick Macklem 6019ec7b004SRick Macklem savevp = vp = NULL; 6029ec7b004SRick Macklem savevpnes.nes_vfslocked = vpnes.nes_vfslocked = 0; 6039ec7b004SRick Macklem savemp = mp = NULL; 6049ec7b004SRick Macklem NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 6059ec7b004SRick Macklem taglen = fxdr_unsigned(int, *tl); 6069ec7b004SRick Macklem if (taglen < 0) { 6079ec7b004SRick Macklem error = EBADRPC; 6089ec7b004SRick Macklem goto nfsmout; 6099ec7b004SRick Macklem } 6109ec7b004SRick Macklem if (taglen <= NFSV4_SMALLSTR) 6119ec7b004SRick Macklem tagstr = tag; 6129ec7b004SRick Macklem else 6139ec7b004SRick Macklem tagstr = malloc(taglen + 1, M_TEMP, M_WAITOK); 6149ec7b004SRick Macklem error = nfsrv_mtostr(nd, tagstr, taglen); 6159ec7b004SRick Macklem if (error) { 6169ec7b004SRick Macklem if (taglen > NFSV4_SMALLSTR) 6179ec7b004SRick Macklem free(tagstr, M_TEMP); 6189ec7b004SRick Macklem taglen = -1; 6199ec7b004SRick Macklem goto nfsmout; 6209ec7b004SRick Macklem } 6219ec7b004SRick Macklem (void) nfsm_strtom(nd, tag, taglen); 6229ec7b004SRick Macklem if (taglen > NFSV4_SMALLSTR) { 6239ec7b004SRick Macklem free(tagstr, M_TEMP); 6249ec7b004SRick Macklem } 6259ec7b004SRick Macklem NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED); 6269ec7b004SRick Macklem NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 6279ec7b004SRick Macklem minorvers = fxdr_unsigned(u_int32_t, *tl++); 6289ec7b004SRick Macklem if (minorvers != NFSV4_MINORVERSION) 6299ec7b004SRick Macklem nd->nd_repstat = NFSERR_MINORVERMISMATCH; 6309ec7b004SRick Macklem if (nd->nd_repstat) 6319ec7b004SRick Macklem numops = 0; 6329ec7b004SRick Macklem else 6339ec7b004SRick Macklem numops = fxdr_unsigned(int, *tl); 6349ec7b004SRick Macklem /* 6359ec7b004SRick Macklem * Loop around doing the sub ops. 6369ec7b004SRick Macklem * vp - is an unlocked vnode pointer for the CFH 6379ec7b004SRick Macklem * savevp - is an unlocked vnode pointer for the SAVEDFH 6389ec7b004SRick Macklem * (at some future date, it might turn out to be more appropriate 6399ec7b004SRick Macklem * to keep the file handles instead of vnode pointers?) 6409ec7b004SRick Macklem * savevpnes and vpnes - are the export flags for the above. 6419ec7b004SRick Macklem */ 6429ec7b004SRick Macklem for (i = 0; i < numops; i++) { 6439ec7b004SRick Macklem NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 6449ec7b004SRick Macklem NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED); 6459183a2a3SRick Macklem *repp = *tl; 6469ec7b004SRick Macklem op = fxdr_unsigned(int, *tl); 6479ec7b004SRick Macklem if (op < NFSV4OP_ACCESS || op >= NFSV4OP_NOPS) { 6489ec7b004SRick Macklem nd->nd_repstat = NFSERR_OPILLEGAL; 6499183a2a3SRick Macklem *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL); 6509ec7b004SRick Macklem *repp = nfsd_errmap(nd); 6519ec7b004SRick Macklem retops++; 6529ec7b004SRick Macklem break; 6539183a2a3SRick Macklem } else { 6549183a2a3SRick Macklem repp++; 6559ec7b004SRick Macklem } 6569ec7b004SRick Macklem 6579ec7b004SRick Macklem /* 6589ec7b004SRick Macklem * Check for a referral on the current FH and, if so, return 6599ec7b004SRick Macklem * NFSERR_MOVED for all ops that allow it, except Getattr. 6609ec7b004SRick Macklem */ 6619ec7b004SRick Macklem if (vp != NULL && op != NFSV4OP_GETATTR && 6629ec7b004SRick Macklem nfsv4root_getreferral(vp, NULL, 0) != NULL && 6639ec7b004SRick Macklem nfsrv_errmoved(op)) { 6649ec7b004SRick Macklem nd->nd_repstat = NFSERR_MOVED; 6659ec7b004SRick Macklem *repp = nfsd_errmap(nd); 6669ec7b004SRick Macklem retops++; 6679ec7b004SRick Macklem break; 6689ec7b004SRick Macklem } 6699ec7b004SRick Macklem 6709ec7b004SRick Macklem nd->nd_procnum = op; 6719ec7b004SRick Macklem /* 6729ec7b004SRick Macklem * If over flood level, reply NFSERR_RESOURCE, if at the first 6739ec7b004SRick Macklem * Op. (Since a client recovery from NFSERR_RESOURCE can get 6749ec7b004SRick Macklem * really nasty for certain Op sequences, I'll play it safe 6759ec7b004SRick Macklem * and only return the error at the beginning.) The cache 6769ec7b004SRick Macklem * will still function over flood level, but uses lots of 6779ec7b004SRick Macklem * mbufs.) 6789ec7b004SRick Macklem * If nfsrv_mallocmget_limit() returns True, the system is near 6799ec7b004SRick Macklem * to its limit for memory that malloc()/mget() can allocate. 6809ec7b004SRick Macklem */ 6819ec7b004SRick Macklem if (i == 0 && nd->nd_rp->rc_refcnt == 0 && 6829ec7b004SRick Macklem (nfsrv_mallocmget_limit() || 6839ec7b004SRick Macklem nfsrc_tcpsavedreplies > nfsrc_floodlevel)) { 6849ec7b004SRick Macklem if (nfsrc_tcpsavedreplies > nfsrc_floodlevel) { 6859ec7b004SRick Macklem printf("nfsd server cache flooded, try to"); 6869ec7b004SRick Macklem printf(" increase nfsrc_floodlevel\n"); 6879ec7b004SRick Macklem } 6889ec7b004SRick Macklem nd->nd_repstat = NFSERR_RESOURCE; 6899ec7b004SRick Macklem *repp = nfsd_errmap(nd); 6909ec7b004SRick Macklem if (op == NFSV4OP_SETATTR) { 6919ec7b004SRick Macklem /* 6929ec7b004SRick Macklem * Setattr replies require a bitmap. 6939ec7b004SRick Macklem * even for errors like these. 6949ec7b004SRick Macklem */ 6959ec7b004SRick Macklem NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 6969ec7b004SRick Macklem *tl = 0; 6979ec7b004SRick Macklem } 6989ec7b004SRick Macklem retops++; 6999ec7b004SRick Macklem break; 7009ec7b004SRick Macklem } 7019ec7b004SRick Macklem if (nfsv4_opflag[op].savereply) 7029ec7b004SRick Macklem nd->nd_flag |= ND_SAVEREPLY; 7039ec7b004SRick Macklem NFSINCRGLOBAL(newnfsstats.srvrpccnt[nd->nd_procnum]); 7049ec7b004SRick Macklem switch (op) { 7059ec7b004SRick Macklem case NFSV4OP_PUTFH: 7069ec7b004SRick Macklem error = nfsrv_mtofh(nd, &fh); 7079ec7b004SRick Macklem if (error) 7089ec7b004SRick Macklem goto nfsmout; 7099ec7b004SRick Macklem if (!nd->nd_repstat) { 7109ec7b004SRick Macklem nes.nes_vfslocked = vpnes.nes_vfslocked; 71117891d00SRick Macklem nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes, &mp, 7129ec7b004SRick Macklem 0, p); 7139ec7b004SRick Macklem } 7149ec7b004SRick Macklem /* For now, allow this for non-export FHs */ 7159ec7b004SRick Macklem if (!nd->nd_repstat) { 7169ec7b004SRick Macklem if (vp) 7179ec7b004SRick Macklem vrele(vp); 7189ec7b004SRick Macklem vp = nvp; 7199ec7b004SRick Macklem NFSVOPUNLOCK(vp, 0, p); 7209ec7b004SRick Macklem vpnes = nes; 7219ec7b004SRick Macklem } 7229ec7b004SRick Macklem break; 7239ec7b004SRick Macklem case NFSV4OP_PUTPUBFH: 7249ec7b004SRick Macklem if (nfs_pubfhset) { 7259ec7b004SRick Macklem nes.nes_vfslocked = vpnes.nes_vfslocked; 72617891d00SRick Macklem nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp, 7279ec7b004SRick Macklem &nes, &mp, 0, p); 7289ec7b004SRick Macklem } else { 7299ec7b004SRick Macklem nd->nd_repstat = NFSERR_NOFILEHANDLE; 7309ec7b004SRick Macklem } 7319ec7b004SRick Macklem if (!nd->nd_repstat) { 7329ec7b004SRick Macklem if (vp) 7339ec7b004SRick Macklem vrele(vp); 7349ec7b004SRick Macklem vp = nvp; 7359ec7b004SRick Macklem NFSVOPUNLOCK(vp, 0, p); 7369ec7b004SRick Macklem vpnes = nes; 7379ec7b004SRick Macklem } 7389ec7b004SRick Macklem break; 7399ec7b004SRick Macklem case NFSV4OP_PUTROOTFH: 7409ec7b004SRick Macklem if (nfs_rootfhset) { 7419ec7b004SRick Macklem nes.nes_vfslocked = vpnes.nes_vfslocked; 74217891d00SRick Macklem nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp, 7439ec7b004SRick Macklem &nes, &mp, 0, p); 7449ec7b004SRick Macklem if (!nd->nd_repstat) { 7459ec7b004SRick Macklem if (vp) 7469ec7b004SRick Macklem vrele(vp); 7479ec7b004SRick Macklem vp = nvp; 7489ec7b004SRick Macklem NFSVOPUNLOCK(vp, 0, p); 7499ec7b004SRick Macklem vpnes = nes; 7509ec7b004SRick Macklem } 7519ec7b004SRick Macklem } else if (nfsv4root_vp && nfsv4root_set) { 7529ec7b004SRick Macklem if (vp) { 7539ec7b004SRick Macklem if (vpnes.nes_vfslocked) 7549ec7b004SRick Macklem nfsvno_unlockvfs(mp); 7559ec7b004SRick Macklem vrele(vp); 7569ec7b004SRick Macklem } 7579ec7b004SRick Macklem vp = nfsv4root_vp; 7589ec7b004SRick Macklem VREF(vp); 7599ec7b004SRick Macklem NFSVNO_SETEXRDONLY(&vpnes); 7609ec7b004SRick Macklem vpnes.nes_vfslocked = 0; 7619ec7b004SRick Macklem mp = vnode_mount(vp); 7629ec7b004SRick Macklem } else { 7639ec7b004SRick Macklem nd->nd_repstat = NFSERR_NOFILEHANDLE; 7649ec7b004SRick Macklem } 7659ec7b004SRick Macklem break; 7669ec7b004SRick Macklem case NFSV4OP_SAVEFH: 7679ec7b004SRick Macklem if (vp && NFSVNO_EXPORTED(&vpnes)) { 7689ec7b004SRick Macklem nd->nd_repstat = 0; 7699ec7b004SRick Macklem /* If vp == savevp, a no-op */ 7709ec7b004SRick Macklem if (vp != savevp) { 7719ec7b004SRick Macklem if (savevp) 7729ec7b004SRick Macklem vrele(savevp); 7739ec7b004SRick Macklem VREF(vp); 7749ec7b004SRick Macklem savevp = vp; 7759ec7b004SRick Macklem savevpnes = vpnes; 7769ec7b004SRick Macklem savemp = mp; 7779ec7b004SRick Macklem } 7789ec7b004SRick Macklem } else { 7799ec7b004SRick Macklem nd->nd_repstat = NFSERR_NOFILEHANDLE; 7809ec7b004SRick Macklem } 7819ec7b004SRick Macklem break; 7829ec7b004SRick Macklem case NFSV4OP_RESTOREFH: 7839ec7b004SRick Macklem if (savevp) { 7849ec7b004SRick Macklem nd->nd_repstat = 0; 7859ec7b004SRick Macklem /* If vp == savevp, a no-op */ 7869ec7b004SRick Macklem if (vp != savevp) { 7879ec7b004SRick Macklem VREF(savevp); 7889ec7b004SRick Macklem if (mp == NULL || savemp == NULL) 7899ec7b004SRick Macklem panic("nfscmpmp"); 7909ec7b004SRick Macklem if (!savevpnes.nes_vfslocked && 7919ec7b004SRick Macklem vpnes.nes_vfslocked) { 7929ec7b004SRick Macklem if (mp == savemp) 7939ec7b004SRick Macklem panic("nfscmp2"); 7949ec7b004SRick Macklem nfsvno_unlockvfs(mp); 7959ec7b004SRick Macklem } else if (savevpnes.nes_vfslocked && 7969ec7b004SRick Macklem !vpnes.nes_vfslocked) { 7979ec7b004SRick Macklem if (mp == savemp) 7989ec7b004SRick Macklem panic("nfscmp3"); 7999ec7b004SRick Macklem savevpnes.nes_vfslocked = nfsvno_lockvfs(savemp); 8009ec7b004SRick Macklem } 8019ec7b004SRick Macklem vrele(vp); 8029ec7b004SRick Macklem vp = savevp; 8039ec7b004SRick Macklem vpnes = savevpnes; 8049ec7b004SRick Macklem mp = savemp; 8059ec7b004SRick Macklem } 8069ec7b004SRick Macklem } else { 8079ec7b004SRick Macklem nd->nd_repstat = NFSERR_RESTOREFH; 8089ec7b004SRick Macklem } 8099ec7b004SRick Macklem break; 8109ec7b004SRick Macklem default: 8119ec7b004SRick Macklem /* 8129ec7b004SRick Macklem * Allow a Lookup, Getattr, GetFH, Secinfo on an 8139ec7b004SRick Macklem * non-exported directory if 8149ec7b004SRick Macklem * nfs_rootfhset. Do I need to allow any other Ops? 8159ec7b004SRick Macklem * (You can only have a non-exported vpnes if 8169ec7b004SRick Macklem * nfs_rootfhset is true. See nfsd_fhtovp()) 8179ec7b004SRick Macklem * Allow AUTH_SYS to be used for file systems 8189ec7b004SRick Macklem * exported GSS only for certain Ops, to allow 8199ec7b004SRick Macklem * clients to do mounts more easily. 8209ec7b004SRick Macklem */ 8219ec7b004SRick Macklem if (nfsv4_opflag[op].needscfh && vp) { 8229ec7b004SRick Macklem if (!NFSVNO_EXPORTED(&vpnes) && 8239ec7b004SRick Macklem op != NFSV4OP_LOOKUP && 8249ec7b004SRick Macklem op != NFSV4OP_GETATTR && 8259ec7b004SRick Macklem op != NFSV4OP_GETFH && 8269ec7b004SRick Macklem op != NFSV4OP_SECINFO) 8279ec7b004SRick Macklem nd->nd_repstat = NFSERR_NOFILEHANDLE; 82898ad4453SRick Macklem else if (nfsvno_testexp(nd, &vpnes) && 8299ec7b004SRick Macklem op != NFSV4OP_LOOKUP && 8309ec7b004SRick Macklem op != NFSV4OP_GETFH && 8319ec7b004SRick Macklem op != NFSV4OP_GETATTR && 8329ec7b004SRick Macklem op != NFSV4OP_SECINFO) 8339ec7b004SRick Macklem nd->nd_repstat = NFSERR_WRONGSEC; 8349ec7b004SRick Macklem if (nd->nd_repstat) { 8359ec7b004SRick Macklem if (op == NFSV4OP_SETATTR) { 8369ec7b004SRick Macklem /* 8379ec7b004SRick Macklem * Setattr reply requires a bitmap 8389ec7b004SRick Macklem * even for errors like these. 8399ec7b004SRick Macklem */ 8409ec7b004SRick Macklem NFSM_BUILD(tl, u_int32_t *, 8419ec7b004SRick Macklem NFSX_UNSIGNED); 8429ec7b004SRick Macklem *tl = 0; 8439ec7b004SRick Macklem } 8449ec7b004SRick Macklem break; 8459ec7b004SRick Macklem } 8469ec7b004SRick Macklem } 8479ec7b004SRick Macklem if (nfsv4_opflag[op].retfh == 1) { 8489ec7b004SRick Macklem if (!vp) { 8499ec7b004SRick Macklem nd->nd_repstat = NFSERR_NOFILEHANDLE; 8509ec7b004SRick Macklem break; 8519ec7b004SRick Macklem } 8529ec7b004SRick Macklem VREF(vp); 8539ec7b004SRick Macklem if (nfsv4_opflag[op].modifyfs) 8549ec7b004SRick Macklem NFS_STARTWRITE(NULL, &mp); 8559ec7b004SRick Macklem error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp, 8569ec7b004SRick Macklem &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes); 8579ec7b004SRick Macklem if (!error && !nd->nd_repstat) { 8589ec7b004SRick Macklem if (vfs_statfs(mp)->f_fsid.val[0] != 8599ec7b004SRick Macklem vfs_statfs(vnode_mount(nvp))->f_fsid.val[0] || 8609ec7b004SRick Macklem vfs_statfs(mp)->f_fsid.val[1] != 8619ec7b004SRick Macklem vfs_statfs(vnode_mount(nvp))->f_fsid.val[1]) { 8629ec7b004SRick Macklem if (vfs_statfs(vnode_mount(nvp))->f_fsid.val[0] == 8639ec7b004SRick Macklem NFSV4ROOT_FSID0 && 8649ec7b004SRick Macklem vfs_statfs(vnode_mount(nvp))->f_fsid.val[1] == 8659ec7b004SRick Macklem NFSV4ROOT_FSID1) { 8669ec7b004SRick Macklem if (vpnes.nes_vfslocked) { 8679ec7b004SRick Macklem nfsvno_unlockvfs(mp); 8689ec7b004SRick Macklem vpnes.nes_vfslocked = 0; 8699ec7b004SRick Macklem } 8709ec7b004SRick Macklem NFSVNO_SETEXRDONLY(&vpnes); 8719ec7b004SRick Macklem mp = vnode_mount(nvp); 8729ec7b004SRick Macklem } else { 8739ec7b004SRick Macklem nd->nd_repstat = nfsvno_checkexp(vnode_mount(nvp), 8749ec7b004SRick Macklem nd->nd_nam, &nes, &credanon); 8759ec7b004SRick Macklem if (!nd->nd_repstat) 8769ec7b004SRick Macklem nd->nd_repstat = nfsd_excred(nd, 8779ec7b004SRick Macklem &nes, credanon); 8785679fe19SAlexander Kabaev if (credanon != NULL) 8795679fe19SAlexander Kabaev crfree(credanon); 8809ec7b004SRick Macklem if (!nd->nd_repstat) { 8819ec7b004SRick Macklem if (vpnes.nes_vfslocked) 8829ec7b004SRick Macklem nfsvno_unlockvfs(mp); 8839ec7b004SRick Macklem mp = vnode_mount(nvp); 8849ec7b004SRick Macklem vpnes = nes; 8859ec7b004SRick Macklem vpnes.nes_vfslocked = 8869ec7b004SRick Macklem nfsvno_lockvfs(mp); 8879ec7b004SRick Macklem } 8889ec7b004SRick Macklem } 8899ec7b004SRick Macklem } 8909ec7b004SRick Macklem if (!nd->nd_repstat) { 8919ec7b004SRick Macklem vrele(vp); 8929ec7b004SRick Macklem vp = nvp; 8939ec7b004SRick Macklem } 8949ec7b004SRick Macklem } 8959ec7b004SRick Macklem if (nfsv4_opflag[op].modifyfs) 8969ec7b004SRick Macklem NFS_ENDWRITE(mp); 8979ec7b004SRick Macklem } else if (nfsv4_opflag[op].retfh == 2) { 8989ec7b004SRick Macklem if (vp == NULL || savevp == NULL) { 8999ec7b004SRick Macklem nd->nd_repstat = NFSERR_NOFILEHANDLE; 9009ec7b004SRick Macklem break; 9019ec7b004SRick Macklem } else if (mp != savemp) { 9029ec7b004SRick Macklem nd->nd_repstat = NFSERR_XDEV; 9039ec7b004SRick Macklem break; 9049ec7b004SRick Macklem } 9059ec7b004SRick Macklem VREF(vp); 9069ec7b004SRick Macklem VREF(savevp); 9079ec7b004SRick Macklem if (nfsv4_opflag[op].modifyfs) 9089ec7b004SRick Macklem NFS_STARTWRITE(NULL, &mp); 9099ec7b004SRick Macklem NFSVOPLOCK(savevp, LK_EXCLUSIVE | LK_RETRY, p); 9109ec7b004SRick Macklem error = (*(nfsrv4_ops2[op]))(nd, isdgram, savevp, 9119ec7b004SRick Macklem vp, p, &savevpnes, &vpnes); 9129ec7b004SRick Macklem if (nfsv4_opflag[op].modifyfs) 9139ec7b004SRick Macklem NFS_ENDWRITE(mp); 9149ec7b004SRick Macklem } else { 9159ec7b004SRick Macklem if (nfsv4_opflag[op].retfh != 0) 9169ec7b004SRick Macklem panic("nfsrvd_compound"); 9179ec7b004SRick Macklem if (nfsv4_opflag[op].needscfh) { 91817891d00SRick Macklem if (vp != NULL) { 91917891d00SRick Macklem if (vn_lock(vp, nfsv4_opflag[op].lktype) 92017891d00SRick Macklem != 0) 92117891d00SRick Macklem nd->nd_repstat = NFSERR_PERM; 92217891d00SRick Macklem } else 9239ec7b004SRick Macklem nd->nd_repstat = NFSERR_NOFILEHANDLE; 92417891d00SRick Macklem if (nd->nd_repstat != 0) { 9259ec7b004SRick Macklem if (op == NFSV4OP_SETATTR) { 9269ec7b004SRick Macklem /* 92717891d00SRick Macklem * Setattr reply requires a 92817891d00SRick Macklem * bitmap even for errors like 92917891d00SRick Macklem * these. 9309ec7b004SRick Macklem */ 9319ec7b004SRick Macklem NFSM_BUILD(tl, u_int32_t *, 9329ec7b004SRick Macklem NFSX_UNSIGNED); 9339ec7b004SRick Macklem *tl = 0; 9349ec7b004SRick Macklem } 9359ec7b004SRick Macklem break; 9369ec7b004SRick Macklem } 93717891d00SRick Macklem VREF(vp); 93817891d00SRick Macklem if (nfsv4_opflag[op].modifyfs) 93917891d00SRick Macklem NFS_STARTWRITE(NULL, &mp); 9409ec7b004SRick Macklem error = (*(nfsrv4_ops0[op]))(nd, isdgram, vp, 9419ec7b004SRick Macklem p, &vpnes); 9429ec7b004SRick Macklem if (nfsv4_opflag[op].modifyfs) 9439ec7b004SRick Macklem NFS_ENDWRITE(mp); 9449ec7b004SRick Macklem } else { 9459ec7b004SRick Macklem error = (*(nfsrv4_ops0[op]))(nd, isdgram, 9469ec7b004SRick Macklem NULL, p, &vpnes); 9479ec7b004SRick Macklem } 9489ec7b004SRick Macklem } 9499ec7b004SRick Macklem }; 9509ec7b004SRick Macklem if (error) { 9519ec7b004SRick Macklem if (error == EBADRPC || error == NFSERR_BADXDR) { 9529ec7b004SRick Macklem nd->nd_repstat = NFSERR_BADXDR; 9539ec7b004SRick Macklem } else { 9549ec7b004SRick Macklem nd->nd_repstat = error; 9559ec7b004SRick Macklem printf("nfsv4 comperr0=%d\n", error); 9569ec7b004SRick Macklem } 9579ec7b004SRick Macklem error = 0; 9589ec7b004SRick Macklem } 9599ec7b004SRick Macklem retops++; 9609ec7b004SRick Macklem if (nd->nd_repstat) { 9619ec7b004SRick Macklem *repp = nfsd_errmap(nd); 9629ec7b004SRick Macklem break; 9639ec7b004SRick Macklem } else { 9649ec7b004SRick Macklem *repp = 0; /* NFS4_OK */ 9659ec7b004SRick Macklem } 9669ec7b004SRick Macklem } 9679ec7b004SRick Macklem nfsmout: 9689ec7b004SRick Macklem if (error) { 9699ec7b004SRick Macklem if (error == EBADRPC || error == NFSERR_BADXDR) 9709ec7b004SRick Macklem nd->nd_repstat = NFSERR_BADXDR; 9719ec7b004SRick Macklem else 9729ec7b004SRick Macklem printf("nfsv4 comperr1=%d\n", error); 9739ec7b004SRick Macklem } 9749ec7b004SRick Macklem if (taglen == -1) { 9759ec7b004SRick Macklem NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 9769ec7b004SRick Macklem *tl++ = 0; 9779ec7b004SRick Macklem *tl = 0; 9789ec7b004SRick Macklem } else { 9799ec7b004SRick Macklem *retopsp = txdr_unsigned(retops); 9809ec7b004SRick Macklem } 9819ec7b004SRick Macklem if (mp && vpnes.nes_vfslocked) 9829ec7b004SRick Macklem nfsvno_unlockvfs(mp); 9839ec7b004SRick Macklem if (vp) 9849ec7b004SRick Macklem vrele(vp); 9859ec7b004SRick Macklem if (savevp) 9869ec7b004SRick Macklem vrele(savevp); 9879ec7b004SRick Macklem NFSLOCKV4ROOTMUTEX(); 9889ec7b004SRick Macklem nfsv4_relref(&nfsv4rootfs_lock); 9899ec7b004SRick Macklem NFSUNLOCKV4ROOTMUTEX(); 9909ec7b004SRick Macklem } 991