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