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