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 return; 380 } 381 if (nd->nd_procnum == NFSPROC_READ || 382 nd->nd_procnum == NFSPROC_READDIR || 383 nd->nd_procnum == NFSPROC_READLINK || 384 nd->nd_procnum == NFSPROC_GETATTR || 385 nd->nd_procnum == NFSPROC_ACCESS) 386 lktype = LK_SHARED; 387 else 388 lktype = LK_EXCLUSIVE; 389 if (nd->nd_flag & ND_PUBLOOKUP) 390 nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes, 391 &mp, nfs_writerpc[nd->nd_procnum], p); 392 else 393 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes, 394 &mp, nfs_writerpc[nd->nd_procnum], p); 395 if (nd->nd_repstat == NFSERR_PROGNOTV4) 396 return; 397 } 398 } 399 400 /* 401 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request 402 * cache, as required. 403 * For V4, nfsrvd_compound() does this. 404 */ 405 if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum]) 406 nd->nd_flag |= ND_SAVEREPLY; 407 408 nfsrvd_rephead(nd); 409 /* 410 * If nd_repstat is non-zero, just fill in the reply status 411 * to complete the RPC reply for V2. Otherwise, you must do 412 * the RPC. 413 */ 414 if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) { 415 *nd->nd_errp = nfsd_errmap(nd); 416 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]); 417 if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0) 418 vn_finished_write(mp); 419 return; 420 } 421 422 /* 423 * Now the procedure can be performed. For V4, nfsrvd_compound() 424 * works through the sub-rpcs, otherwise just call the procedure. 425 * The procedures are in three groups with different arguments. 426 * The group is indicated by the value in nfs_retfh[]. 427 */ 428 if (nd->nd_flag & ND_NFSV4) { 429 nfsrvd_compound(nd, isdgram, p); 430 } else { 431 if (nfs_retfh[nd->nd_procnum] == 1) { 432 if (vp) 433 NFSVOPUNLOCK(vp, 0, p); 434 error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram, 435 vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes); 436 } else if (nfs_retfh[nd->nd_procnum] == 2) { 437 error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram, 438 vp, NULL, p, &nes, NULL); 439 } else { 440 error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram, 441 vp, p, &nes); 442 } 443 if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0) 444 vn_finished_write(mp); 445 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]); 446 } 447 if (error) { 448 if (error != EBADRPC) 449 printf("nfs dorpc err2=%d\n", error); 450 nd->nd_repstat = NFSERR_GARBAGE; 451 } 452 *nd->nd_errp = nfsd_errmap(nd); 453 454 /* 455 * Don't cache certain reply status values. 456 */ 457 if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) && 458 (nd->nd_repstat == NFSERR_GARBAGE || 459 nd->nd_repstat == NFSERR_BADXDR || 460 nd->nd_repstat == NFSERR_MOVED || 461 nd->nd_repstat == NFSERR_DELAY || 462 nd->nd_repstat == NFSERR_BADSEQID || 463 nd->nd_repstat == NFSERR_RESOURCE || 464 nd->nd_repstat == NFSERR_SERVERFAULT || 465 nd->nd_repstat == NFSERR_STALECLIENTID || 466 nd->nd_repstat == NFSERR_STALESTATEID || 467 nd->nd_repstat == NFSERR_OLDSTATEID || 468 nd->nd_repstat == NFSERR_BADSTATEID || 469 nd->nd_repstat == NFSERR_GRACE || 470 nd->nd_repstat == NFSERR_NOGRACE)) 471 nd->nd_flag &= ~ND_SAVEREPLY; 472 } 473 474 /* 475 * Breaks down a compound RPC request and calls the server routines for 476 * the subprocedures. 477 * Some suboperations are performed directly here to simplify file handle<--> 478 * vnode pointer handling. 479 */ 480 static void 481 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, 482 NFSPROC_T *p) 483 { 484 int i, op; 485 u_int32_t *tl; 486 struct nfsclient *clp, *nclp; 487 int numops, taglen = -1, error = 0, igotlock; 488 u_int32_t minorvers, retops = 0, *retopsp = NULL, *repp; 489 u_char tag[NFSV4_SMALLSTR + 1], *tagstr; 490 vnode_t vp, nvp, savevp; 491 struct nfsrvfh fh; 492 mount_t new_mp, temp_mp = NULL; 493 struct ucred *credanon; 494 struct nfsexstuff nes, vpnes, savevpnes; 495 fsid_t cur_fsid, save_fsid; 496 static u_int64_t compref = 0; 497 498 NFSVNO_EXINIT(&vpnes); 499 NFSVNO_EXINIT(&savevpnes); 500 /* 501 * Put the seq# of the current compound RPC in nfsrv_descript. 502 * (This is used by nfsrv_checkgetattr(), to see if the write 503 * delegation was created by the same compound RPC as the one 504 * with that Getattr in it.) 505 * Don't worry about the 64bit number wrapping around. It ain't 506 * gonna happen before this server gets shut down/rebooted. 507 */ 508 nd->nd_compref = compref++; 509 510 /* 511 * Check for and optionally get a lock on the root. This lock means that 512 * no nfsd will be fiddling with the V4 file system and state stuff. It 513 * is required when the V4 root is being changed, the stable storage 514 * restart file is being updated, or callbacks are being done. 515 * When any of the nfsd are processing an NFSv4 compound RPC, they must 516 * either hold a reference count (nfs_usecnt) or the lock. When 517 * nfsrv_unlock() is called to release the lock, it can optionally 518 * also get a reference count, which saves the need for a call to 519 * nfsrv_getref() after nfsrv_unlock(). 520 */ 521 /* 522 * First, check to see if we need to wait for an update lock. 523 */ 524 igotlock = 0; 525 NFSLOCKV4ROOTMUTEX(); 526 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK) 527 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 528 NFSV4ROOTLOCKMUTEXPTR, NULL); 529 else 530 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL, 531 NFSV4ROOTLOCKMUTEXPTR, NULL); 532 NFSUNLOCKV4ROOTMUTEX(); 533 if (igotlock) { 534 /* 535 * If I got the lock, I can update the stable storage file. 536 * Done when the grace period is over or a client has long 537 * since expired. 538 */ 539 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK; 540 if ((nfsrv_stablefirst.nsf_flags & 541 (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER) 542 nfsrv_updatestable(p); 543 544 /* 545 * If at least one client has long since expired, search 546 * the client list for them, write a REVOKE record on the 547 * stable storage file and then remove them from the client 548 * list. 549 */ 550 if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) { 551 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT; 552 for (i = 0; i < NFSCLIENTHASHSIZE; i++) { 553 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, 554 nclp) { 555 if (clp->lc_flags & LCL_EXPIREIT) { 556 if (!LIST_EMPTY(&clp->lc_open) || 557 !LIST_EMPTY(&clp->lc_deleg)) 558 nfsrv_writestable(clp->lc_id, 559 clp->lc_idlen, NFSNST_REVOKE, p); 560 nfsrv_cleanclient(clp, p); 561 nfsrv_freedeleglist(&clp->lc_deleg); 562 nfsrv_freedeleglist(&clp->lc_olddeleg); 563 LIST_REMOVE(clp, lc_hash); 564 nfsrv_zapclient(clp, p); 565 } 566 } 567 } 568 } 569 NFSLOCKV4ROOTMUTEX(); 570 nfsv4_unlock(&nfsv4rootfs_lock, 1); 571 NFSUNLOCKV4ROOTMUTEX(); 572 } else { 573 /* 574 * If we didn't get the lock, we need to get a refcnt, 575 * which also checks for and waits for the lock. 576 */ 577 NFSLOCKV4ROOTMUTEX(); 578 nfsv4_getref(&nfsv4rootfs_lock, NULL, 579 NFSV4ROOTLOCKMUTEXPTR, NULL); 580 NFSUNLOCKV4ROOTMUTEX(); 581 } 582 583 /* 584 * If flagged, search for open owners that haven't had any opens 585 * for a long time. 586 */ 587 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) { 588 nfsrv_throwawayopens(p); 589 } 590 591 savevp = vp = NULL; 592 save_fsid.val[0] = save_fsid.val[1] = 0; 593 cur_fsid.val[0] = cur_fsid.val[1] = 0; 594 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 595 taglen = fxdr_unsigned(int, *tl); 596 if (taglen < 0) { 597 error = EBADRPC; 598 goto nfsmout; 599 } 600 if (taglen <= NFSV4_SMALLSTR) 601 tagstr = tag; 602 else 603 tagstr = malloc(taglen + 1, M_TEMP, M_WAITOK); 604 error = nfsrv_mtostr(nd, tagstr, taglen); 605 if (error) { 606 if (taglen > NFSV4_SMALLSTR) 607 free(tagstr, M_TEMP); 608 taglen = -1; 609 goto nfsmout; 610 } 611 (void) nfsm_strtom(nd, tag, taglen); 612 if (taglen > NFSV4_SMALLSTR) { 613 free(tagstr, M_TEMP); 614 } 615 NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED); 616 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 617 minorvers = fxdr_unsigned(u_int32_t, *tl++); 618 if (minorvers != NFSV4_MINORVERSION) 619 nd->nd_repstat = NFSERR_MINORVERMISMATCH; 620 if (nd->nd_repstat) 621 numops = 0; 622 else 623 numops = fxdr_unsigned(int, *tl); 624 /* 625 * Loop around doing the sub ops. 626 * vp - is an unlocked vnode pointer for the CFH 627 * savevp - is an unlocked vnode pointer for the SAVEDFH 628 * (at some future date, it might turn out to be more appropriate 629 * to keep the file handles instead of vnode pointers?) 630 * savevpnes and vpnes - are the export flags for the above. 631 */ 632 for (i = 0; i < numops; i++) { 633 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 634 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED); 635 *repp = *tl; 636 op = fxdr_unsigned(int, *tl); 637 if (op < NFSV4OP_ACCESS || op >= NFSV4OP_NOPS) { 638 nd->nd_repstat = NFSERR_OPILLEGAL; 639 *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL); 640 *repp = nfsd_errmap(nd); 641 retops++; 642 break; 643 } else { 644 repp++; 645 } 646 647 /* 648 * Check for a referral on the current FH and, if so, return 649 * NFSERR_MOVED for all ops that allow it, except Getattr. 650 */ 651 if (vp != NULL && op != NFSV4OP_GETATTR && 652 nfsv4root_getreferral(vp, NULL, 0) != NULL && 653 nfsrv_errmoved(op)) { 654 nd->nd_repstat = NFSERR_MOVED; 655 *repp = nfsd_errmap(nd); 656 retops++; 657 break; 658 } 659 660 nd->nd_procnum = op; 661 /* 662 * If over flood level, reply NFSERR_RESOURCE, if at the first 663 * Op. (Since a client recovery from NFSERR_RESOURCE can get 664 * really nasty for certain Op sequences, I'll play it safe 665 * and only return the error at the beginning.) The cache 666 * will still function over flood level, but uses lots of 667 * mbufs.) 668 * If nfsrv_mallocmget_limit() returns True, the system is near 669 * to its limit for memory that malloc()/mget() can allocate. 670 */ 671 if (i == 0 && nd->nd_rp->rc_refcnt == 0 && 672 (nfsrv_mallocmget_limit() || 673 nfsrc_tcpsavedreplies > nfsrc_floodlevel)) { 674 if (nfsrc_tcpsavedreplies > nfsrc_floodlevel) { 675 printf("nfsd server cache flooded, try to"); 676 printf(" increase nfsrc_floodlevel\n"); 677 } 678 nd->nd_repstat = NFSERR_RESOURCE; 679 *repp = nfsd_errmap(nd); 680 if (op == NFSV4OP_SETATTR) { 681 /* 682 * Setattr replies require a bitmap. 683 * even for errors like these. 684 */ 685 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 686 *tl = 0; 687 } 688 retops++; 689 break; 690 } 691 if (nfsv4_opflag[op].savereply) 692 nd->nd_flag |= ND_SAVEREPLY; 693 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nd->nd_procnum]); 694 switch (op) { 695 case NFSV4OP_PUTFH: 696 error = nfsrv_mtofh(nd, &fh); 697 if (error) 698 goto nfsmout; 699 if (!nd->nd_repstat) 700 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes, 701 NULL, 0, p); 702 /* For now, allow this for non-export FHs */ 703 if (!nd->nd_repstat) { 704 if (vp) 705 vrele(vp); 706 vp = nvp; 707 cur_fsid = vp->v_mount->mnt_stat.f_fsid; 708 VOP_UNLOCK(vp, 0); 709 vpnes = nes; 710 } 711 break; 712 case NFSV4OP_PUTPUBFH: 713 if (nfs_pubfhset) 714 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp, 715 &nes, NULL, 0, p); 716 else 717 nd->nd_repstat = NFSERR_NOFILEHANDLE; 718 if (!nd->nd_repstat) { 719 if (vp) 720 vrele(vp); 721 vp = nvp; 722 cur_fsid = vp->v_mount->mnt_stat.f_fsid; 723 VOP_UNLOCK(vp, 0); 724 vpnes = nes; 725 } 726 break; 727 case NFSV4OP_PUTROOTFH: 728 if (nfs_rootfhset) { 729 nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp, 730 &nes, NULL, 0, p); 731 if (!nd->nd_repstat) { 732 if (vp) 733 vrele(vp); 734 vp = nvp; 735 cur_fsid = vp->v_mount->mnt_stat.f_fsid; 736 VOP_UNLOCK(vp, 0); 737 vpnes = nes; 738 } 739 } else 740 nd->nd_repstat = NFSERR_NOFILEHANDLE; 741 break; 742 case NFSV4OP_SAVEFH: 743 if (vp && NFSVNO_EXPORTED(&vpnes)) { 744 nd->nd_repstat = 0; 745 /* If vp == savevp, a no-op */ 746 if (vp != savevp) { 747 if (savevp) 748 vrele(savevp); 749 VREF(vp); 750 savevp = vp; 751 savevpnes = vpnes; 752 save_fsid = cur_fsid; 753 } 754 } else { 755 nd->nd_repstat = NFSERR_NOFILEHANDLE; 756 } 757 break; 758 case NFSV4OP_RESTOREFH: 759 if (savevp) { 760 nd->nd_repstat = 0; 761 /* If vp == savevp, a no-op */ 762 if (vp != savevp) { 763 VREF(savevp); 764 vrele(vp); 765 vp = savevp; 766 vpnes = savevpnes; 767 cur_fsid = save_fsid; 768 } 769 } else { 770 nd->nd_repstat = NFSERR_RESTOREFH; 771 } 772 break; 773 default: 774 /* 775 * Allow a Lookup, Getattr, GetFH, Secinfo on an 776 * non-exported directory if 777 * nfs_rootfhset. Do I need to allow any other Ops? 778 * (You can only have a non-exported vpnes if 779 * nfs_rootfhset is true. See nfsd_fhtovp()) 780 * Allow AUTH_SYS to be used for file systems 781 * exported GSS only for certain Ops, to allow 782 * clients to do mounts more easily. 783 */ 784 if (nfsv4_opflag[op].needscfh && vp) { 785 if (!NFSVNO_EXPORTED(&vpnes) && 786 op != NFSV4OP_LOOKUP && 787 op != NFSV4OP_GETATTR && 788 op != NFSV4OP_GETFH && 789 op != NFSV4OP_SECINFO) 790 nd->nd_repstat = NFSERR_NOFILEHANDLE; 791 else if (nfsvno_testexp(nd, &vpnes) && 792 op != NFSV4OP_LOOKUP && 793 op != NFSV4OP_GETFH && 794 op != NFSV4OP_GETATTR && 795 op != NFSV4OP_SECINFO) 796 nd->nd_repstat = NFSERR_WRONGSEC; 797 if (nd->nd_repstat) { 798 if (op == NFSV4OP_SETATTR) { 799 /* 800 * Setattr reply requires a bitmap 801 * even for errors like these. 802 */ 803 NFSM_BUILD(tl, u_int32_t *, 804 NFSX_UNSIGNED); 805 *tl = 0; 806 } 807 break; 808 } 809 } 810 if (nfsv4_opflag[op].retfh == 1) { 811 if (!vp) { 812 nd->nd_repstat = NFSERR_NOFILEHANDLE; 813 break; 814 } 815 VREF(vp); 816 if (nfsv4_opflag[op].modifyfs) 817 vn_start_write(vp, &temp_mp, V_WAIT); 818 error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp, 819 &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes); 820 if (!error && !nd->nd_repstat) { 821 if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) { 822 new_mp = nvp->v_mount; 823 if (cur_fsid.val[0] != 824 new_mp->mnt_stat.f_fsid.val[0] || 825 cur_fsid.val[1] != 826 new_mp->mnt_stat.f_fsid.val[1]) { 827 /* crossed a server mount point */ 828 nd->nd_repstat = nfsvno_checkexp(new_mp, 829 nd->nd_nam, &nes, &credanon); 830 if (!nd->nd_repstat) 831 nd->nd_repstat = nfsd_excred(nd, 832 &nes, credanon); 833 if (credanon != NULL) 834 crfree(credanon); 835 if (!nd->nd_repstat) { 836 vpnes = nes; 837 cur_fsid = new_mp->mnt_stat.f_fsid; 838 } 839 } 840 /* Lookup ops return a locked vnode */ 841 VOP_UNLOCK(nvp, 0); 842 } 843 if (!nd->nd_repstat) { 844 vrele(vp); 845 vp = nvp; 846 } else 847 vrele(nvp); 848 } 849 if (nfsv4_opflag[op].modifyfs) 850 vn_finished_write(temp_mp); 851 } else if (nfsv4_opflag[op].retfh == 2) { 852 if (vp == NULL || savevp == NULL) { 853 nd->nd_repstat = NFSERR_NOFILEHANDLE; 854 break; 855 } else if (cur_fsid.val[0] != save_fsid.val[0] || 856 cur_fsid.val[1] != save_fsid.val[1]) { 857 nd->nd_repstat = NFSERR_XDEV; 858 break; 859 } 860 if (nfsv4_opflag[op].modifyfs) 861 vn_start_write(savevp, &temp_mp, V_WAIT); 862 if (vn_lock(savevp, LK_EXCLUSIVE) == 0) { 863 VREF(vp); 864 VREF(savevp); 865 error = (*(nfsrv4_ops2[op]))(nd, isdgram, 866 savevp, vp, p, &savevpnes, &vpnes); 867 } else 868 nd->nd_repstat = NFSERR_PERM; 869 if (nfsv4_opflag[op].modifyfs) 870 vn_finished_write(temp_mp); 871 } else { 872 if (nfsv4_opflag[op].retfh != 0) 873 panic("nfsrvd_compound"); 874 if (nfsv4_opflag[op].needscfh) { 875 if (vp != NULL) { 876 if (nfsv4_opflag[op].modifyfs) 877 vn_start_write(vp, &temp_mp, 878 V_WAIT); 879 if (vn_lock(vp, nfsv4_opflag[op].lktype) 880 == 0) 881 VREF(vp); 882 else 883 nd->nd_repstat = NFSERR_PERM; 884 } else { 885 nd->nd_repstat = NFSERR_NOFILEHANDLE; 886 if (op == NFSV4OP_SETATTR) { 887 /* 888 * Setattr reply requires a 889 * bitmap even for errors like 890 * these. 891 */ 892 NFSM_BUILD(tl, u_int32_t *, 893 NFSX_UNSIGNED); 894 *tl = 0; 895 } 896 break; 897 } 898 if (nd->nd_repstat == 0) 899 error = (*(nfsrv4_ops0[op]))(nd, 900 isdgram, vp, p, &vpnes); 901 if (nfsv4_opflag[op].modifyfs) 902 vn_finished_write(temp_mp); 903 } else { 904 error = (*(nfsrv4_ops0[op]))(nd, isdgram, 905 NULL, p, &vpnes); 906 } 907 } 908 }; 909 if (error) { 910 if (error == EBADRPC || error == NFSERR_BADXDR) { 911 nd->nd_repstat = NFSERR_BADXDR; 912 } else { 913 nd->nd_repstat = error; 914 printf("nfsv4 comperr0=%d\n", error); 915 } 916 error = 0; 917 } 918 retops++; 919 if (nd->nd_repstat) { 920 *repp = nfsd_errmap(nd); 921 break; 922 } else { 923 *repp = 0; /* NFS4_OK */ 924 } 925 } 926 nfsmout: 927 if (error) { 928 if (error == EBADRPC || error == NFSERR_BADXDR) 929 nd->nd_repstat = NFSERR_BADXDR; 930 else 931 printf("nfsv4 comperr1=%d\n", error); 932 } 933 if (taglen == -1) { 934 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 935 *tl++ = 0; 936 *tl = 0; 937 } else { 938 *retopsp = txdr_unsigned(retops); 939 } 940 if (vp) 941 vrele(vp); 942 if (savevp) 943 vrele(savevp); 944 NFSLOCKV4ROOTMUTEX(); 945 nfsv4_relref(&nfsv4rootfs_lock); 946 NFSUNLOCKV4ROOTMUTEX(); 947 } 948