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