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