1 /* $NetBSD: nfs_nfsdsocket.c,v 1.1.1.1 2013/09/30 07:19:47 dholland Exp $ */ 2 /*- 3 * Copyright (c) 1989, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * Rick Macklem at The University of Guelph. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 */ 34 35 #include <sys/cdefs.h> 36 /* __FBSDID("FreeBSD: head/sys/fs/nfsserver/nfs_nfsdsocket.c 249592 2013-04-17 21:00:22Z ken "); */ 37 __RCSID("$NetBSD: nfs_nfsdsocket.c,v 1.1.1.1 2013/09/30 07:19:47 dholland Exp $"); 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 nfsstats newnfsstats; 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[NFSCLIENTHASHSIZE]; 52 extern int nfsrc_floodlevel, nfsrc_tcpsavedreplies; 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[NFSV4OP_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 }; 179 180 int (*nfsrv4_ops1[NFSV4OP_NOPS])(struct nfsrv_descript *, 181 int, vnode_t , vnode_t *, fhandle_t *, 182 NFSPROC_T *, struct nfsexstuff *) = { 183 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 184 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 185 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 186 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 187 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 188 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 189 nfsrvd_mknod, 190 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 191 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 192 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 193 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 194 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 195 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 196 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 197 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 198 nfsrvd_lookup, 199 nfsrvd_lookup, 200 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0, 201 nfsrvd_open, 202 nfsrvd_openattr, 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 (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 (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 (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 }; 224 225 int (*nfsrv4_ops2[NFSV4OP_NOPS])(struct nfsrv_descript *, 226 int, vnode_t , vnode_t , NFSPROC_T *, 227 struct nfsexstuff *, struct nfsexstuff *) = { 228 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 229 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 230 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 231 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 232 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 233 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 234 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 235 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 236 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 237 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 238 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 239 nfsrvd_link, 240 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 241 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 242 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 243 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 244 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 245 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 246 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 247 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 248 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 249 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 250 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 251 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 252 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 253 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 254 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 255 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 256 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 257 nfsrvd_rename, 258 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 259 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 260 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 261 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 262 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 263 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 264 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0, 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 }; 269 #endif /* !APPLEKEXT */ 270 271 /* 272 * Static array that defines which nfs rpc's are nonidempotent 273 */ 274 static int nfsrv_nonidempotent[NFS_V3NPROCS] = { 275 FALSE, 276 FALSE, 277 TRUE, 278 FALSE, 279 FALSE, 280 FALSE, 281 FALSE, 282 TRUE, 283 TRUE, 284 TRUE, 285 TRUE, 286 TRUE, 287 TRUE, 288 TRUE, 289 TRUE, 290 TRUE, 291 FALSE, 292 FALSE, 293 FALSE, 294 FALSE, 295 FALSE, 296 FALSE, 297 }; 298 299 /* 300 * This static array indicates whether or not the RPC modifies the 301 * file system. 302 */ 303 static int nfs_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0, 304 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 305 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; 306 307 /* local functions */ 308 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, 309 NFSPROC_T *p); 310 311 312 /* 313 * This static array indicates which server procedures require the extra 314 * arguments to return the current file handle for V2, 3. 315 */ 316 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 317 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 }; 318 319 extern struct nfsv4_opflag nfsv4_opflag[NFSV4OP_NOPS]; 320 321 static int nfsv3to4op[NFS_V3NPROCS] = { 322 NFSPROC_NULL, 323 NFSV4OP_GETATTR, 324 NFSV4OP_SETATTR, 325 NFSV4OP_LOOKUP, 326 NFSV4OP_ACCESS, 327 NFSV4OP_READLINK, 328 NFSV4OP_READ, 329 NFSV4OP_WRITE, 330 NFSV4OP_V3CREATE, 331 NFSV4OP_MKDIR, 332 NFSV4OP_SYMLINK, 333 NFSV4OP_MKNOD, 334 NFSV4OP_REMOVE, 335 NFSV4OP_RMDIR, 336 NFSV4OP_RENAME, 337 NFSV4OP_LINK, 338 NFSV4OP_READDIR, 339 NFSV4OP_READDIRPLUS, 340 NFSV4OP_FSSTAT, 341 NFSV4OP_FSINFO, 342 NFSV4OP_PATHCONF, 343 NFSV4OP_COMMIT, 344 }; 345 346 /* 347 * Do an RPC. Basically, get the file handles translated to vnode pointers 348 * and then call the appropriate server routine. The server routines are 349 * split into groups, based on whether they use a file handle or file 350 * handle plus name or ... 351 * The NFS V4 Compound RPC is performed separately by nfsrvd_compound(). 352 */ 353 APPLESTATIC void 354 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, 355 NFSPROC_T *p) 356 { 357 int error = 0, lktype; 358 vnode_t vp; 359 mount_t mp = NULL; 360 struct nfsrvfh fh; 361 struct nfsexstuff nes; 362 363 /* 364 * Get a locked vnode for the first file handle 365 */ 366 if (!(nd->nd_flag & ND_NFSV4)) { 367 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc")); 368 /* 369 * For NFSv3, if the malloc/mget allocation is near limits, 370 * return NFSERR_DELAY. 371 */ 372 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) { 373 nd->nd_repstat = NFSERR_DELAY; 374 vp = NULL; 375 } else { 376 error = nfsrv_mtofh(nd, &fh); 377 if (error) { 378 if (error != EBADRPC) 379 printf("nfs dorpc err1=%d\n", error); 380 nd->nd_repstat = NFSERR_GARBAGE; 381 goto out; 382 } 383 if (nd->nd_procnum == NFSPROC_READ || 384 nd->nd_procnum == NFSPROC_WRITE || 385 nd->nd_procnum == NFSPROC_READDIR || 386 nd->nd_procnum == NFSPROC_READLINK || 387 nd->nd_procnum == NFSPROC_GETATTR || 388 nd->nd_procnum == NFSPROC_ACCESS) 389 lktype = LK_SHARED; 390 else 391 lktype = LK_EXCLUSIVE; 392 if (nd->nd_flag & ND_PUBLOOKUP) 393 nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes, 394 &mp, nfs_writerpc[nd->nd_procnum], p); 395 else 396 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes, 397 &mp, nfs_writerpc[nd->nd_procnum], p); 398 if (nd->nd_repstat == NFSERR_PROGNOTV4) 399 goto out; 400 } 401 } 402 403 /* 404 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request 405 * cache, as required. 406 * For V4, nfsrvd_compound() does this. 407 */ 408 if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum]) 409 nd->nd_flag |= ND_SAVEREPLY; 410 411 nfsrvd_rephead(nd); 412 /* 413 * If nd_repstat is non-zero, just fill in the reply status 414 * to complete the RPC reply for V2. Otherwise, you must do 415 * the RPC. 416 */ 417 if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) { 418 *nd->nd_errp = nfsd_errmap(nd); 419 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]); 420 if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0) 421 vn_finished_write(mp); 422 goto out; 423 } 424 425 /* 426 * Now the procedure can be performed. For V4, nfsrvd_compound() 427 * works through the sub-rpcs, otherwise just call the procedure. 428 * The procedures are in three groups with different arguments. 429 * The group is indicated by the value in nfs_retfh[]. 430 */ 431 if (nd->nd_flag & ND_NFSV4) { 432 nfsrvd_compound(nd, isdgram, p); 433 } else { 434 if (nfs_retfh[nd->nd_procnum] == 1) { 435 if (vp) 436 NFSVOPUNLOCK(vp, 0); 437 error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram, 438 vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes); 439 } else if (nfs_retfh[nd->nd_procnum] == 2) { 440 error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram, 441 vp, NULL, p, &nes, NULL); 442 } else { 443 error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram, 444 vp, p, &nes); 445 } 446 if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0) 447 vn_finished_write(mp); 448 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]); 449 } 450 if (error) { 451 if (error != EBADRPC) 452 printf("nfs dorpc err2=%d\n", error); 453 nd->nd_repstat = NFSERR_GARBAGE; 454 } 455 *nd->nd_errp = nfsd_errmap(nd); 456 457 /* 458 * Don't cache certain reply status values. 459 */ 460 if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) && 461 (nd->nd_repstat == NFSERR_GARBAGE || 462 nd->nd_repstat == NFSERR_BADXDR || 463 nd->nd_repstat == NFSERR_MOVED || 464 nd->nd_repstat == NFSERR_DELAY || 465 nd->nd_repstat == NFSERR_BADSEQID || 466 nd->nd_repstat == NFSERR_RESOURCE || 467 nd->nd_repstat == NFSERR_SERVERFAULT || 468 nd->nd_repstat == NFSERR_STALECLIENTID || 469 nd->nd_repstat == NFSERR_STALESTATEID || 470 nd->nd_repstat == NFSERR_OLDSTATEID || 471 nd->nd_repstat == NFSERR_BADSTATEID || 472 nd->nd_repstat == NFSERR_GRACE || 473 nd->nd_repstat == NFSERR_NOGRACE)) 474 nd->nd_flag &= ~ND_SAVEREPLY; 475 476 out: 477 NFSEXITCODE2(0, nd); 478 } 479 480 /* 481 * Breaks down a compound RPC request and calls the server routines for 482 * the subprocedures. 483 * Some suboperations are performed directly here to simplify file handle<--> 484 * vnode pointer handling. 485 */ 486 static void 487 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, 488 NFSPROC_T *p) 489 { 490 int i, op; 491 u_int32_t *tl; 492 struct nfsclient *clp, *nclp; 493 int numops, taglen = -1, error = 0, igotlock; 494 u_int32_t minorvers, retops = 0, *retopsp = NULL, *repp; 495 u_char tag[NFSV4_SMALLSTR + 1], *tagstr; 496 vnode_t vp, nvp, savevp; 497 struct nfsrvfh fh; 498 mount_t new_mp, temp_mp = NULL; 499 struct ucred *credanon; 500 struct nfsexstuff nes, vpnes, savevpnes; 501 fsid_t cur_fsid, save_fsid; 502 static u_int64_t compref = 0; 503 504 NFSVNO_EXINIT(&vpnes); 505 NFSVNO_EXINIT(&savevpnes); 506 /* 507 * Put the seq# of the current compound RPC in nfsrv_descript. 508 * (This is used by nfsrv_checkgetattr(), to see if the write 509 * delegation was created by the same compound RPC as the one 510 * with that Getattr in it.) 511 * Don't worry about the 64bit number wrapping around. It ain't 512 * gonna happen before this server gets shut down/rebooted. 513 */ 514 nd->nd_compref = compref++; 515 516 /* 517 * Check for and optionally get a lock on the root. This lock means that 518 * no nfsd will be fiddling with the V4 file system and state stuff. It 519 * is required when the V4 root is being changed, the stable storage 520 * restart file is being updated, or callbacks are being done. 521 * When any of the nfsd are processing an NFSv4 compound RPC, they must 522 * either hold a reference count (nfs_usecnt) or the lock. When 523 * nfsrv_unlock() is called to release the lock, it can optionally 524 * also get a reference count, which saves the need for a call to 525 * nfsrv_getref() after nfsrv_unlock(). 526 */ 527 /* 528 * First, check to see if we need to wait for an update lock. 529 */ 530 igotlock = 0; 531 NFSLOCKV4ROOTMUTEX(); 532 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK) 533 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 534 NFSV4ROOTLOCKMUTEXPTR, NULL); 535 else 536 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL, 537 NFSV4ROOTLOCKMUTEXPTR, NULL); 538 NFSUNLOCKV4ROOTMUTEX(); 539 if (igotlock) { 540 /* 541 * If I got the lock, I can update the stable storage file. 542 * Done when the grace period is over or a client has long 543 * since expired. 544 */ 545 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK; 546 if ((nfsrv_stablefirst.nsf_flags & 547 (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER) 548 nfsrv_updatestable(p); 549 550 /* 551 * If at least one client has long since expired, search 552 * the client list for them, write a REVOKE record on the 553 * stable storage file and then remove them from the client 554 * list. 555 */ 556 if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) { 557 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT; 558 for (i = 0; i < NFSCLIENTHASHSIZE; i++) { 559 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, 560 nclp) { 561 if (clp->lc_flags & LCL_EXPIREIT) { 562 if (!LIST_EMPTY(&clp->lc_open) || 563 !LIST_EMPTY(&clp->lc_deleg)) 564 nfsrv_writestable(clp->lc_id, 565 clp->lc_idlen, NFSNST_REVOKE, p); 566 nfsrv_cleanclient(clp, p); 567 nfsrv_freedeleglist(&clp->lc_deleg); 568 nfsrv_freedeleglist(&clp->lc_olddeleg); 569 LIST_REMOVE(clp, lc_hash); 570 nfsrv_zapclient(clp, p); 571 } 572 } 573 } 574 } 575 NFSLOCKV4ROOTMUTEX(); 576 nfsv4_unlock(&nfsv4rootfs_lock, 1); 577 NFSUNLOCKV4ROOTMUTEX(); 578 } else { 579 /* 580 * If we didn't get the lock, we need to get a refcnt, 581 * which also checks for and waits for the lock. 582 */ 583 NFSLOCKV4ROOTMUTEX(); 584 nfsv4_getref(&nfsv4rootfs_lock, NULL, 585 NFSV4ROOTLOCKMUTEXPTR, NULL); 586 NFSUNLOCKV4ROOTMUTEX(); 587 } 588 589 /* 590 * If flagged, search for open owners that haven't had any opens 591 * for a long time. 592 */ 593 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) { 594 nfsrv_throwawayopens(p); 595 } 596 597 savevp = vp = NULL; 598 save_fsid.val[0] = save_fsid.val[1] = 0; 599 cur_fsid.val[0] = cur_fsid.val[1] = 0; 600 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 601 taglen = fxdr_unsigned(int, *tl); 602 if (taglen < 0) { 603 error = EBADRPC; 604 goto nfsmout; 605 } 606 if (taglen <= NFSV4_SMALLSTR) 607 tagstr = tag; 608 else 609 tagstr = malloc(taglen + 1, M_TEMP, M_WAITOK); 610 error = nfsrv_mtostr(nd, tagstr, taglen); 611 if (error) { 612 if (taglen > NFSV4_SMALLSTR) 613 free(tagstr, M_TEMP); 614 taglen = -1; 615 goto nfsmout; 616 } 617 (void) nfsm_strtom(nd, tag, taglen); 618 if (taglen > NFSV4_SMALLSTR) { 619 free(tagstr, M_TEMP); 620 } 621 NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED); 622 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 623 minorvers = fxdr_unsigned(u_int32_t, *tl++); 624 if (minorvers != NFSV4_MINORVERSION) 625 nd->nd_repstat = NFSERR_MINORVERMISMATCH; 626 if (nd->nd_repstat) 627 numops = 0; 628 else 629 numops = fxdr_unsigned(int, *tl); 630 /* 631 * Loop around doing the sub ops. 632 * vp - is an unlocked vnode pointer for the CFH 633 * savevp - is an unlocked vnode pointer for the SAVEDFH 634 * (at some future date, it might turn out to be more appropriate 635 * to keep the file handles instead of vnode pointers?) 636 * savevpnes and vpnes - are the export flags for the above. 637 */ 638 for (i = 0; i < numops; i++) { 639 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 640 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED); 641 *repp = *tl; 642 op = fxdr_unsigned(int, *tl); 643 if (op < NFSV4OP_ACCESS || op >= NFSV4OP_NOPS) { 644 nd->nd_repstat = NFSERR_OPILLEGAL; 645 *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL); 646 *repp = nfsd_errmap(nd); 647 retops++; 648 break; 649 } else { 650 repp++; 651 } 652 653 /* 654 * Check for a referral on the current FH and, if so, return 655 * NFSERR_MOVED for all ops that allow it, except Getattr. 656 */ 657 if (vp != NULL && op != NFSV4OP_GETATTR && 658 nfsv4root_getreferral(vp, NULL, 0) != NULL && 659 nfsrv_errmoved(op)) { 660 nd->nd_repstat = NFSERR_MOVED; 661 *repp = nfsd_errmap(nd); 662 retops++; 663 break; 664 } 665 666 nd->nd_procnum = op; 667 /* 668 * If over flood level, reply NFSERR_RESOURCE, if at the first 669 * Op. (Since a client recovery from NFSERR_RESOURCE can get 670 * really nasty for certain Op sequences, I'll play it safe 671 * and only return the error at the beginning.) The cache 672 * will still function over flood level, but uses lots of 673 * mbufs.) 674 * If nfsrv_mallocmget_limit() returns True, the system is near 675 * to its limit for memory that malloc()/mget() can allocate. 676 */ 677 if (i == 0 && nd->nd_rp->rc_refcnt == 0 && 678 (nfsrv_mallocmget_limit() || 679 nfsrc_tcpsavedreplies > nfsrc_floodlevel)) { 680 if (nfsrc_tcpsavedreplies > nfsrc_floodlevel) { 681 printf("nfsd server cache flooded, try to"); 682 printf(" increase nfsrc_floodlevel\n"); 683 } 684 nd->nd_repstat = NFSERR_RESOURCE; 685 *repp = nfsd_errmap(nd); 686 if (op == NFSV4OP_SETATTR) { 687 /* 688 * Setattr replies require a bitmap. 689 * even for errors like these. 690 */ 691 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 692 *tl = 0; 693 } 694 retops++; 695 break; 696 } 697 if (nfsv4_opflag[op].savereply) 698 nd->nd_flag |= ND_SAVEREPLY; 699 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nd->nd_procnum]); 700 switch (op) { 701 case NFSV4OP_PUTFH: 702 error = nfsrv_mtofh(nd, &fh); 703 if (error) 704 goto nfsmout; 705 if (!nd->nd_repstat) 706 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes, 707 NULL, 0, p); 708 /* For now, allow this for non-export FHs */ 709 if (!nd->nd_repstat) { 710 if (vp) 711 vrele(vp); 712 vp = nvp; 713 cur_fsid = vp->v_mount->mnt_stat.f_fsid; 714 NFSVOPUNLOCK(vp, 0); 715 vpnes = nes; 716 } 717 break; 718 case NFSV4OP_PUTPUBFH: 719 if (nfs_pubfhset) 720 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp, 721 &nes, NULL, 0, p); 722 else 723 nd->nd_repstat = NFSERR_NOFILEHANDLE; 724 if (!nd->nd_repstat) { 725 if (vp) 726 vrele(vp); 727 vp = nvp; 728 cur_fsid = vp->v_mount->mnt_stat.f_fsid; 729 NFSVOPUNLOCK(vp, 0); 730 vpnes = nes; 731 } 732 break; 733 case NFSV4OP_PUTROOTFH: 734 if (nfs_rootfhset) { 735 nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp, 736 &nes, NULL, 0, p); 737 if (!nd->nd_repstat) { 738 if (vp) 739 vrele(vp); 740 vp = nvp; 741 cur_fsid = vp->v_mount->mnt_stat.f_fsid; 742 NFSVOPUNLOCK(vp, 0); 743 vpnes = nes; 744 } 745 } else 746 nd->nd_repstat = NFSERR_NOFILEHANDLE; 747 break; 748 case NFSV4OP_SAVEFH: 749 if (vp && NFSVNO_EXPORTED(&vpnes)) { 750 nd->nd_repstat = 0; 751 /* If vp == savevp, a no-op */ 752 if (vp != savevp) { 753 if (savevp) 754 vrele(savevp); 755 VREF(vp); 756 savevp = vp; 757 savevpnes = vpnes; 758 save_fsid = cur_fsid; 759 } 760 } else { 761 nd->nd_repstat = NFSERR_NOFILEHANDLE; 762 } 763 break; 764 case NFSV4OP_RESTOREFH: 765 if (savevp) { 766 nd->nd_repstat = 0; 767 /* If vp == savevp, a no-op */ 768 if (vp != savevp) { 769 VREF(savevp); 770 vrele(vp); 771 vp = savevp; 772 vpnes = savevpnes; 773 cur_fsid = save_fsid; 774 } 775 } else { 776 nd->nd_repstat = NFSERR_RESTOREFH; 777 } 778 break; 779 default: 780 /* 781 * Allow a Lookup, Getattr, GetFH, Secinfo on an 782 * non-exported directory if 783 * nfs_rootfhset. Do I need to allow any other Ops? 784 * (You can only have a non-exported vpnes if 785 * nfs_rootfhset is true. See nfsd_fhtovp()) 786 * Allow AUTH_SYS to be used for file systems 787 * exported GSS only for certain Ops, to allow 788 * clients to do mounts more easily. 789 */ 790 if (nfsv4_opflag[op].needscfh && vp) { 791 if (!NFSVNO_EXPORTED(&vpnes) && 792 op != NFSV4OP_LOOKUP && 793 op != NFSV4OP_GETATTR && 794 op != NFSV4OP_GETFH && 795 op != NFSV4OP_ACCESS && 796 op != NFSV4OP_READLINK && 797 op != NFSV4OP_SECINFO) 798 nd->nd_repstat = NFSERR_NOFILEHANDLE; 799 else if (nfsvno_testexp(nd, &vpnes) && 800 op != NFSV4OP_LOOKUP && 801 op != NFSV4OP_GETFH && 802 op != NFSV4OP_GETATTR && 803 op != NFSV4OP_SECINFO) 804 nd->nd_repstat = NFSERR_WRONGSEC; 805 if (nd->nd_repstat) { 806 if (op == NFSV4OP_SETATTR) { 807 /* 808 * Setattr reply requires a bitmap 809 * even for errors like these. 810 */ 811 NFSM_BUILD(tl, u_int32_t *, 812 NFSX_UNSIGNED); 813 *tl = 0; 814 } 815 break; 816 } 817 } 818 if (nfsv4_opflag[op].retfh == 1) { 819 if (!vp) { 820 nd->nd_repstat = NFSERR_NOFILEHANDLE; 821 break; 822 } 823 VREF(vp); 824 if (nfsv4_opflag[op].modifyfs) 825 vn_start_write(vp, &temp_mp, V_WAIT); 826 error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp, 827 &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes); 828 if (!error && !nd->nd_repstat) { 829 if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) { 830 new_mp = nvp->v_mount; 831 if (cur_fsid.val[0] != 832 new_mp->mnt_stat.f_fsid.val[0] || 833 cur_fsid.val[1] != 834 new_mp->mnt_stat.f_fsid.val[1]) { 835 /* crossed a server mount point */ 836 nd->nd_repstat = nfsvno_checkexp(new_mp, 837 nd->nd_nam, &nes, &credanon); 838 if (!nd->nd_repstat) 839 nd->nd_repstat = nfsd_excred(nd, 840 &nes, credanon); 841 if (credanon != NULL) 842 crfree(credanon); 843 if (!nd->nd_repstat) { 844 vpnes = nes; 845 cur_fsid = new_mp->mnt_stat.f_fsid; 846 } 847 } 848 /* Lookup ops return a locked vnode */ 849 NFSVOPUNLOCK(nvp, 0); 850 } 851 if (!nd->nd_repstat) { 852 vrele(vp); 853 vp = nvp; 854 } else 855 vrele(nvp); 856 } 857 if (nfsv4_opflag[op].modifyfs) 858 vn_finished_write(temp_mp); 859 } else if (nfsv4_opflag[op].retfh == 2) { 860 if (vp == NULL || savevp == NULL) { 861 nd->nd_repstat = NFSERR_NOFILEHANDLE; 862 break; 863 } else if (cur_fsid.val[0] != save_fsid.val[0] || 864 cur_fsid.val[1] != save_fsid.val[1]) { 865 nd->nd_repstat = NFSERR_XDEV; 866 break; 867 } 868 if (nfsv4_opflag[op].modifyfs) 869 vn_start_write(savevp, &temp_mp, V_WAIT); 870 if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) { 871 VREF(vp); 872 VREF(savevp); 873 error = (*(nfsrv4_ops2[op]))(nd, isdgram, 874 savevp, vp, p, &savevpnes, &vpnes); 875 } else 876 nd->nd_repstat = NFSERR_PERM; 877 if (nfsv4_opflag[op].modifyfs) 878 vn_finished_write(temp_mp); 879 } else { 880 if (nfsv4_opflag[op].retfh != 0) 881 panic("nfsrvd_compound"); 882 if (nfsv4_opflag[op].needscfh) { 883 if (vp != NULL) { 884 if (nfsv4_opflag[op].modifyfs) 885 vn_start_write(vp, &temp_mp, 886 V_WAIT); 887 if (NFSVOPLOCK(vp, nfsv4_opflag[op].lktype) 888 == 0) 889 VREF(vp); 890 else 891 nd->nd_repstat = NFSERR_PERM; 892 } else { 893 nd->nd_repstat = NFSERR_NOFILEHANDLE; 894 if (op == NFSV4OP_SETATTR) { 895 /* 896 * Setattr reply requires a 897 * bitmap even for errors like 898 * these. 899 */ 900 NFSM_BUILD(tl, u_int32_t *, 901 NFSX_UNSIGNED); 902 *tl = 0; 903 } 904 break; 905 } 906 if (nd->nd_repstat == 0) 907 error = (*(nfsrv4_ops0[op]))(nd, 908 isdgram, vp, p, &vpnes); 909 if (nfsv4_opflag[op].modifyfs) 910 vn_finished_write(temp_mp); 911 } else { 912 error = (*(nfsrv4_ops0[op]))(nd, isdgram, 913 NULL, p, &vpnes); 914 } 915 } 916 }; 917 if (error) { 918 if (error == EBADRPC || error == NFSERR_BADXDR) { 919 nd->nd_repstat = NFSERR_BADXDR; 920 } else { 921 nd->nd_repstat = error; 922 printf("nfsv4 comperr0=%d\n", error); 923 } 924 error = 0; 925 } 926 retops++; 927 if (nd->nd_repstat) { 928 *repp = nfsd_errmap(nd); 929 break; 930 } else { 931 *repp = 0; /* NFS4_OK */ 932 } 933 } 934 nfsmout: 935 if (error) { 936 if (error == EBADRPC || error == NFSERR_BADXDR) 937 nd->nd_repstat = NFSERR_BADXDR; 938 else 939 printf("nfsv4 comperr1=%d\n", error); 940 } 941 if (taglen == -1) { 942 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 943 *tl++ = 0; 944 *tl = 0; 945 } else { 946 *retopsp = txdr_unsigned(retops); 947 } 948 if (vp) 949 vrele(vp); 950 if (savevp) 951 vrele(savevp); 952 NFSLOCKV4ROOTMUTEX(); 953 nfsv4_relref(&nfsv4rootfs_lock); 954 NFSUNLOCKV4ROOTMUTEX(); 955 956 NFSEXITCODE2(0, nd); 957 } 958