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