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