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 { 3579ec7b004SRick Macklem int error = 0; 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 } 3839ec7b004SRick Macklem nes.nes_vfslocked = 0; 3849ec7b004SRick Macklem if (nd->nd_flag & ND_PUBLOOKUP) 3859ec7b004SRick Macklem nfsd_fhtovp(nd, &nfs_pubfh, &vp, &nes, 3869ec7b004SRick Macklem &mp, nfs_writerpc[nd->nd_procnum], p); 3879ec7b004SRick Macklem else 3889ec7b004SRick Macklem nfsd_fhtovp(nd, &fh, &vp, &nes, 3899ec7b004SRick Macklem &mp, nfs_writerpc[nd->nd_procnum], p); 3909ec7b004SRick Macklem if (nd->nd_repstat == NFSERR_PROGNOTV4) 3919ec7b004SRick Macklem return; 3929ec7b004SRick Macklem } 3939ec7b004SRick Macklem } 3949ec7b004SRick Macklem 3959ec7b004SRick Macklem /* 3969ec7b004SRick Macklem * For V2 and 3, set the ND_SAVEREPLY flag for the recent request 3979ec7b004SRick Macklem * cache, as required. 3989ec7b004SRick Macklem * For V4, nfsrvd_compound() does this. 3999ec7b004SRick Macklem */ 4009ec7b004SRick Macklem if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum]) 4019ec7b004SRick Macklem nd->nd_flag |= ND_SAVEREPLY; 4029ec7b004SRick Macklem 4039ec7b004SRick Macklem nfsrvd_rephead(nd); 4049ec7b004SRick Macklem /* 4059ec7b004SRick Macklem * If nd_repstat is non-zero, just fill in the reply status 4069ec7b004SRick Macklem * to complete the RPC reply for V2. Otherwise, you must do 4079ec7b004SRick Macklem * the RPC. 4089ec7b004SRick Macklem */ 4099ec7b004SRick Macklem if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) { 4109ec7b004SRick Macklem *nd->nd_errp = nfsd_errmap(nd); 4119ec7b004SRick Macklem NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]); 4129ec7b004SRick Macklem if (mp != NULL) { 4139ec7b004SRick Macklem if (nfs_writerpc[nd->nd_procnum]) 4149ec7b004SRick Macklem NFS_ENDWRITE(mp); 4159ec7b004SRick Macklem if (nes.nes_vfslocked) 4169ec7b004SRick Macklem nfsvno_unlockvfs(mp); 4179ec7b004SRick Macklem } 4189ec7b004SRick Macklem return; 4199ec7b004SRick Macklem } 4209ec7b004SRick Macklem 4219ec7b004SRick Macklem /* 4229ec7b004SRick Macklem * Now the procedure can be performed. For V4, nfsrvd_compound() 4239ec7b004SRick Macklem * works through the sub-rpcs, otherwise just call the procedure. 4249ec7b004SRick Macklem * The procedures are in three groups with different arguments. 4259ec7b004SRick Macklem * The group is indicated by the value in nfs_retfh[]. 4269ec7b004SRick Macklem */ 4279ec7b004SRick Macklem if (nd->nd_flag & ND_NFSV4) { 4289ec7b004SRick Macklem nfsrvd_compound(nd, isdgram, p); 4299ec7b004SRick Macklem } else { 4309ec7b004SRick Macklem if (nfs_retfh[nd->nd_procnum] == 1) { 4319ec7b004SRick Macklem if (vp) 4329ec7b004SRick Macklem NFSVOPUNLOCK(vp, 0, p); 4339ec7b004SRick Macklem error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram, 4349ec7b004SRick Macklem vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes); 4359ec7b004SRick Macklem } else if (nfs_retfh[nd->nd_procnum] == 2) { 4369ec7b004SRick Macklem error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram, 4379ec7b004SRick Macklem vp, NULL, p, &nes, NULL); 4389ec7b004SRick Macklem } else { 4399ec7b004SRick Macklem error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram, 4409ec7b004SRick Macklem vp, p, &nes); 4419ec7b004SRick Macklem } 4429ec7b004SRick Macklem if (mp) { 4439ec7b004SRick Macklem if (nfs_writerpc[nd->nd_procnum]) 4449ec7b004SRick Macklem NFS_ENDWRITE(mp); 4459ec7b004SRick Macklem if (nes.nes_vfslocked) 4469ec7b004SRick Macklem nfsvno_unlockvfs(mp); 4479ec7b004SRick Macklem } 4489ec7b004SRick Macklem NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]); 4499ec7b004SRick Macklem } 4509ec7b004SRick Macklem if (error) { 4519ec7b004SRick Macklem if (error != EBADRPC) 4529ec7b004SRick Macklem printf("nfs dorpc err2=%d\n", error); 4539ec7b004SRick Macklem nd->nd_repstat = NFSERR_GARBAGE; 4549ec7b004SRick Macklem } 4559ec7b004SRick Macklem *nd->nd_errp = nfsd_errmap(nd); 4569ec7b004SRick Macklem 4579ec7b004SRick Macklem /* 4589ec7b004SRick Macklem * Don't cache certain reply status values. 4599ec7b004SRick Macklem */ 4609ec7b004SRick Macklem if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) && 4619ec7b004SRick Macklem (nd->nd_repstat == NFSERR_GARBAGE || 4629ec7b004SRick Macklem nd->nd_repstat == NFSERR_BADXDR || 4639ec7b004SRick Macklem nd->nd_repstat == NFSERR_MOVED || 4649ec7b004SRick Macklem nd->nd_repstat == NFSERR_DELAY || 4659ec7b004SRick Macklem nd->nd_repstat == NFSERR_BADSEQID || 4669ec7b004SRick Macklem nd->nd_repstat == NFSERR_RESOURCE || 4679ec7b004SRick Macklem nd->nd_repstat == NFSERR_SERVERFAULT || 4689ec7b004SRick Macklem nd->nd_repstat == NFSERR_STALECLIENTID || 4699ec7b004SRick Macklem nd->nd_repstat == NFSERR_STALESTATEID || 4709ec7b004SRick Macklem nd->nd_repstat == NFSERR_OLDSTATEID || 4719ec7b004SRick Macklem nd->nd_repstat == NFSERR_BADSTATEID || 4729ec7b004SRick Macklem nd->nd_repstat == NFSERR_GRACE || 4739ec7b004SRick Macklem nd->nd_repstat == NFSERR_NOGRACE)) 4749ec7b004SRick Macklem nd->nd_flag &= ~ND_SAVEREPLY; 4759ec7b004SRick Macklem } 4769ec7b004SRick Macklem 4779ec7b004SRick Macklem /* 4789ec7b004SRick Macklem * Breaks down a compound RPC request and calls the server routines for 4799ec7b004SRick Macklem * the subprocedures. 4809ec7b004SRick Macklem * Some suboperations are performed directly here to simplify file handle<--> 4819ec7b004SRick Macklem * vnode pointer handling. 4829ec7b004SRick Macklem */ 4839ec7b004SRick Macklem static void 4849ec7b004SRick Macklem nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, 4859ec7b004SRick Macklem NFSPROC_T *p) 4869ec7b004SRick Macklem { 4879ec7b004SRick Macklem int i, op; 4889ec7b004SRick Macklem u_int32_t *tl; 4899ec7b004SRick Macklem struct nfsclient *clp, *nclp; 4909ec7b004SRick Macklem int numops, taglen = -1, error = 0, igotlock; 4919ec7b004SRick Macklem u_int32_t minorvers, retops = 0, *retopsp = NULL, *repp; 4929ec7b004SRick Macklem u_char tag[NFSV4_SMALLSTR + 1], *tagstr; 4939ec7b004SRick Macklem vnode_t vp, nvp, savevp; 4949ec7b004SRick Macklem struct nfsrvfh fh; 4959ec7b004SRick Macklem mount_t mp, savemp; 4969ec7b004SRick Macklem struct ucred *credanon; 4979ec7b004SRick Macklem struct nfsexstuff nes, vpnes, savevpnes; 4989ec7b004SRick Macklem static u_int64_t compref = 0; 4999ec7b004SRick Macklem 5009ec7b004SRick Macklem NFSVNO_EXINIT(&vpnes); 5019ec7b004SRick Macklem NFSVNO_EXINIT(&savevpnes); 5029ec7b004SRick Macklem /* 5039ec7b004SRick Macklem * Put the seq# of the current compound RPC in nfsrv_descript. 5049ec7b004SRick Macklem * (This is used by nfsrv_checkgetattr(), to see if the write 5059ec7b004SRick Macklem * delegation was created by the same compound RPC as the one 5069ec7b004SRick Macklem * with that Getattr in it.) 5079ec7b004SRick Macklem * Don't worry about the 64bit number wrapping around. It ain't 5089ec7b004SRick Macklem * gonna happen before this server gets shut down/rebooted. 5099ec7b004SRick Macklem */ 5109ec7b004SRick Macklem nd->nd_compref = compref++; 5119ec7b004SRick Macklem 5129ec7b004SRick Macklem /* 5139ec7b004SRick Macklem * Check for and optionally get a lock on the root. This lock means that 5149ec7b004SRick Macklem * no nfsd will be fiddling with the V4 file system and state stuff. It 5159ec7b004SRick Macklem * is required when the V4 root is being changed, the stable storage 5169ec7b004SRick Macklem * restart file is being updated, or callbacks are being done. 5179ec7b004SRick Macklem * When any of the nfsd are processing an NFSv4 compound RPC, they must 5189ec7b004SRick Macklem * either hold a reference count (nfs_usecnt) or the lock. When 5199ec7b004SRick Macklem * nfsrv_unlock() is called to release the lock, it can optionally 5209ec7b004SRick Macklem * also get a reference count, which saves the need for a call to 5219ec7b004SRick Macklem * nfsrv_getref() after nfsrv_unlock(). 5229ec7b004SRick Macklem */ 5239ec7b004SRick Macklem /* 5249ec7b004SRick Macklem * First, check to see if we need to wait for an update lock. 5259ec7b004SRick Macklem */ 5269ec7b004SRick Macklem igotlock = 0; 5279ec7b004SRick Macklem NFSLOCKV4ROOTMUTEX(); 5289ec7b004SRick Macklem if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK) 5299ec7b004SRick Macklem igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 5309ec7b004SRick Macklem NFSV4ROOTLOCKMUTEXPTR); 5319ec7b004SRick Macklem else 5329ec7b004SRick Macklem igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL, 5339ec7b004SRick Macklem NFSV4ROOTLOCKMUTEXPTR); 5349ec7b004SRick Macklem NFSUNLOCKV4ROOTMUTEX(); 5359ec7b004SRick Macklem if (igotlock) { 5369ec7b004SRick Macklem NFSLOCKSTATE(); /* to avoid a race with */ 5379ec7b004SRick Macklem NFSUNLOCKSTATE(); /* nfsrv_servertimer() */ 5389ec7b004SRick Macklem /* 5399ec7b004SRick Macklem * If I got the lock, I can update the stable storage file. 5409ec7b004SRick Macklem * Done when the grace period is over or a client has long 5419ec7b004SRick Macklem * since expired. 5429ec7b004SRick Macklem */ 5439ec7b004SRick Macklem nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK; 5449ec7b004SRick Macklem if ((nfsrv_stablefirst.nsf_flags & 5459ec7b004SRick Macklem (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER) 5469ec7b004SRick Macklem nfsrv_updatestable(p); 5479ec7b004SRick Macklem 5489ec7b004SRick Macklem /* 5499ec7b004SRick Macklem * If at least one client has long since expired, search 5509ec7b004SRick Macklem * the client list for them, write a REVOKE record on the 5519ec7b004SRick Macklem * stable storage file and then remove them from the client 5529ec7b004SRick Macklem * list. 5539ec7b004SRick Macklem */ 5549ec7b004SRick Macklem if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) { 5559ec7b004SRick Macklem nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT; 5569ec7b004SRick Macklem for (i = 0; i < NFSCLIENTHASHSIZE; i++) { 5579ec7b004SRick Macklem LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, 5589ec7b004SRick Macklem nclp) { 5599ec7b004SRick Macklem if (clp->lc_flags & LCL_EXPIREIT) { 5609ec7b004SRick Macklem if (!LIST_EMPTY(&clp->lc_open) || 5619ec7b004SRick Macklem !LIST_EMPTY(&clp->lc_deleg)) 5629ec7b004SRick Macklem nfsrv_writestable(clp->lc_id, 5639ec7b004SRick Macklem clp->lc_idlen, NFSNST_REVOKE, p); 5649ec7b004SRick Macklem nfsrv_cleanclient(clp, p); 5659ec7b004SRick Macklem nfsrv_freedeleglist(&clp->lc_deleg); 5669ec7b004SRick Macklem nfsrv_freedeleglist(&clp->lc_olddeleg); 5679ec7b004SRick Macklem LIST_REMOVE(clp, lc_hash); 5689ec7b004SRick Macklem nfsrv_zapclient(clp, p); 5699ec7b004SRick Macklem } 5709ec7b004SRick Macklem } 5719ec7b004SRick Macklem } 5729ec7b004SRick Macklem } 5739ec7b004SRick Macklem NFSLOCKV4ROOTMUTEX(); 5749ec7b004SRick Macklem nfsv4_unlock(&nfsv4rootfs_lock, 1); 5759ec7b004SRick Macklem NFSUNLOCKV4ROOTMUTEX(); 5769ec7b004SRick Macklem } else { 5779ec7b004SRick Macklem /* 5789ec7b004SRick Macklem * If we didn't get the lock, we need to get a refcnt, 5799ec7b004SRick Macklem * which also checks for and waits for the lock. 5809ec7b004SRick Macklem */ 5819ec7b004SRick Macklem NFSLOCKV4ROOTMUTEX(); 5829ec7b004SRick Macklem nfsv4_getref(&nfsv4rootfs_lock, NULL, 5839ec7b004SRick Macklem NFSV4ROOTLOCKMUTEXPTR); 5849ec7b004SRick Macklem NFSUNLOCKV4ROOTMUTEX(); 5859ec7b004SRick Macklem } 5869ec7b004SRick Macklem 5879ec7b004SRick Macklem /* 5889ec7b004SRick Macklem * If flagged, search for open owners that haven't had any opens 5899ec7b004SRick Macklem * for a long time. 5909ec7b004SRick Macklem */ 5919ec7b004SRick Macklem if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) { 5929ec7b004SRick Macklem nfsrv_throwawayopens(p); 5939ec7b004SRick Macklem } 5949ec7b004SRick Macklem 5959ec7b004SRick Macklem savevp = vp = NULL; 5969ec7b004SRick Macklem savevpnes.nes_vfslocked = vpnes.nes_vfslocked = 0; 5979ec7b004SRick Macklem savemp = mp = NULL; 5989ec7b004SRick Macklem NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 5999ec7b004SRick Macklem taglen = fxdr_unsigned(int, *tl); 6009ec7b004SRick Macklem if (taglen < 0) { 6019ec7b004SRick Macklem error = EBADRPC; 6029ec7b004SRick Macklem goto nfsmout; 6039ec7b004SRick Macklem } 6049ec7b004SRick Macklem if (taglen <= NFSV4_SMALLSTR) 6059ec7b004SRick Macklem tagstr = tag; 6069ec7b004SRick Macklem else 6079ec7b004SRick Macklem tagstr = malloc(taglen + 1, M_TEMP, M_WAITOK); 6089ec7b004SRick Macklem error = nfsrv_mtostr(nd, tagstr, taglen); 6099ec7b004SRick Macklem if (error) { 6109ec7b004SRick Macklem if (taglen > NFSV4_SMALLSTR) 6119ec7b004SRick Macklem free(tagstr, M_TEMP); 6129ec7b004SRick Macklem taglen = -1; 6139ec7b004SRick Macklem goto nfsmout; 6149ec7b004SRick Macklem } 6159ec7b004SRick Macklem (void) nfsm_strtom(nd, tag, taglen); 6169ec7b004SRick Macklem if (taglen > NFSV4_SMALLSTR) { 6179ec7b004SRick Macklem free(tagstr, M_TEMP); 6189ec7b004SRick Macklem } 6199ec7b004SRick Macklem NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED); 6209ec7b004SRick Macklem NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 6219ec7b004SRick Macklem minorvers = fxdr_unsigned(u_int32_t, *tl++); 6229ec7b004SRick Macklem if (minorvers != NFSV4_MINORVERSION) 6239ec7b004SRick Macklem nd->nd_repstat = NFSERR_MINORVERMISMATCH; 6249ec7b004SRick Macklem if (nd->nd_repstat) 6259ec7b004SRick Macklem numops = 0; 6269ec7b004SRick Macklem else 6279ec7b004SRick Macklem numops = fxdr_unsigned(int, *tl); 6289ec7b004SRick Macklem /* 6299ec7b004SRick Macklem * Loop around doing the sub ops. 6309ec7b004SRick Macklem * vp - is an unlocked vnode pointer for the CFH 6319ec7b004SRick Macklem * savevp - is an unlocked vnode pointer for the SAVEDFH 6329ec7b004SRick Macklem * (at some future date, it might turn out to be more appropriate 6339ec7b004SRick Macklem * to keep the file handles instead of vnode pointers?) 6349ec7b004SRick Macklem * savevpnes and vpnes - are the export flags for the above. 6359ec7b004SRick Macklem */ 6369ec7b004SRick Macklem for (i = 0; i < numops; i++) { 6379ec7b004SRick Macklem NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 6389ec7b004SRick Macklem NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED); 6399183a2a3SRick Macklem *repp = *tl; 6409ec7b004SRick Macklem op = fxdr_unsigned(int, *tl); 6419ec7b004SRick Macklem if (op < NFSV4OP_ACCESS || op >= NFSV4OP_NOPS) { 6429ec7b004SRick Macklem nd->nd_repstat = NFSERR_OPILLEGAL; 6439183a2a3SRick Macklem *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL); 6449ec7b004SRick Macklem *repp = nfsd_errmap(nd); 6459ec7b004SRick Macklem retops++; 6469ec7b004SRick Macklem break; 6479183a2a3SRick Macklem } else { 6489183a2a3SRick Macklem repp++; 6499ec7b004SRick Macklem } 6509ec7b004SRick Macklem 6519ec7b004SRick Macklem /* 6529ec7b004SRick Macklem * Check for a referral on the current FH and, if so, return 6539ec7b004SRick Macklem * NFSERR_MOVED for all ops that allow it, except Getattr. 6549ec7b004SRick Macklem */ 6559ec7b004SRick Macklem if (vp != NULL && op != NFSV4OP_GETATTR && 6569ec7b004SRick Macklem nfsv4root_getreferral(vp, NULL, 0) != NULL && 6579ec7b004SRick Macklem nfsrv_errmoved(op)) { 6589ec7b004SRick Macklem nd->nd_repstat = NFSERR_MOVED; 6599ec7b004SRick Macklem *repp = nfsd_errmap(nd); 6609ec7b004SRick Macklem retops++; 6619ec7b004SRick Macklem break; 6629ec7b004SRick Macklem } 6639ec7b004SRick Macklem 6649ec7b004SRick Macklem nd->nd_procnum = op; 6659ec7b004SRick Macklem /* 6669ec7b004SRick Macklem * If over flood level, reply NFSERR_RESOURCE, if at the first 6679ec7b004SRick Macklem * Op. (Since a client recovery from NFSERR_RESOURCE can get 6689ec7b004SRick Macklem * really nasty for certain Op sequences, I'll play it safe 6699ec7b004SRick Macklem * and only return the error at the beginning.) The cache 6709ec7b004SRick Macklem * will still function over flood level, but uses lots of 6719ec7b004SRick Macklem * mbufs.) 6729ec7b004SRick Macklem * If nfsrv_mallocmget_limit() returns True, the system is near 6739ec7b004SRick Macklem * to its limit for memory that malloc()/mget() can allocate. 6749ec7b004SRick Macklem */ 6759ec7b004SRick Macklem if (i == 0 && nd->nd_rp->rc_refcnt == 0 && 6769ec7b004SRick Macklem (nfsrv_mallocmget_limit() || 6779ec7b004SRick Macklem nfsrc_tcpsavedreplies > nfsrc_floodlevel)) { 6789ec7b004SRick Macklem if (nfsrc_tcpsavedreplies > nfsrc_floodlevel) { 6799ec7b004SRick Macklem printf("nfsd server cache flooded, try to"); 6809ec7b004SRick Macklem printf(" increase nfsrc_floodlevel\n"); 6819ec7b004SRick Macklem } 6829ec7b004SRick Macklem nd->nd_repstat = NFSERR_RESOURCE; 6839ec7b004SRick Macklem *repp = nfsd_errmap(nd); 6849ec7b004SRick Macklem if (op == NFSV4OP_SETATTR) { 6859ec7b004SRick Macklem /* 6869ec7b004SRick Macklem * Setattr replies require a bitmap. 6879ec7b004SRick Macklem * even for errors like these. 6889ec7b004SRick Macklem */ 6899ec7b004SRick Macklem NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 6909ec7b004SRick Macklem *tl = 0; 6919ec7b004SRick Macklem } 6929ec7b004SRick Macklem retops++; 6939ec7b004SRick Macklem break; 6949ec7b004SRick Macklem } 6959ec7b004SRick Macklem if (nfsv4_opflag[op].savereply) 6969ec7b004SRick Macklem nd->nd_flag |= ND_SAVEREPLY; 6979ec7b004SRick Macklem NFSINCRGLOBAL(newnfsstats.srvrpccnt[nd->nd_procnum]); 6989ec7b004SRick Macklem switch (op) { 6999ec7b004SRick Macklem case NFSV4OP_PUTFH: 7009ec7b004SRick Macklem error = nfsrv_mtofh(nd, &fh); 7019ec7b004SRick Macklem if (error) 7029ec7b004SRick Macklem goto nfsmout; 7039ec7b004SRick Macklem if (!nd->nd_repstat) { 7049ec7b004SRick Macklem nes.nes_vfslocked = vpnes.nes_vfslocked; 7059ec7b004SRick Macklem nfsd_fhtovp(nd, &fh, &nvp, &nes, &mp, 7069ec7b004SRick Macklem 0, p); 7079ec7b004SRick Macklem } 7089ec7b004SRick Macklem /* For now, allow this for non-export FHs */ 7099ec7b004SRick Macklem if (!nd->nd_repstat) { 7109ec7b004SRick Macklem if (vp) 7119ec7b004SRick Macklem vrele(vp); 7129ec7b004SRick Macklem vp = nvp; 7139ec7b004SRick Macklem NFSVOPUNLOCK(vp, 0, p); 7149ec7b004SRick Macklem vpnes = nes; 7159ec7b004SRick Macklem } 7169ec7b004SRick Macklem break; 7179ec7b004SRick Macklem case NFSV4OP_PUTPUBFH: 7189ec7b004SRick Macklem if (nfs_pubfhset) { 7199ec7b004SRick Macklem nes.nes_vfslocked = vpnes.nes_vfslocked; 7209ec7b004SRick Macklem nfsd_fhtovp(nd, &nfs_pubfh, &nvp, 7219ec7b004SRick Macklem &nes, &mp, 0, p); 7229ec7b004SRick Macklem } else { 7239ec7b004SRick Macklem nd->nd_repstat = NFSERR_NOFILEHANDLE; 7249ec7b004SRick Macklem } 7259ec7b004SRick Macklem if (!nd->nd_repstat) { 7269ec7b004SRick Macklem if (vp) 7279ec7b004SRick Macklem vrele(vp); 7289ec7b004SRick Macklem vp = nvp; 7299ec7b004SRick Macklem NFSVOPUNLOCK(vp, 0, p); 7309ec7b004SRick Macklem vpnes = nes; 7319ec7b004SRick Macklem } 7329ec7b004SRick Macklem break; 7339ec7b004SRick Macklem case NFSV4OP_PUTROOTFH: 7349ec7b004SRick Macklem if (nfs_rootfhset) { 7359ec7b004SRick Macklem nes.nes_vfslocked = vpnes.nes_vfslocked; 7369ec7b004SRick Macklem nfsd_fhtovp(nd, &nfs_rootfh, &nvp, 7379ec7b004SRick Macklem &nes, &mp, 0, p); 7389ec7b004SRick Macklem if (!nd->nd_repstat) { 7399ec7b004SRick Macklem if (vp) 7409ec7b004SRick Macklem vrele(vp); 7419ec7b004SRick Macklem vp = nvp; 7429ec7b004SRick Macklem NFSVOPUNLOCK(vp, 0, p); 7439ec7b004SRick Macklem vpnes = nes; 7449ec7b004SRick Macklem } 7459ec7b004SRick Macklem } else if (nfsv4root_vp && nfsv4root_set) { 7469ec7b004SRick Macklem if (vp) { 7479ec7b004SRick Macklem if (vpnes.nes_vfslocked) 7489ec7b004SRick Macklem nfsvno_unlockvfs(mp); 7499ec7b004SRick Macklem vrele(vp); 7509ec7b004SRick Macklem } 7519ec7b004SRick Macklem vp = nfsv4root_vp; 7529ec7b004SRick Macklem VREF(vp); 7539ec7b004SRick Macklem NFSVNO_SETEXRDONLY(&vpnes); 7549ec7b004SRick Macklem vpnes.nes_vfslocked = 0; 7559ec7b004SRick Macklem mp = vnode_mount(vp); 7569ec7b004SRick Macklem } else { 7579ec7b004SRick Macklem nd->nd_repstat = NFSERR_NOFILEHANDLE; 7589ec7b004SRick Macklem } 7599ec7b004SRick Macklem break; 7609ec7b004SRick Macklem case NFSV4OP_SAVEFH: 7619ec7b004SRick Macklem if (vp && NFSVNO_EXPORTED(&vpnes)) { 7629ec7b004SRick Macklem nd->nd_repstat = 0; 7639ec7b004SRick Macklem /* If vp == savevp, a no-op */ 7649ec7b004SRick Macklem if (vp != savevp) { 7659ec7b004SRick Macklem if (savevp) 7669ec7b004SRick Macklem vrele(savevp); 7679ec7b004SRick Macklem VREF(vp); 7689ec7b004SRick Macklem savevp = vp; 7699ec7b004SRick Macklem savevpnes = vpnes; 7709ec7b004SRick Macklem savemp = mp; 7719ec7b004SRick Macklem } 7729ec7b004SRick Macklem } else { 7739ec7b004SRick Macklem nd->nd_repstat = NFSERR_NOFILEHANDLE; 7749ec7b004SRick Macklem } 7759ec7b004SRick Macklem break; 7769ec7b004SRick Macklem case NFSV4OP_RESTOREFH: 7779ec7b004SRick Macklem if (savevp) { 7789ec7b004SRick Macklem nd->nd_repstat = 0; 7799ec7b004SRick Macklem /* If vp == savevp, a no-op */ 7809ec7b004SRick Macklem if (vp != savevp) { 7819ec7b004SRick Macklem VREF(savevp); 7829ec7b004SRick Macklem if (mp == NULL || savemp == NULL) 7839ec7b004SRick Macklem panic("nfscmpmp"); 7849ec7b004SRick Macklem if (!savevpnes.nes_vfslocked && 7859ec7b004SRick Macklem vpnes.nes_vfslocked) { 7869ec7b004SRick Macklem if (mp == savemp) 7879ec7b004SRick Macklem panic("nfscmp2"); 7889ec7b004SRick Macklem nfsvno_unlockvfs(mp); 7899ec7b004SRick Macklem } else if (savevpnes.nes_vfslocked && 7909ec7b004SRick Macklem !vpnes.nes_vfslocked) { 7919ec7b004SRick Macklem if (mp == savemp) 7929ec7b004SRick Macklem panic("nfscmp3"); 7939ec7b004SRick Macklem savevpnes.nes_vfslocked = nfsvno_lockvfs(savemp); 7949ec7b004SRick Macklem } 7959ec7b004SRick Macklem vrele(vp); 7969ec7b004SRick Macklem vp = savevp; 7979ec7b004SRick Macklem vpnes = savevpnes; 7989ec7b004SRick Macklem mp = savemp; 7999ec7b004SRick Macklem } 8009ec7b004SRick Macklem } else { 8019ec7b004SRick Macklem nd->nd_repstat = NFSERR_RESTOREFH; 8029ec7b004SRick Macklem } 8039ec7b004SRick Macklem break; 8049ec7b004SRick Macklem default: 8059ec7b004SRick Macklem /* 8069ec7b004SRick Macklem * Allow a Lookup, Getattr, GetFH, Secinfo on an 8079ec7b004SRick Macklem * non-exported directory if 8089ec7b004SRick Macklem * nfs_rootfhset. Do I need to allow any other Ops? 8099ec7b004SRick Macklem * (You can only have a non-exported vpnes if 8109ec7b004SRick Macklem * nfs_rootfhset is true. See nfsd_fhtovp()) 8119ec7b004SRick Macklem * Allow AUTH_SYS to be used for file systems 8129ec7b004SRick Macklem * exported GSS only for certain Ops, to allow 8139ec7b004SRick Macklem * clients to do mounts more easily. 8149ec7b004SRick Macklem */ 8159ec7b004SRick Macklem if (nfsv4_opflag[op].needscfh && vp) { 8169ec7b004SRick Macklem if (!NFSVNO_EXPORTED(&vpnes) && 8179ec7b004SRick Macklem op != NFSV4OP_LOOKUP && 8189ec7b004SRick Macklem op != NFSV4OP_GETATTR && 8199ec7b004SRick Macklem op != NFSV4OP_GETFH && 8209ec7b004SRick Macklem op != NFSV4OP_SECINFO) 8219ec7b004SRick Macklem nd->nd_repstat = NFSERR_NOFILEHANDLE; 82298ad4453SRick Macklem else if (nfsvno_testexp(nd, &vpnes) && 8239ec7b004SRick Macklem op != NFSV4OP_LOOKUP && 8249ec7b004SRick Macklem op != NFSV4OP_GETFH && 8259ec7b004SRick Macklem op != NFSV4OP_GETATTR && 8269ec7b004SRick Macklem op != NFSV4OP_SECINFO) 8279ec7b004SRick Macklem nd->nd_repstat = NFSERR_WRONGSEC; 8289ec7b004SRick Macklem if (nd->nd_repstat) { 8299ec7b004SRick Macklem if (op == NFSV4OP_SETATTR) { 8309ec7b004SRick Macklem /* 8319ec7b004SRick Macklem * Setattr reply requires a bitmap 8329ec7b004SRick Macklem * even for errors like these. 8339ec7b004SRick Macklem */ 8349ec7b004SRick Macklem NFSM_BUILD(tl, u_int32_t *, 8359ec7b004SRick Macklem NFSX_UNSIGNED); 8369ec7b004SRick Macklem *tl = 0; 8379ec7b004SRick Macklem } 8389ec7b004SRick Macklem break; 8399ec7b004SRick Macklem } 8409ec7b004SRick Macklem } 8419ec7b004SRick Macklem if (nfsv4_opflag[op].retfh == 1) { 8429ec7b004SRick Macklem if (!vp) { 8439ec7b004SRick Macklem nd->nd_repstat = NFSERR_NOFILEHANDLE; 8449ec7b004SRick Macklem break; 8459ec7b004SRick Macklem } 8469ec7b004SRick Macklem VREF(vp); 8479ec7b004SRick Macklem if (nfsv4_opflag[op].modifyfs) 8489ec7b004SRick Macklem NFS_STARTWRITE(NULL, &mp); 8499ec7b004SRick Macklem error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp, 8509ec7b004SRick Macklem &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes); 8519ec7b004SRick Macklem if (!error && !nd->nd_repstat) { 8529ec7b004SRick Macklem if (vfs_statfs(mp)->f_fsid.val[0] != 8539ec7b004SRick Macklem vfs_statfs(vnode_mount(nvp))->f_fsid.val[0] || 8549ec7b004SRick Macklem vfs_statfs(mp)->f_fsid.val[1] != 8559ec7b004SRick Macklem vfs_statfs(vnode_mount(nvp))->f_fsid.val[1]) { 8569ec7b004SRick Macklem if (vfs_statfs(vnode_mount(nvp))->f_fsid.val[0] == 8579ec7b004SRick Macklem NFSV4ROOT_FSID0 && 8589ec7b004SRick Macklem vfs_statfs(vnode_mount(nvp))->f_fsid.val[1] == 8599ec7b004SRick Macklem NFSV4ROOT_FSID1) { 8609ec7b004SRick Macklem if (vpnes.nes_vfslocked) { 8619ec7b004SRick Macklem nfsvno_unlockvfs(mp); 8629ec7b004SRick Macklem vpnes.nes_vfslocked = 0; 8639ec7b004SRick Macklem } 8649ec7b004SRick Macklem NFSVNO_SETEXRDONLY(&vpnes); 8659ec7b004SRick Macklem mp = vnode_mount(nvp); 8669ec7b004SRick Macklem } else { 8679ec7b004SRick Macklem nd->nd_repstat = nfsvno_checkexp(vnode_mount(nvp), 8689ec7b004SRick Macklem nd->nd_nam, &nes, &credanon); 8699ec7b004SRick Macklem if (!nd->nd_repstat) 8709ec7b004SRick Macklem nd->nd_repstat = nfsd_excred(nd, 8719ec7b004SRick Macklem &nes, credanon); 8725679fe19SAlexander Kabaev if (credanon != NULL) 8735679fe19SAlexander Kabaev crfree(credanon); 8749ec7b004SRick Macklem if (!nd->nd_repstat) { 8759ec7b004SRick Macklem if (vpnes.nes_vfslocked) 8769ec7b004SRick Macklem nfsvno_unlockvfs(mp); 8779ec7b004SRick Macklem mp = vnode_mount(nvp); 8789ec7b004SRick Macklem vpnes = nes; 8799ec7b004SRick Macklem vpnes.nes_vfslocked = 8809ec7b004SRick Macklem nfsvno_lockvfs(mp); 8819ec7b004SRick Macklem } 8829ec7b004SRick Macklem } 8839ec7b004SRick Macklem } 8849ec7b004SRick Macklem if (!nd->nd_repstat) { 8859ec7b004SRick Macklem vrele(vp); 8869ec7b004SRick Macklem vp = nvp; 8879ec7b004SRick Macklem } 8889ec7b004SRick Macklem } 8899ec7b004SRick Macklem if (nfsv4_opflag[op].modifyfs) 8909ec7b004SRick Macklem NFS_ENDWRITE(mp); 8919ec7b004SRick Macklem } else if (nfsv4_opflag[op].retfh == 2) { 8929ec7b004SRick Macklem if (vp == NULL || savevp == NULL) { 8939ec7b004SRick Macklem nd->nd_repstat = NFSERR_NOFILEHANDLE; 8949ec7b004SRick Macklem break; 8959ec7b004SRick Macklem } else if (mp != savemp) { 8969ec7b004SRick Macklem nd->nd_repstat = NFSERR_XDEV; 8979ec7b004SRick Macklem break; 8989ec7b004SRick Macklem } 8999ec7b004SRick Macklem VREF(vp); 9009ec7b004SRick Macklem VREF(savevp); 9019ec7b004SRick Macklem if (nfsv4_opflag[op].modifyfs) 9029ec7b004SRick Macklem NFS_STARTWRITE(NULL, &mp); 9039ec7b004SRick Macklem NFSVOPLOCK(savevp, LK_EXCLUSIVE | LK_RETRY, p); 9049ec7b004SRick Macklem error = (*(nfsrv4_ops2[op]))(nd, isdgram, savevp, 9059ec7b004SRick Macklem vp, p, &savevpnes, &vpnes); 9069ec7b004SRick Macklem if (nfsv4_opflag[op].modifyfs) 9079ec7b004SRick Macklem NFS_ENDWRITE(mp); 9089ec7b004SRick Macklem } else { 9099ec7b004SRick Macklem if (nfsv4_opflag[op].retfh != 0) 9109ec7b004SRick Macklem panic("nfsrvd_compound"); 9119ec7b004SRick Macklem if (nfsv4_opflag[op].needscfh) { 9129ec7b004SRick Macklem if (vp) { 9139ec7b004SRick Macklem VREF(vp); 9149ec7b004SRick Macklem if (nfsv4_opflag[op].modifyfs) 9159ec7b004SRick Macklem NFS_STARTWRITE(NULL, &mp); 9169ec7b004SRick Macklem NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY, p); 9179ec7b004SRick Macklem } else { 9189ec7b004SRick Macklem nd->nd_repstat = NFSERR_NOFILEHANDLE; 9199ec7b004SRick Macklem if (op == NFSV4OP_SETATTR) { 9209ec7b004SRick Macklem /* 9219ec7b004SRick Macklem * Setattr reply requires a bitmap 9229ec7b004SRick Macklem * even for errors like these. 9239ec7b004SRick Macklem */ 9249ec7b004SRick Macklem NFSM_BUILD(tl, u_int32_t *, 9259ec7b004SRick Macklem NFSX_UNSIGNED); 9269ec7b004SRick Macklem *tl = 0; 9279ec7b004SRick Macklem } 9289ec7b004SRick Macklem break; 9299ec7b004SRick Macklem } 9309ec7b004SRick Macklem error = (*(nfsrv4_ops0[op]))(nd, isdgram, vp, 9319ec7b004SRick Macklem p, &vpnes); 9329ec7b004SRick Macklem if (nfsv4_opflag[op].modifyfs) 9339ec7b004SRick Macklem NFS_ENDWRITE(mp); 9349ec7b004SRick Macklem } else { 9359ec7b004SRick Macklem error = (*(nfsrv4_ops0[op]))(nd, isdgram, 9369ec7b004SRick Macklem NULL, p, &vpnes); 9379ec7b004SRick Macklem } 9389ec7b004SRick Macklem } 9399ec7b004SRick Macklem }; 9409ec7b004SRick Macklem if (error) { 9419ec7b004SRick Macklem if (error == EBADRPC || error == NFSERR_BADXDR) { 9429ec7b004SRick Macklem nd->nd_repstat = NFSERR_BADXDR; 9439ec7b004SRick Macklem } else { 9449ec7b004SRick Macklem nd->nd_repstat = error; 9459ec7b004SRick Macklem printf("nfsv4 comperr0=%d\n", error); 9469ec7b004SRick Macklem } 9479ec7b004SRick Macklem error = 0; 9489ec7b004SRick Macklem } 9499ec7b004SRick Macklem retops++; 9509ec7b004SRick Macklem if (nd->nd_repstat) { 9519ec7b004SRick Macklem *repp = nfsd_errmap(nd); 9529ec7b004SRick Macklem break; 9539ec7b004SRick Macklem } else { 9549ec7b004SRick Macklem *repp = 0; /* NFS4_OK */ 9559ec7b004SRick Macklem } 9569ec7b004SRick Macklem } 9579ec7b004SRick Macklem nfsmout: 9589ec7b004SRick Macklem if (error) { 9599ec7b004SRick Macklem if (error == EBADRPC || error == NFSERR_BADXDR) 9609ec7b004SRick Macklem nd->nd_repstat = NFSERR_BADXDR; 9619ec7b004SRick Macklem else 9629ec7b004SRick Macklem printf("nfsv4 comperr1=%d\n", error); 9639ec7b004SRick Macklem } 9649ec7b004SRick Macklem if (taglen == -1) { 9659ec7b004SRick Macklem NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 9669ec7b004SRick Macklem *tl++ = 0; 9679ec7b004SRick Macklem *tl = 0; 9689ec7b004SRick Macklem } else { 9699ec7b004SRick Macklem *retopsp = txdr_unsigned(retops); 9709ec7b004SRick Macklem } 9719ec7b004SRick Macklem if (mp && vpnes.nes_vfslocked) 9729ec7b004SRick Macklem nfsvno_unlockvfs(mp); 9739ec7b004SRick Macklem if (vp) 9749ec7b004SRick Macklem vrele(vp); 9759ec7b004SRick Macklem if (savevp) 9769ec7b004SRick Macklem vrele(savevp); 9779ec7b004SRick Macklem NFSLOCKV4ROOTMUTEX(); 9789ec7b004SRick Macklem nfsv4_relref(&nfsv4rootfs_lock); 9799ec7b004SRick Macklem NFSUNLOCKV4ROOTMUTEX(); 9809ec7b004SRick Macklem } 981