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