1191783Srmacklem/*- 2191783Srmacklem * Copyright (c) 1989, 1993 3191783Srmacklem * The Regents of the University of California. All rights reserved. 4191783Srmacklem * 5191783Srmacklem * This code is derived from software contributed to Berkeley by 6191783Srmacklem * Rick Macklem at The University of Guelph. 7191783Srmacklem * 8191783Srmacklem * Redistribution and use in source and binary forms, with or without 9191783Srmacklem * modification, are permitted provided that the following conditions 10191783Srmacklem * are met: 11191783Srmacklem * 1. Redistributions of source code must retain the above copyright 12191783Srmacklem * notice, this list of conditions and the following disclaimer. 13191783Srmacklem * 2. Redistributions in binary form must reproduce the above copyright 14191783Srmacklem * notice, this list of conditions and the following disclaimer in the 15191783Srmacklem * documentation and/or other materials provided with the distribution. 16191783Srmacklem * 4. Neither the name of the University nor the names of its contributors 17191783Srmacklem * may be used to endorse or promote products derived from this software 18191783Srmacklem * without specific prior written permission. 19191783Srmacklem * 20191783Srmacklem * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21191783Srmacklem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22191783Srmacklem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23191783Srmacklem * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24191783Srmacklem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25191783Srmacklem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26191783Srmacklem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27191783Srmacklem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28191783Srmacklem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29191783Srmacklem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30191783Srmacklem * SUCH DAMAGE. 31191783Srmacklem * 32191783Srmacklem */ 33191783Srmacklem 34191783Srmacklem#include <sys/cdefs.h> 35191783Srmacklem__FBSDID("$FreeBSD$"); 36191783Srmacklem 37191783Srmacklem#ifndef APPLEKEXT 38191783Srmacklem/* 39191783Srmacklem * These functions support the macros and help fiddle mbuf chains for 40191783Srmacklem * the nfs op functions. They do things like create the rpc header and 41191783Srmacklem * copy data between mbuf chains and uio lists. 42191783Srmacklem */ 43191783Srmacklem#include <fs/nfs/nfsport.h> 44191783Srmacklem 45191783Srmacklemextern u_int32_t newnfs_true, newnfs_false; 46191783Srmacklemextern int nfs_pubfhset; 47284216Srmacklemextern struct nfsclienthashhead *nfsclienthash; 48284216Srmacklemextern int nfsrv_clienthashsize; 49284216Srmacklemextern struct nfslockhashhead *nfslockhash; 50284216Srmacklemextern int nfsrv_lockhashsize; 51284216Srmacklemextern struct nfssessionhash *nfssessionhash; 52284216Srmacklemextern int nfsrv_sessionhashsize; 53191783Srmacklemextern int nfsrv_useacl; 54191783Srmacklemextern uid_t nfsrv_defaultuid; 55191783Srmacklemextern gid_t nfsrv_defaultgid; 56191783Srmacklem 57191783Srmacklemchar nfs_v2pubfh[NFSX_V2FH]; 58191783Srmacklemstatic nfstype newnfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, 59191783Srmacklem NFNON, NFCHR, NFNON }; 60191783Srmacklemextern nfstype nfsv34_type[9]; 61191783Srmacklem#endif /* !APPLEKEXT */ 62191783Srmacklem 63269398Srmacklemstatic u_int32_t nfsrv_isannfserr(u_int32_t); 64269398Srmacklem 65228260SrmacklemSYSCTL_DECL(_vfs_nfsd); 66228260Srmacklem 67228260Srmacklemstatic int disable_checkutf8 = 0; 68228260SrmacklemSYSCTL_INT(_vfs_nfsd, OID_AUTO, disable_checkutf8, CTLFLAG_RW, 69228260Srmacklem &disable_checkutf8, 0, 70228260Srmacklem "Disable the NFSv4 check for a UTF8 compliant name"); 71228260Srmacklem 72273877Saraujostatic int enable_nobodycheck = 1; 73273877SaraujoSYSCTL_INT(_vfs_nfsd, OID_AUTO, enable_nobodycheck, CTLFLAG_RW, 74273877Saraujo &enable_nobodycheck, 0, 75273877Saraujo "Enable the NFSv4 check when setting user nobody as owner"); 76273877Saraujo 77273877Saraujostatic int enable_nogroupcheck = 1; 78273877SaraujoSYSCTL_INT(_vfs_nfsd, OID_AUTO, enable_nogroupcheck, CTLFLAG_RW, 79273877Saraujo &enable_nogroupcheck, 0, 80273877Saraujo "Enable the NFSv4 check when setting group nogroup as owner"); 81273877Saraujo 82191783Srmacklemstatic char nfsrv_hexdigit(char, int *); 83191783Srmacklem 84191783Srmacklem/* 85191783Srmacklem * Maps errno values to nfs error numbers. 86191783Srmacklem * Use NFSERR_IO as the catch all for ones not specifically defined in 87269398Srmacklem * RFC 1094. (It now includes the errors added for NFSv3.) 88191783Srmacklem */ 89269398Srmacklemstatic u_char nfsrv_v2errmap[NFSERR_REMOTE] = { 90191783Srmacklem NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO, 91191783Srmacklem NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 92191783Srmacklem NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO, 93269398Srmacklem NFSERR_IO, NFSERR_EXIST, NFSERR_XDEV, NFSERR_NODEV, NFSERR_NOTDIR, 94269398Srmacklem NFSERR_ISDIR, NFSERR_INVAL, NFSERR_IO, NFSERR_IO, NFSERR_IO, 95191783Srmacklem NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS, 96269398Srmacklem NFSERR_MLINK, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 97191783Srmacklem NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 98191783Srmacklem NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 99191783Srmacklem NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 100191783Srmacklem NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 101191783Srmacklem NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 102191783Srmacklem NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO, 103191783Srmacklem NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE, 104269398Srmacklem NFSERR_REMOTE, 105191783Srmacklem}; 106191783Srmacklem 107191783Srmacklem/* 108191783Srmacklem * Maps errno values to nfs error numbers. 109191783Srmacklem * Although it is not obvious whether or not NFS clients really care if 110191783Srmacklem * a returned error value is in the specified list for the procedure, the 111191783Srmacklem * safest thing to do is filter them appropriately. For Version 2, the 112191783Srmacklem * X/Open XNFS document is the only specification that defines error values 113191783Srmacklem * for each RPC (The RFC simply lists all possible error values for all RPCs), 114191783Srmacklem * so I have decided to not do this for Version 2. 115191783Srmacklem * The first entry is the default error return and the rest are the valid 116191783Srmacklem * errors for that RPC in increasing numeric order. 117191783Srmacklem */ 118191783Srmacklemstatic short nfsv3err_null[] = { 119191783Srmacklem 0, 120191783Srmacklem 0, 121191783Srmacklem}; 122191783Srmacklem 123191783Srmacklemstatic short nfsv3err_getattr[] = { 124191783Srmacklem NFSERR_IO, 125191783Srmacklem NFSERR_IO, 126191783Srmacklem NFSERR_STALE, 127191783Srmacklem NFSERR_BADHANDLE, 128191783Srmacklem NFSERR_SERVERFAULT, 129191783Srmacklem NFSERR_DELAY, 130191783Srmacklem 0, 131191783Srmacklem}; 132191783Srmacklem 133191783Srmacklemstatic short nfsv3err_setattr[] = { 134191783Srmacklem NFSERR_IO, 135191783Srmacklem NFSERR_ACCES, 136191783Srmacklem NFSERR_PERM, 137191783Srmacklem NFSERR_IO, 138191783Srmacklem NFSERR_INVAL, 139191783Srmacklem NFSERR_NOSPC, 140191783Srmacklem NFSERR_ROFS, 141191783Srmacklem NFSERR_DQUOT, 142191783Srmacklem NFSERR_STALE, 143191783Srmacklem NFSERR_BADHANDLE, 144191783Srmacklem NFSERR_NOT_SYNC, 145191783Srmacklem NFSERR_SERVERFAULT, 146191783Srmacklem NFSERR_DELAY, 147191783Srmacklem 0, 148191783Srmacklem}; 149191783Srmacklem 150191783Srmacklemstatic short nfsv3err_lookup[] = { 151191783Srmacklem NFSERR_IO, 152191783Srmacklem NFSERR_NOENT, 153191783Srmacklem NFSERR_ACCES, 154191783Srmacklem NFSERR_NAMETOL, 155191783Srmacklem NFSERR_IO, 156191783Srmacklem NFSERR_NOTDIR, 157191783Srmacklem NFSERR_STALE, 158191783Srmacklem NFSERR_BADHANDLE, 159191783Srmacklem NFSERR_SERVERFAULT, 160191783Srmacklem NFSERR_DELAY, 161191783Srmacklem 0, 162191783Srmacklem}; 163191783Srmacklem 164191783Srmacklemstatic short nfsv3err_access[] = { 165191783Srmacklem NFSERR_IO, 166191783Srmacklem NFSERR_IO, 167191783Srmacklem NFSERR_STALE, 168191783Srmacklem NFSERR_BADHANDLE, 169191783Srmacklem NFSERR_SERVERFAULT, 170191783Srmacklem NFSERR_DELAY, 171191783Srmacklem 0, 172191783Srmacklem}; 173191783Srmacklem 174191783Srmacklemstatic short nfsv3err_readlink[] = { 175191783Srmacklem NFSERR_IO, 176191783Srmacklem NFSERR_IO, 177191783Srmacklem NFSERR_ACCES, 178191783Srmacklem NFSERR_INVAL, 179191783Srmacklem NFSERR_STALE, 180191783Srmacklem NFSERR_BADHANDLE, 181191783Srmacklem NFSERR_NOTSUPP, 182191783Srmacklem NFSERR_SERVERFAULT, 183191783Srmacklem NFSERR_DELAY, 184191783Srmacklem 0, 185191783Srmacklem}; 186191783Srmacklem 187191783Srmacklemstatic short nfsv3err_read[] = { 188191783Srmacklem NFSERR_IO, 189191783Srmacklem NFSERR_IO, 190191783Srmacklem NFSERR_NXIO, 191191783Srmacklem NFSERR_ACCES, 192191783Srmacklem NFSERR_INVAL, 193191783Srmacklem NFSERR_STALE, 194191783Srmacklem NFSERR_BADHANDLE, 195191783Srmacklem NFSERR_SERVERFAULT, 196191783Srmacklem NFSERR_DELAY, 197191783Srmacklem 0, 198191783Srmacklem}; 199191783Srmacklem 200191783Srmacklemstatic short nfsv3err_write[] = { 201191783Srmacklem NFSERR_IO, 202191783Srmacklem NFSERR_IO, 203191783Srmacklem NFSERR_ACCES, 204191783Srmacklem NFSERR_NOSPC, 205191783Srmacklem NFSERR_INVAL, 206191783Srmacklem NFSERR_FBIG, 207191783Srmacklem NFSERR_ROFS, 208191783Srmacklem NFSERR_DQUOT, 209191783Srmacklem NFSERR_STALE, 210191783Srmacklem NFSERR_BADHANDLE, 211191783Srmacklem NFSERR_SERVERFAULT, 212191783Srmacklem NFSERR_DELAY, 213191783Srmacklem 0, 214191783Srmacklem}; 215191783Srmacklem 216191783Srmacklemstatic short nfsv3err_create[] = { 217191783Srmacklem NFSERR_IO, 218191783Srmacklem NFSERR_EXIST, 219191783Srmacklem NFSERR_NAMETOL, 220191783Srmacklem NFSERR_ACCES, 221191783Srmacklem NFSERR_IO, 222191783Srmacklem NFSERR_NOTDIR, 223191783Srmacklem NFSERR_NOSPC, 224191783Srmacklem NFSERR_ROFS, 225191783Srmacklem NFSERR_DQUOT, 226191783Srmacklem NFSERR_STALE, 227191783Srmacklem NFSERR_BADHANDLE, 228191783Srmacklem NFSERR_NOTSUPP, 229191783Srmacklem NFSERR_SERVERFAULT, 230191783Srmacklem NFSERR_DELAY, 231191783Srmacklem 0, 232191783Srmacklem}; 233191783Srmacklem 234191783Srmacklemstatic short nfsv3err_mkdir[] = { 235191783Srmacklem NFSERR_IO, 236191783Srmacklem NFSERR_EXIST, 237191783Srmacklem NFSERR_ACCES, 238191783Srmacklem NFSERR_NAMETOL, 239191783Srmacklem NFSERR_IO, 240191783Srmacklem NFSERR_NOTDIR, 241191783Srmacklem NFSERR_NOSPC, 242191783Srmacklem NFSERR_ROFS, 243191783Srmacklem NFSERR_DQUOT, 244191783Srmacklem NFSERR_STALE, 245191783Srmacklem NFSERR_BADHANDLE, 246191783Srmacklem NFSERR_NOTSUPP, 247191783Srmacklem NFSERR_SERVERFAULT, 248191783Srmacklem NFSERR_DELAY, 249191783Srmacklem 0, 250191783Srmacklem}; 251191783Srmacklem 252191783Srmacklemstatic short nfsv3err_symlink[] = { 253191783Srmacklem NFSERR_IO, 254191783Srmacklem NFSERR_ACCES, 255191783Srmacklem NFSERR_EXIST, 256191783Srmacklem NFSERR_NAMETOL, 257191783Srmacklem NFSERR_NOSPC, 258191783Srmacklem NFSERR_IO, 259191783Srmacklem NFSERR_NOTDIR, 260191783Srmacklem NFSERR_ROFS, 261191783Srmacklem NFSERR_DQUOT, 262191783Srmacklem NFSERR_STALE, 263191783Srmacklem NFSERR_BADHANDLE, 264191783Srmacklem NFSERR_NOTSUPP, 265191783Srmacklem NFSERR_SERVERFAULT, 266191783Srmacklem NFSERR_DELAY, 267191783Srmacklem 0, 268191783Srmacklem}; 269191783Srmacklem 270191783Srmacklemstatic short nfsv3err_mknod[] = { 271191783Srmacklem NFSERR_IO, 272191783Srmacklem NFSERR_ACCES, 273191783Srmacklem NFSERR_EXIST, 274191783Srmacklem NFSERR_NAMETOL, 275191783Srmacklem NFSERR_NOSPC, 276191783Srmacklem NFSERR_IO, 277191783Srmacklem NFSERR_NOTDIR, 278191783Srmacklem NFSERR_ROFS, 279191783Srmacklem NFSERR_DQUOT, 280191783Srmacklem NFSERR_STALE, 281191783Srmacklem NFSERR_BADHANDLE, 282191783Srmacklem NFSERR_NOTSUPP, 283191783Srmacklem NFSERR_SERVERFAULT, 284191783Srmacklem NFSERR_DELAY, 285191783Srmacklem NFSERR_BADTYPE, 286191783Srmacklem 0, 287191783Srmacklem}; 288191783Srmacklem 289191783Srmacklemstatic short nfsv3err_remove[] = { 290191783Srmacklem NFSERR_IO, 291191783Srmacklem NFSERR_NOENT, 292191783Srmacklem NFSERR_ACCES, 293191783Srmacklem NFSERR_NAMETOL, 294191783Srmacklem NFSERR_IO, 295191783Srmacklem NFSERR_NOTDIR, 296191783Srmacklem NFSERR_ROFS, 297191783Srmacklem NFSERR_STALE, 298191783Srmacklem NFSERR_BADHANDLE, 299191783Srmacklem NFSERR_SERVERFAULT, 300191783Srmacklem NFSERR_DELAY, 301191783Srmacklem 0, 302191783Srmacklem}; 303191783Srmacklem 304191783Srmacklemstatic short nfsv3err_rmdir[] = { 305191783Srmacklem NFSERR_IO, 306191783Srmacklem NFSERR_NOENT, 307191783Srmacklem NFSERR_ACCES, 308191783Srmacklem NFSERR_NOTDIR, 309191783Srmacklem NFSERR_NAMETOL, 310191783Srmacklem NFSERR_IO, 311191783Srmacklem NFSERR_EXIST, 312191783Srmacklem NFSERR_INVAL, 313191783Srmacklem NFSERR_ROFS, 314191783Srmacklem NFSERR_NOTEMPTY, 315191783Srmacklem NFSERR_STALE, 316191783Srmacklem NFSERR_BADHANDLE, 317191783Srmacklem NFSERR_NOTSUPP, 318191783Srmacklem NFSERR_SERVERFAULT, 319191783Srmacklem NFSERR_DELAY, 320191783Srmacklem 0, 321191783Srmacklem}; 322191783Srmacklem 323191783Srmacklemstatic short nfsv3err_rename[] = { 324191783Srmacklem NFSERR_IO, 325191783Srmacklem NFSERR_NOENT, 326191783Srmacklem NFSERR_ACCES, 327191783Srmacklem NFSERR_EXIST, 328191783Srmacklem NFSERR_NAMETOL, 329191783Srmacklem NFSERR_XDEV, 330191783Srmacklem NFSERR_IO, 331191783Srmacklem NFSERR_NOTDIR, 332191783Srmacklem NFSERR_ISDIR, 333191783Srmacklem NFSERR_INVAL, 334191783Srmacklem NFSERR_NOSPC, 335191783Srmacklem NFSERR_ROFS, 336191783Srmacklem NFSERR_MLINK, 337191783Srmacklem NFSERR_NOTEMPTY, 338191783Srmacklem NFSERR_DQUOT, 339191783Srmacklem NFSERR_STALE, 340191783Srmacklem NFSERR_BADHANDLE, 341191783Srmacklem NFSERR_NOTSUPP, 342191783Srmacklem NFSERR_SERVERFAULT, 343191783Srmacklem NFSERR_DELAY, 344191783Srmacklem 0, 345191783Srmacklem}; 346191783Srmacklem 347191783Srmacklemstatic short nfsv3err_link[] = { 348191783Srmacklem NFSERR_IO, 349191783Srmacklem NFSERR_ACCES, 350191783Srmacklem NFSERR_EXIST, 351191783Srmacklem NFSERR_NAMETOL, 352191783Srmacklem NFSERR_IO, 353191783Srmacklem NFSERR_XDEV, 354191783Srmacklem NFSERR_NOTDIR, 355191783Srmacklem NFSERR_INVAL, 356191783Srmacklem NFSERR_NOSPC, 357191783Srmacklem NFSERR_ROFS, 358191783Srmacklem NFSERR_MLINK, 359191783Srmacklem NFSERR_DQUOT, 360191783Srmacklem NFSERR_STALE, 361191783Srmacklem NFSERR_BADHANDLE, 362191783Srmacklem NFSERR_NOTSUPP, 363191783Srmacklem NFSERR_SERVERFAULT, 364191783Srmacklem NFSERR_DELAY, 365191783Srmacklem 0, 366191783Srmacklem}; 367191783Srmacklem 368191783Srmacklemstatic short nfsv3err_readdir[] = { 369191783Srmacklem NFSERR_IO, 370191783Srmacklem NFSERR_ACCES, 371191783Srmacklem NFSERR_NOTDIR, 372191783Srmacklem NFSERR_IO, 373191783Srmacklem NFSERR_STALE, 374191783Srmacklem NFSERR_BADHANDLE, 375191783Srmacklem NFSERR_BAD_COOKIE, 376191783Srmacklem NFSERR_TOOSMALL, 377191783Srmacklem NFSERR_SERVERFAULT, 378191783Srmacklem NFSERR_DELAY, 379191783Srmacklem 0, 380191783Srmacklem}; 381191783Srmacklem 382191783Srmacklemstatic short nfsv3err_readdirplus[] = { 383191783Srmacklem NFSERR_IO, 384191783Srmacklem NFSERR_ACCES, 385191783Srmacklem NFSERR_NOTDIR, 386191783Srmacklem NFSERR_IO, 387191783Srmacklem NFSERR_STALE, 388191783Srmacklem NFSERR_BADHANDLE, 389191783Srmacklem NFSERR_BAD_COOKIE, 390191783Srmacklem NFSERR_NOTSUPP, 391191783Srmacklem NFSERR_TOOSMALL, 392191783Srmacklem NFSERR_SERVERFAULT, 393191783Srmacklem NFSERR_DELAY, 394191783Srmacklem 0, 395191783Srmacklem}; 396191783Srmacklem 397191783Srmacklemstatic short nfsv3err_fsstat[] = { 398191783Srmacklem NFSERR_IO, 399191783Srmacklem NFSERR_IO, 400191783Srmacklem NFSERR_STALE, 401191783Srmacklem NFSERR_BADHANDLE, 402191783Srmacklem NFSERR_SERVERFAULT, 403191783Srmacklem NFSERR_DELAY, 404191783Srmacklem 0, 405191783Srmacklem}; 406191783Srmacklem 407191783Srmacklemstatic short nfsv3err_fsinfo[] = { 408191783Srmacklem NFSERR_STALE, 409191783Srmacklem NFSERR_STALE, 410191783Srmacklem NFSERR_BADHANDLE, 411191783Srmacklem NFSERR_SERVERFAULT, 412191783Srmacklem NFSERR_DELAY, 413191783Srmacklem 0, 414191783Srmacklem}; 415191783Srmacklem 416191783Srmacklemstatic short nfsv3err_pathconf[] = { 417191783Srmacklem NFSERR_STALE, 418191783Srmacklem NFSERR_STALE, 419191783Srmacklem NFSERR_BADHANDLE, 420191783Srmacklem NFSERR_SERVERFAULT, 421191783Srmacklem NFSERR_DELAY, 422191783Srmacklem 0, 423191783Srmacklem}; 424191783Srmacklem 425191783Srmacklemstatic short nfsv3err_commit[] = { 426191783Srmacklem NFSERR_IO, 427191783Srmacklem NFSERR_IO, 428191783Srmacklem NFSERR_STALE, 429191783Srmacklem NFSERR_BADHANDLE, 430191783Srmacklem NFSERR_SERVERFAULT, 431191783Srmacklem NFSERR_DELAY, 432191783Srmacklem 0, 433191783Srmacklem}; 434191783Srmacklem 435191783Srmacklemstatic short *nfsrv_v3errmap[] = { 436191783Srmacklem nfsv3err_null, 437191783Srmacklem nfsv3err_getattr, 438191783Srmacklem nfsv3err_setattr, 439191783Srmacklem nfsv3err_lookup, 440191783Srmacklem nfsv3err_access, 441191783Srmacklem nfsv3err_readlink, 442191783Srmacklem nfsv3err_read, 443191783Srmacklem nfsv3err_write, 444191783Srmacklem nfsv3err_create, 445191783Srmacklem nfsv3err_mkdir, 446191783Srmacklem nfsv3err_symlink, 447191783Srmacklem nfsv3err_mknod, 448191783Srmacklem nfsv3err_remove, 449191783Srmacklem nfsv3err_rmdir, 450191783Srmacklem nfsv3err_rename, 451191783Srmacklem nfsv3err_link, 452191783Srmacklem nfsv3err_readdir, 453191783Srmacklem nfsv3err_readdirplus, 454191783Srmacklem nfsv3err_fsstat, 455191783Srmacklem nfsv3err_fsinfo, 456191783Srmacklem nfsv3err_pathconf, 457191783Srmacklem nfsv3err_commit, 458191783Srmacklem}; 459191783Srmacklem 460191783Srmacklem/* 461191783Srmacklem * And the same for V4. 462191783Srmacklem */ 463191783Srmacklemstatic short nfsv4err_null[] = { 464191783Srmacklem 0, 465191783Srmacklem 0, 466191783Srmacklem}; 467191783Srmacklem 468191783Srmacklemstatic short nfsv4err_access[] = { 469191783Srmacklem NFSERR_IO, 470191783Srmacklem NFSERR_ACCES, 471191783Srmacklem NFSERR_BADHANDLE, 472191783Srmacklem NFSERR_BADXDR, 473191783Srmacklem NFSERR_DELAY, 474191783Srmacklem NFSERR_FHEXPIRED, 475191783Srmacklem NFSERR_INVAL, 476191783Srmacklem NFSERR_IO, 477191783Srmacklem NFSERR_MOVED, 478191783Srmacklem NFSERR_NOFILEHANDLE, 479191783Srmacklem NFSERR_RESOURCE, 480191783Srmacklem NFSERR_SERVERFAULT, 481191783Srmacklem NFSERR_STALE, 482191783Srmacklem 0, 483191783Srmacklem}; 484191783Srmacklem 485191783Srmacklemstatic short nfsv4err_close[] = { 486191783Srmacklem NFSERR_EXPIRED, 487191783Srmacklem NFSERR_ADMINREVOKED, 488191783Srmacklem NFSERR_BADHANDLE, 489191783Srmacklem NFSERR_BADSEQID, 490191783Srmacklem NFSERR_BADSTATEID, 491191783Srmacklem NFSERR_BADXDR, 492191783Srmacklem NFSERR_DELAY, 493191783Srmacklem NFSERR_EXPIRED, 494191783Srmacklem NFSERR_FHEXPIRED, 495191783Srmacklem NFSERR_INVAL, 496191783Srmacklem NFSERR_ISDIR, 497191783Srmacklem NFSERR_LEASEMOVED, 498191783Srmacklem NFSERR_LOCKSHELD, 499191783Srmacklem NFSERR_MOVED, 500191783Srmacklem NFSERR_NOFILEHANDLE, 501191783Srmacklem NFSERR_OLDSTATEID, 502191783Srmacklem NFSERR_RESOURCE, 503191783Srmacklem NFSERR_SERVERFAULT, 504191783Srmacklem NFSERR_STALE, 505191783Srmacklem NFSERR_STALESTATEID, 506191783Srmacklem 0, 507191783Srmacklem}; 508191783Srmacklem 509191783Srmacklemstatic short nfsv4err_commit[] = { 510191783Srmacklem NFSERR_IO, 511191783Srmacklem NFSERR_ACCES, 512191783Srmacklem NFSERR_BADHANDLE, 513191783Srmacklem NFSERR_BADXDR, 514191783Srmacklem NFSERR_FHEXPIRED, 515191783Srmacklem NFSERR_INVAL, 516191783Srmacklem NFSERR_IO, 517191783Srmacklem NFSERR_ISDIR, 518191783Srmacklem NFSERR_MOVED, 519191783Srmacklem NFSERR_NOFILEHANDLE, 520191783Srmacklem NFSERR_RESOURCE, 521191783Srmacklem NFSERR_ROFS, 522191783Srmacklem NFSERR_SERVERFAULT, 523191783Srmacklem NFSERR_STALE, 524191783Srmacklem 0, 525191783Srmacklem}; 526191783Srmacklem 527191783Srmacklemstatic short nfsv4err_create[] = { 528191783Srmacklem NFSERR_IO, 529191783Srmacklem NFSERR_ACCES, 530191783Srmacklem NFSERR_ATTRNOTSUPP, 531191783Srmacklem NFSERR_BADCHAR, 532191783Srmacklem NFSERR_BADHANDLE, 533191783Srmacklem NFSERR_BADNAME, 534191783Srmacklem NFSERR_BADOWNER, 535191783Srmacklem NFSERR_BADTYPE, 536191783Srmacklem NFSERR_BADXDR, 537191783Srmacklem NFSERR_DELAY, 538191783Srmacklem NFSERR_DQUOT, 539191783Srmacklem NFSERR_EXIST, 540191783Srmacklem NFSERR_FHEXPIRED, 541191783Srmacklem NFSERR_INVAL, 542191783Srmacklem NFSERR_IO, 543191783Srmacklem NFSERR_MOVED, 544191783Srmacklem NFSERR_NAMETOL, 545191783Srmacklem NFSERR_NOFILEHANDLE, 546191783Srmacklem NFSERR_NOSPC, 547191783Srmacklem NFSERR_NOTDIR, 548191783Srmacklem NFSERR_PERM, 549191783Srmacklem NFSERR_RESOURCE, 550191783Srmacklem NFSERR_ROFS, 551191783Srmacklem NFSERR_SERVERFAULT, 552191783Srmacklem NFSERR_STALE, 553191783Srmacklem 0, 554191783Srmacklem}; 555191783Srmacklem 556191783Srmacklemstatic short nfsv4err_delegpurge[] = { 557191783Srmacklem NFSERR_SERVERFAULT, 558191783Srmacklem NFSERR_BADXDR, 559191783Srmacklem NFSERR_NOTSUPP, 560191783Srmacklem NFSERR_LEASEMOVED, 561191783Srmacklem NFSERR_MOVED, 562191783Srmacklem NFSERR_RESOURCE, 563191783Srmacklem NFSERR_SERVERFAULT, 564191783Srmacklem NFSERR_STALECLIENTID, 565191783Srmacklem 0, 566191783Srmacklem}; 567191783Srmacklem 568191783Srmacklemstatic short nfsv4err_delegreturn[] = { 569191783Srmacklem NFSERR_SERVERFAULT, 570191783Srmacklem NFSERR_ADMINREVOKED, 571191783Srmacklem NFSERR_BADSTATEID, 572191783Srmacklem NFSERR_BADXDR, 573191783Srmacklem NFSERR_EXPIRED, 574191783Srmacklem NFSERR_INVAL, 575191783Srmacklem NFSERR_LEASEMOVED, 576191783Srmacklem NFSERR_MOVED, 577191783Srmacklem NFSERR_NOFILEHANDLE, 578191783Srmacklem NFSERR_NOTSUPP, 579191783Srmacklem NFSERR_OLDSTATEID, 580191783Srmacklem NFSERR_RESOURCE, 581191783Srmacklem NFSERR_SERVERFAULT, 582191783Srmacklem NFSERR_STALE, 583191783Srmacklem NFSERR_STALESTATEID, 584191783Srmacklem 0, 585191783Srmacklem}; 586191783Srmacklem 587191783Srmacklemstatic short nfsv4err_getattr[] = { 588191783Srmacklem NFSERR_IO, 589191783Srmacklem NFSERR_ACCES, 590191783Srmacklem NFSERR_BADHANDLE, 591191783Srmacklem NFSERR_BADXDR, 592191783Srmacklem NFSERR_DELAY, 593191783Srmacklem NFSERR_FHEXPIRED, 594191783Srmacklem NFSERR_INVAL, 595191783Srmacklem NFSERR_IO, 596191783Srmacklem NFSERR_MOVED, 597191783Srmacklem NFSERR_NOFILEHANDLE, 598191783Srmacklem NFSERR_RESOURCE, 599191783Srmacklem NFSERR_SERVERFAULT, 600191783Srmacklem NFSERR_STALE, 601191783Srmacklem 0, 602191783Srmacklem}; 603191783Srmacklem 604191783Srmacklemstatic short nfsv4err_getfh[] = { 605191783Srmacklem NFSERR_BADHANDLE, 606191783Srmacklem NFSERR_BADHANDLE, 607191783Srmacklem NFSERR_FHEXPIRED, 608191783Srmacklem NFSERR_MOVED, 609191783Srmacklem NFSERR_NOFILEHANDLE, 610191783Srmacklem NFSERR_RESOURCE, 611191783Srmacklem NFSERR_SERVERFAULT, 612191783Srmacklem NFSERR_STALE, 613191783Srmacklem 0, 614191783Srmacklem}; 615191783Srmacklem 616191783Srmacklemstatic short nfsv4err_link[] = { 617191783Srmacklem NFSERR_IO, 618191783Srmacklem NFSERR_ACCES, 619191783Srmacklem NFSERR_BADCHAR, 620191783Srmacklem NFSERR_BADHANDLE, 621191783Srmacklem NFSERR_BADNAME, 622191783Srmacklem NFSERR_BADXDR, 623191783Srmacklem NFSERR_DELAY, 624191783Srmacklem NFSERR_DQUOT, 625191783Srmacklem NFSERR_EXIST, 626191783Srmacklem NFSERR_FHEXPIRED, 627191783Srmacklem NFSERR_FILEOPEN, 628191783Srmacklem NFSERR_INVAL, 629191783Srmacklem NFSERR_IO, 630191783Srmacklem NFSERR_ISDIR, 631191783Srmacklem NFSERR_MLINK, 632191783Srmacklem NFSERR_MOVED, 633191783Srmacklem NFSERR_NAMETOL, 634191783Srmacklem NFSERR_NOENT, 635191783Srmacklem NFSERR_NOFILEHANDLE, 636191783Srmacklem NFSERR_NOSPC, 637191783Srmacklem NFSERR_NOTDIR, 638191783Srmacklem NFSERR_NOTSUPP, 639191783Srmacklem NFSERR_RESOURCE, 640191783Srmacklem NFSERR_ROFS, 641191783Srmacklem NFSERR_SERVERFAULT, 642191783Srmacklem NFSERR_STALE, 643191783Srmacklem NFSERR_WRONGSEC, 644191783Srmacklem NFSERR_XDEV, 645191783Srmacklem 0, 646191783Srmacklem}; 647191783Srmacklem 648191783Srmacklemstatic short nfsv4err_lock[] = { 649191783Srmacklem NFSERR_SERVERFAULT, 650191783Srmacklem NFSERR_ACCES, 651191783Srmacklem NFSERR_ADMINREVOKED, 652191783Srmacklem NFSERR_BADHANDLE, 653191783Srmacklem NFSERR_BADRANGE, 654191783Srmacklem NFSERR_BADSEQID, 655191783Srmacklem NFSERR_BADSTATEID, 656191783Srmacklem NFSERR_BADXDR, 657191783Srmacklem NFSERR_DEADLOCK, 658191783Srmacklem NFSERR_DELAY, 659191783Srmacklem NFSERR_DENIED, 660191783Srmacklem NFSERR_EXPIRED, 661191783Srmacklem NFSERR_FHEXPIRED, 662191783Srmacklem NFSERR_GRACE, 663191783Srmacklem NFSERR_INVAL, 664191783Srmacklem NFSERR_ISDIR, 665191783Srmacklem NFSERR_LEASEMOVED, 666191783Srmacklem NFSERR_LOCKNOTSUPP, 667191783Srmacklem NFSERR_LOCKRANGE, 668191783Srmacklem NFSERR_MOVED, 669191783Srmacklem NFSERR_NOFILEHANDLE, 670191783Srmacklem NFSERR_NOGRACE, 671191783Srmacklem NFSERR_OLDSTATEID, 672191783Srmacklem NFSERR_OPENMODE, 673191783Srmacklem NFSERR_RECLAIMBAD, 674191783Srmacklem NFSERR_RECLAIMCONFLICT, 675191783Srmacklem NFSERR_RESOURCE, 676191783Srmacklem NFSERR_SERVERFAULT, 677191783Srmacklem NFSERR_STALE, 678191783Srmacklem NFSERR_STALECLIENTID, 679191783Srmacklem NFSERR_STALESTATEID, 680191783Srmacklem 0, 681191783Srmacklem}; 682191783Srmacklem 683191783Srmacklemstatic short nfsv4err_lockt[] = { 684191783Srmacklem NFSERR_SERVERFAULT, 685191783Srmacklem NFSERR_ACCES, 686191783Srmacklem NFSERR_BADHANDLE, 687191783Srmacklem NFSERR_BADRANGE, 688191783Srmacklem NFSERR_BADXDR, 689191783Srmacklem NFSERR_DELAY, 690191783Srmacklem NFSERR_DENIED, 691191783Srmacklem NFSERR_FHEXPIRED, 692191783Srmacklem NFSERR_GRACE, 693191783Srmacklem NFSERR_INVAL, 694191783Srmacklem NFSERR_ISDIR, 695191783Srmacklem NFSERR_LEASEMOVED, 696191783Srmacklem NFSERR_LOCKRANGE, 697191783Srmacklem NFSERR_MOVED, 698191783Srmacklem NFSERR_NOFILEHANDLE, 699191783Srmacklem NFSERR_RESOURCE, 700191783Srmacklem NFSERR_SERVERFAULT, 701191783Srmacklem NFSERR_STALE, 702191783Srmacklem NFSERR_STALECLIENTID, 703191783Srmacklem 0, 704191783Srmacklem}; 705191783Srmacklem 706191783Srmacklemstatic short nfsv4err_locku[] = { 707191783Srmacklem NFSERR_SERVERFAULT, 708191783Srmacklem NFSERR_ACCES, 709191783Srmacklem NFSERR_ADMINREVOKED, 710191783Srmacklem NFSERR_BADHANDLE, 711191783Srmacklem NFSERR_BADRANGE, 712191783Srmacklem NFSERR_BADSEQID, 713191783Srmacklem NFSERR_BADSTATEID, 714191783Srmacklem NFSERR_BADXDR, 715191783Srmacklem NFSERR_EXPIRED, 716191783Srmacklem NFSERR_FHEXPIRED, 717191783Srmacklem NFSERR_GRACE, 718191783Srmacklem NFSERR_INVAL, 719191783Srmacklem NFSERR_ISDIR, 720191783Srmacklem NFSERR_LEASEMOVED, 721191783Srmacklem NFSERR_LOCKRANGE, 722191783Srmacklem NFSERR_MOVED, 723191783Srmacklem NFSERR_NOFILEHANDLE, 724191783Srmacklem NFSERR_OLDSTATEID, 725191783Srmacklem NFSERR_RESOURCE, 726191783Srmacklem NFSERR_SERVERFAULT, 727191783Srmacklem NFSERR_STALE, 728191783Srmacklem NFSERR_STALESTATEID, 729191783Srmacklem 0, 730191783Srmacklem}; 731191783Srmacklem 732191783Srmacklemstatic short nfsv4err_lookup[] = { 733191783Srmacklem NFSERR_IO, 734191783Srmacklem NFSERR_ACCES, 735191783Srmacklem NFSERR_BADCHAR, 736191783Srmacklem NFSERR_BADHANDLE, 737191783Srmacklem NFSERR_BADNAME, 738191783Srmacklem NFSERR_BADXDR, 739191783Srmacklem NFSERR_FHEXPIRED, 740191783Srmacklem NFSERR_INVAL, 741191783Srmacklem NFSERR_IO, 742191783Srmacklem NFSERR_MOVED, 743191783Srmacklem NFSERR_NAMETOL, 744191783Srmacklem NFSERR_NOENT, 745191783Srmacklem NFSERR_NOFILEHANDLE, 746191783Srmacklem NFSERR_NOTDIR, 747191783Srmacklem NFSERR_RESOURCE, 748191783Srmacklem NFSERR_SERVERFAULT, 749191783Srmacklem NFSERR_STALE, 750191783Srmacklem NFSERR_SYMLINK, 751191783Srmacklem NFSERR_WRONGSEC, 752191783Srmacklem 0, 753191783Srmacklem}; 754191783Srmacklem 755191783Srmacklemstatic short nfsv4err_lookupp[] = { 756191783Srmacklem NFSERR_IO, 757191783Srmacklem NFSERR_ACCES, 758191783Srmacklem NFSERR_BADHANDLE, 759191783Srmacklem NFSERR_FHEXPIRED, 760191783Srmacklem NFSERR_IO, 761191783Srmacklem NFSERR_MOVED, 762191783Srmacklem NFSERR_NOENT, 763191783Srmacklem NFSERR_NOFILEHANDLE, 764191783Srmacklem NFSERR_NOTDIR, 765191783Srmacklem NFSERR_RESOURCE, 766191783Srmacklem NFSERR_SERVERFAULT, 767191783Srmacklem NFSERR_STALE, 768191783Srmacklem 0, 769191783Srmacklem}; 770191783Srmacklem 771191783Srmacklemstatic short nfsv4err_nverify[] = { 772191783Srmacklem NFSERR_IO, 773191783Srmacklem NFSERR_ACCES, 774191783Srmacklem NFSERR_ATTRNOTSUPP, 775191783Srmacklem NFSERR_BADCHAR, 776191783Srmacklem NFSERR_BADHANDLE, 777191783Srmacklem NFSERR_BADXDR, 778191783Srmacklem NFSERR_DELAY, 779191783Srmacklem NFSERR_FHEXPIRED, 780191783Srmacklem NFSERR_INVAL, 781191783Srmacklem NFSERR_IO, 782191783Srmacklem NFSERR_MOVED, 783191783Srmacklem NFSERR_NOFILEHANDLE, 784191783Srmacklem NFSERR_RESOURCE, 785191783Srmacklem NFSERR_SAME, 786191783Srmacklem NFSERR_SERVERFAULT, 787191783Srmacklem NFSERR_STALE, 788191783Srmacklem 0, 789191783Srmacklem}; 790191783Srmacklem 791191783Srmacklemstatic short nfsv4err_open[] = { 792191783Srmacklem NFSERR_IO, 793191783Srmacklem NFSERR_ACCES, 794191783Srmacklem NFSERR_ADMINREVOKED, 795191783Srmacklem NFSERR_ATTRNOTSUPP, 796191783Srmacklem NFSERR_BADCHAR, 797191783Srmacklem NFSERR_BADHANDLE, 798191783Srmacklem NFSERR_BADNAME, 799191783Srmacklem NFSERR_BADOWNER, 800191783Srmacklem NFSERR_BADSEQID, 801191783Srmacklem NFSERR_BADXDR, 802191783Srmacklem NFSERR_DELAY, 803191783Srmacklem NFSERR_DQUOT, 804191783Srmacklem NFSERR_EXIST, 805191783Srmacklem NFSERR_EXPIRED, 806191783Srmacklem NFSERR_FHEXPIRED, 807191783Srmacklem NFSERR_GRACE, 808191783Srmacklem NFSERR_IO, 809191783Srmacklem NFSERR_INVAL, 810191783Srmacklem NFSERR_ISDIR, 811191783Srmacklem NFSERR_LEASEMOVED, 812191783Srmacklem NFSERR_MOVED, 813191783Srmacklem NFSERR_NAMETOL, 814191783Srmacklem NFSERR_NOENT, 815191783Srmacklem NFSERR_NOFILEHANDLE, 816191783Srmacklem NFSERR_NOGRACE, 817191783Srmacklem NFSERR_NOSPC, 818191783Srmacklem NFSERR_NOTDIR, 819191783Srmacklem NFSERR_NOTSUPP, 820191783Srmacklem NFSERR_PERM, 821191783Srmacklem NFSERR_RECLAIMBAD, 822191783Srmacklem NFSERR_RECLAIMCONFLICT, 823191783Srmacklem NFSERR_RESOURCE, 824191783Srmacklem NFSERR_ROFS, 825191783Srmacklem NFSERR_SERVERFAULT, 826191783Srmacklem NFSERR_SHAREDENIED, 827191783Srmacklem NFSERR_STALE, 828191783Srmacklem NFSERR_STALECLIENTID, 829191783Srmacklem NFSERR_SYMLINK, 830191783Srmacklem NFSERR_WRONGSEC, 831191783Srmacklem 0, 832191783Srmacklem}; 833191783Srmacklem 834191783Srmacklemstatic short nfsv4err_openattr[] = { 835191783Srmacklem NFSERR_IO, 836191783Srmacklem NFSERR_ACCES, 837191783Srmacklem NFSERR_BADHANDLE, 838191783Srmacklem NFSERR_BADXDR, 839191783Srmacklem NFSERR_DELAY, 840191783Srmacklem NFSERR_DQUOT, 841191783Srmacklem NFSERR_FHEXPIRED, 842191783Srmacklem NFSERR_IO, 843191783Srmacklem NFSERR_MOVED, 844191783Srmacklem NFSERR_NOENT, 845191783Srmacklem NFSERR_NOFILEHANDLE, 846191783Srmacklem NFSERR_NOSPC, 847191783Srmacklem NFSERR_NOTSUPP, 848191783Srmacklem NFSERR_RESOURCE, 849191783Srmacklem NFSERR_ROFS, 850191783Srmacklem NFSERR_SERVERFAULT, 851191783Srmacklem NFSERR_STALE, 852191783Srmacklem 0, 853191783Srmacklem}; 854191783Srmacklem 855191783Srmacklemstatic short nfsv4err_openconfirm[] = { 856191783Srmacklem NFSERR_SERVERFAULT, 857191783Srmacklem NFSERR_ADMINREVOKED, 858191783Srmacklem NFSERR_BADHANDLE, 859191783Srmacklem NFSERR_BADSEQID, 860191783Srmacklem NFSERR_BADSTATEID, 861191783Srmacklem NFSERR_BADXDR, 862191783Srmacklem NFSERR_EXPIRED, 863191783Srmacklem NFSERR_FHEXPIRED, 864191783Srmacklem NFSERR_INVAL, 865191783Srmacklem NFSERR_ISDIR, 866191783Srmacklem NFSERR_MOVED, 867191783Srmacklem NFSERR_NOFILEHANDLE, 868191783Srmacklem NFSERR_OLDSTATEID, 869191783Srmacklem NFSERR_RESOURCE, 870191783Srmacklem NFSERR_SERVERFAULT, 871191783Srmacklem NFSERR_STALE, 872191783Srmacklem NFSERR_STALESTATEID, 873191783Srmacklem 0, 874191783Srmacklem}; 875191783Srmacklem 876191783Srmacklemstatic short nfsv4err_opendowngrade[] = { 877191783Srmacklem NFSERR_SERVERFAULT, 878191783Srmacklem NFSERR_ADMINREVOKED, 879191783Srmacklem NFSERR_BADHANDLE, 880191783Srmacklem NFSERR_BADSEQID, 881191783Srmacklem NFSERR_BADSTATEID, 882191783Srmacklem NFSERR_BADXDR, 883191783Srmacklem NFSERR_EXPIRED, 884191783Srmacklem NFSERR_FHEXPIRED, 885191783Srmacklem NFSERR_INVAL, 886191783Srmacklem NFSERR_MOVED, 887191783Srmacklem NFSERR_NOFILEHANDLE, 888191783Srmacklem NFSERR_OLDSTATEID, 889191783Srmacklem NFSERR_RESOURCE, 890191783Srmacklem NFSERR_SERVERFAULT, 891191783Srmacklem NFSERR_STALE, 892191783Srmacklem NFSERR_STALESTATEID, 893191783Srmacklem 0, 894191783Srmacklem}; 895191783Srmacklem 896191783Srmacklemstatic short nfsv4err_putfh[] = { 897191783Srmacklem NFSERR_SERVERFAULT, 898191783Srmacklem NFSERR_BADHANDLE, 899191783Srmacklem NFSERR_BADXDR, 900191783Srmacklem NFSERR_FHEXPIRED, 901191783Srmacklem NFSERR_MOVED, 902191783Srmacklem NFSERR_RESOURCE, 903191783Srmacklem NFSERR_SERVERFAULT, 904191783Srmacklem NFSERR_STALE, 905191783Srmacklem NFSERR_WRONGSEC, 906191783Srmacklem 0, 907191783Srmacklem}; 908191783Srmacklem 909191783Srmacklemstatic short nfsv4err_putpubfh[] = { 910191783Srmacklem NFSERR_SERVERFAULT, 911191783Srmacklem NFSERR_RESOURCE, 912191783Srmacklem NFSERR_SERVERFAULT, 913191783Srmacklem NFSERR_WRONGSEC, 914191783Srmacklem 0, 915191783Srmacklem}; 916191783Srmacklem 917191783Srmacklemstatic short nfsv4err_putrootfh[] = { 918191783Srmacklem NFSERR_SERVERFAULT, 919191783Srmacklem NFSERR_RESOURCE, 920191783Srmacklem NFSERR_SERVERFAULT, 921191783Srmacklem NFSERR_WRONGSEC, 922191783Srmacklem 0, 923191783Srmacklem}; 924191783Srmacklem 925191783Srmacklemstatic short nfsv4err_read[] = { 926191783Srmacklem NFSERR_IO, 927191783Srmacklem NFSERR_ACCES, 928191783Srmacklem NFSERR_ADMINREVOKED, 929191783Srmacklem NFSERR_BADHANDLE, 930191783Srmacklem NFSERR_BADSTATEID, 931191783Srmacklem NFSERR_BADXDR, 932191783Srmacklem NFSERR_DELAY, 933191783Srmacklem NFSERR_EXPIRED, 934191783Srmacklem NFSERR_FHEXPIRED, 935191783Srmacklem NFSERR_GRACE, 936191783Srmacklem NFSERR_IO, 937191783Srmacklem NFSERR_INVAL, 938191783Srmacklem NFSERR_ISDIR, 939191783Srmacklem NFSERR_LEASEMOVED, 940191783Srmacklem NFSERR_LOCKED, 941191783Srmacklem NFSERR_MOVED, 942191783Srmacklem NFSERR_NOFILEHANDLE, 943191783Srmacklem NFSERR_NXIO, 944191783Srmacklem NFSERR_OLDSTATEID, 945191783Srmacklem NFSERR_OPENMODE, 946191783Srmacklem NFSERR_RESOURCE, 947191783Srmacklem NFSERR_SERVERFAULT, 948191783Srmacklem NFSERR_STALE, 949191783Srmacklem NFSERR_STALESTATEID, 950191783Srmacklem 0, 951191783Srmacklem}; 952191783Srmacklem 953191783Srmacklemstatic short nfsv4err_readdir[] = { 954191783Srmacklem NFSERR_IO, 955191783Srmacklem NFSERR_ACCES, 956191783Srmacklem NFSERR_BADHANDLE, 957191783Srmacklem NFSERR_BAD_COOKIE, 958191783Srmacklem NFSERR_BADXDR, 959191783Srmacklem NFSERR_DELAY, 960191783Srmacklem NFSERR_FHEXPIRED, 961191783Srmacklem NFSERR_INVAL, 962191783Srmacklem NFSERR_IO, 963191783Srmacklem NFSERR_MOVED, 964191783Srmacklem NFSERR_NOFILEHANDLE, 965191783Srmacklem NFSERR_NOTDIR, 966191783Srmacklem NFSERR_NOTSAME, 967191783Srmacklem NFSERR_RESOURCE, 968191783Srmacklem NFSERR_SERVERFAULT, 969191783Srmacklem NFSERR_STALE, 970191783Srmacklem NFSERR_TOOSMALL, 971191783Srmacklem 0, 972191783Srmacklem}; 973191783Srmacklem 974191783Srmacklemstatic short nfsv4err_readlink[] = { 975191783Srmacklem NFSERR_IO, 976191783Srmacklem NFSERR_ACCES, 977191783Srmacklem NFSERR_BADHANDLE, 978191783Srmacklem NFSERR_DELAY, 979191783Srmacklem NFSERR_FHEXPIRED, 980191783Srmacklem NFSERR_INVAL, 981191783Srmacklem NFSERR_IO, 982191783Srmacklem NFSERR_ISDIR, 983191783Srmacklem NFSERR_MOVED, 984191783Srmacklem NFSERR_NOFILEHANDLE, 985191783Srmacklem NFSERR_NOTSUPP, 986191783Srmacklem NFSERR_RESOURCE, 987191783Srmacklem NFSERR_SERVERFAULT, 988191783Srmacklem NFSERR_STALE, 989191783Srmacklem 0, 990191783Srmacklem}; 991191783Srmacklem 992191783Srmacklemstatic short nfsv4err_remove[] = { 993191783Srmacklem NFSERR_IO, 994191783Srmacklem NFSERR_ACCES, 995191783Srmacklem NFSERR_BADCHAR, 996191783Srmacklem NFSERR_BADHANDLE, 997191783Srmacklem NFSERR_BADNAME, 998191783Srmacklem NFSERR_BADXDR, 999191783Srmacklem NFSERR_DELAY, 1000191783Srmacklem NFSERR_FHEXPIRED, 1001191783Srmacklem NFSERR_FILEOPEN, 1002191783Srmacklem NFSERR_INVAL, 1003191783Srmacklem NFSERR_IO, 1004191783Srmacklem NFSERR_MOVED, 1005191783Srmacklem NFSERR_NAMETOL, 1006191783Srmacklem NFSERR_NOENT, 1007191783Srmacklem NFSERR_NOFILEHANDLE, 1008191783Srmacklem NFSERR_NOTDIR, 1009191783Srmacklem NFSERR_NOTEMPTY, 1010191783Srmacklem NFSERR_RESOURCE, 1011191783Srmacklem NFSERR_ROFS, 1012191783Srmacklem NFSERR_SERVERFAULT, 1013191783Srmacklem NFSERR_STALE, 1014191783Srmacklem 0, 1015191783Srmacklem}; 1016191783Srmacklem 1017191783Srmacklemstatic short nfsv4err_rename[] = { 1018191783Srmacklem NFSERR_IO, 1019191783Srmacklem NFSERR_ACCES, 1020191783Srmacklem NFSERR_BADCHAR, 1021191783Srmacklem NFSERR_BADHANDLE, 1022191783Srmacklem NFSERR_BADNAME, 1023191783Srmacklem NFSERR_BADXDR, 1024191783Srmacklem NFSERR_DELAY, 1025191783Srmacklem NFSERR_DQUOT, 1026191783Srmacklem NFSERR_EXIST, 1027191783Srmacklem NFSERR_FHEXPIRED, 1028191783Srmacklem NFSERR_FILEOPEN, 1029191783Srmacklem NFSERR_INVAL, 1030191783Srmacklem NFSERR_IO, 1031191783Srmacklem NFSERR_MOVED, 1032191783Srmacklem NFSERR_NAMETOL, 1033191783Srmacklem NFSERR_NOENT, 1034191783Srmacklem NFSERR_NOFILEHANDLE, 1035191783Srmacklem NFSERR_NOSPC, 1036191783Srmacklem NFSERR_NOTDIR, 1037191783Srmacklem NFSERR_NOTEMPTY, 1038191783Srmacklem NFSERR_RESOURCE, 1039191783Srmacklem NFSERR_ROFS, 1040191783Srmacklem NFSERR_SERVERFAULT, 1041191783Srmacklem NFSERR_STALE, 1042191783Srmacklem NFSERR_WRONGSEC, 1043191783Srmacklem NFSERR_XDEV, 1044191783Srmacklem 0, 1045191783Srmacklem}; 1046191783Srmacklem 1047191783Srmacklemstatic short nfsv4err_renew[] = { 1048191783Srmacklem NFSERR_SERVERFAULT, 1049191783Srmacklem NFSERR_ACCES, 1050191783Srmacklem NFSERR_ADMINREVOKED, 1051191783Srmacklem NFSERR_BADXDR, 1052191783Srmacklem NFSERR_CBPATHDOWN, 1053191783Srmacklem NFSERR_EXPIRED, 1054191783Srmacklem NFSERR_LEASEMOVED, 1055191783Srmacklem NFSERR_RESOURCE, 1056191783Srmacklem NFSERR_SERVERFAULT, 1057191783Srmacklem NFSERR_STALECLIENTID, 1058191783Srmacklem 0, 1059191783Srmacklem}; 1060191783Srmacklem 1061191783Srmacklemstatic short nfsv4err_restorefh[] = { 1062191783Srmacklem NFSERR_SERVERFAULT, 1063191783Srmacklem NFSERR_BADHANDLE, 1064191783Srmacklem NFSERR_FHEXPIRED, 1065191783Srmacklem NFSERR_MOVED, 1066191783Srmacklem NFSERR_RESOURCE, 1067191783Srmacklem NFSERR_RESTOREFH, 1068191783Srmacklem NFSERR_SERVERFAULT, 1069191783Srmacklem NFSERR_STALE, 1070191783Srmacklem NFSERR_WRONGSEC, 1071191783Srmacklem 0, 1072191783Srmacklem}; 1073191783Srmacklem 1074191783Srmacklemstatic short nfsv4err_savefh[] = { 1075191783Srmacklem NFSERR_SERVERFAULT, 1076191783Srmacklem NFSERR_BADHANDLE, 1077191783Srmacklem NFSERR_FHEXPIRED, 1078191783Srmacklem NFSERR_MOVED, 1079191783Srmacklem NFSERR_NOFILEHANDLE, 1080191783Srmacklem NFSERR_RESOURCE, 1081191783Srmacklem NFSERR_SERVERFAULT, 1082191783Srmacklem NFSERR_STALE, 1083191783Srmacklem 0, 1084191783Srmacklem}; 1085191783Srmacklem 1086191783Srmacklemstatic short nfsv4err_secinfo[] = { 1087191783Srmacklem NFSERR_SERVERFAULT, 1088191783Srmacklem NFSERR_ACCES, 1089191783Srmacklem NFSERR_BADCHAR, 1090191783Srmacklem NFSERR_BADHANDLE, 1091191783Srmacklem NFSERR_BADNAME, 1092191783Srmacklem NFSERR_BADXDR, 1093191783Srmacklem NFSERR_FHEXPIRED, 1094191783Srmacklem NFSERR_INVAL, 1095191783Srmacklem NFSERR_MOVED, 1096191783Srmacklem NFSERR_NAMETOL, 1097191783Srmacklem NFSERR_NOENT, 1098191783Srmacklem NFSERR_NOFILEHANDLE, 1099191783Srmacklem NFSERR_NOTDIR, 1100191783Srmacklem NFSERR_RESOURCE, 1101191783Srmacklem NFSERR_SERVERFAULT, 1102191783Srmacklem NFSERR_STALE, 1103191783Srmacklem 0, 1104191783Srmacklem}; 1105191783Srmacklem 1106191783Srmacklemstatic short nfsv4err_setattr[] = { 1107191783Srmacklem NFSERR_IO, 1108191783Srmacklem NFSERR_ACCES, 1109191783Srmacklem NFSERR_ADMINREVOKED, 1110191783Srmacklem NFSERR_ATTRNOTSUPP, 1111191783Srmacklem NFSERR_BADCHAR, 1112191783Srmacklem NFSERR_BADHANDLE, 1113191783Srmacklem NFSERR_BADOWNER, 1114191783Srmacklem NFSERR_BADSTATEID, 1115191783Srmacklem NFSERR_BADXDR, 1116191783Srmacklem NFSERR_DELAY, 1117191783Srmacklem NFSERR_DQUOT, 1118191783Srmacklem NFSERR_EXPIRED, 1119191783Srmacklem NFSERR_FBIG, 1120191783Srmacklem NFSERR_FHEXPIRED, 1121191783Srmacklem NFSERR_GRACE, 1122191783Srmacklem NFSERR_INVAL, 1123191783Srmacklem NFSERR_IO, 1124191783Srmacklem NFSERR_ISDIR, 1125191783Srmacklem NFSERR_LOCKED, 1126191783Srmacklem NFSERR_MOVED, 1127191783Srmacklem NFSERR_NOFILEHANDLE, 1128191783Srmacklem NFSERR_NOSPC, 1129191783Srmacklem NFSERR_OLDSTATEID, 1130191783Srmacklem NFSERR_OPENMODE, 1131191783Srmacklem NFSERR_PERM, 1132191783Srmacklem NFSERR_RESOURCE, 1133191783Srmacklem NFSERR_ROFS, 1134191783Srmacklem NFSERR_SERVERFAULT, 1135191783Srmacklem NFSERR_STALE, 1136191783Srmacklem NFSERR_STALESTATEID, 1137191783Srmacklem 0, 1138191783Srmacklem}; 1139191783Srmacklem 1140191783Srmacklemstatic short nfsv4err_setclientid[] = { 1141191783Srmacklem NFSERR_SERVERFAULT, 1142191783Srmacklem NFSERR_BADXDR, 1143191783Srmacklem NFSERR_CLIDINUSE, 1144191783Srmacklem NFSERR_INVAL, 1145191783Srmacklem NFSERR_RESOURCE, 1146191783Srmacklem NFSERR_SERVERFAULT, 1147299223Srmacklem NFSERR_WRONGSEC, 1148191783Srmacklem 0, 1149191783Srmacklem}; 1150191783Srmacklem 1151191783Srmacklemstatic short nfsv4err_setclientidconfirm[] = { 1152191783Srmacklem NFSERR_SERVERFAULT, 1153191783Srmacklem NFSERR_BADXDR, 1154191783Srmacklem NFSERR_CLIDINUSE, 1155191783Srmacklem NFSERR_RESOURCE, 1156191783Srmacklem NFSERR_SERVERFAULT, 1157191783Srmacklem NFSERR_STALECLIENTID, 1158191783Srmacklem 0, 1159191783Srmacklem}; 1160191783Srmacklem 1161191783Srmacklemstatic short nfsv4err_verify[] = { 1162191783Srmacklem NFSERR_SERVERFAULT, 1163191783Srmacklem NFSERR_ACCES, 1164191783Srmacklem NFSERR_ATTRNOTSUPP, 1165191783Srmacklem NFSERR_BADCHAR, 1166191783Srmacklem NFSERR_BADHANDLE, 1167191783Srmacklem NFSERR_BADXDR, 1168191783Srmacklem NFSERR_DELAY, 1169191783Srmacklem NFSERR_FHEXPIRED, 1170191783Srmacklem NFSERR_INVAL, 1171191783Srmacklem NFSERR_MOVED, 1172191783Srmacklem NFSERR_NOFILEHANDLE, 1173191783Srmacklem NFSERR_NOTSAME, 1174191783Srmacklem NFSERR_RESOURCE, 1175191783Srmacklem NFSERR_SERVERFAULT, 1176191783Srmacklem NFSERR_STALE, 1177191783Srmacklem 0, 1178191783Srmacklem}; 1179191783Srmacklem 1180191783Srmacklemstatic short nfsv4err_write[] = { 1181191783Srmacklem NFSERR_IO, 1182191783Srmacklem NFSERR_ACCES, 1183191783Srmacklem NFSERR_ADMINREVOKED, 1184191783Srmacklem NFSERR_BADHANDLE, 1185191783Srmacklem NFSERR_BADSTATEID, 1186191783Srmacklem NFSERR_BADXDR, 1187191783Srmacklem NFSERR_DELAY, 1188191783Srmacklem NFSERR_DQUOT, 1189191783Srmacklem NFSERR_EXPIRED, 1190191783Srmacklem NFSERR_FBIG, 1191191783Srmacklem NFSERR_FHEXPIRED, 1192191783Srmacklem NFSERR_GRACE, 1193191783Srmacklem NFSERR_INVAL, 1194191783Srmacklem NFSERR_IO, 1195191783Srmacklem NFSERR_ISDIR, 1196191783Srmacklem NFSERR_LEASEMOVED, 1197191783Srmacklem NFSERR_LOCKED, 1198191783Srmacklem NFSERR_MOVED, 1199191783Srmacklem NFSERR_NOFILEHANDLE, 1200191783Srmacklem NFSERR_NOSPC, 1201191783Srmacklem NFSERR_NXIO, 1202191783Srmacklem NFSERR_OLDSTATEID, 1203191783Srmacklem NFSERR_OPENMODE, 1204191783Srmacklem NFSERR_RESOURCE, 1205191783Srmacklem NFSERR_ROFS, 1206191783Srmacklem NFSERR_SERVERFAULT, 1207191783Srmacklem NFSERR_STALE, 1208191783Srmacklem NFSERR_STALESTATEID, 1209191783Srmacklem 0, 1210191783Srmacklem}; 1211191783Srmacklem 1212191783Srmacklemstatic short nfsv4err_releaselockowner[] = { 1213191783Srmacklem NFSERR_SERVERFAULT, 1214191783Srmacklem NFSERR_ADMINREVOKED, 1215191783Srmacklem NFSERR_BADXDR, 1216191783Srmacklem NFSERR_EXPIRED, 1217191783Srmacklem NFSERR_LEASEMOVED, 1218191783Srmacklem NFSERR_LOCKSHELD, 1219191783Srmacklem NFSERR_RESOURCE, 1220191783Srmacklem NFSERR_SERVERFAULT, 1221191783Srmacklem NFSERR_STALECLIENTID, 1222191783Srmacklem 0, 1223191783Srmacklem}; 1224191783Srmacklem 1225191783Srmacklemstatic short *nfsrv_v4errmap[] = { 1226191783Srmacklem nfsv4err_null, 1227191783Srmacklem nfsv4err_null, 1228191783Srmacklem nfsv4err_null, 1229191783Srmacklem nfsv4err_access, 1230191783Srmacklem nfsv4err_close, 1231191783Srmacklem nfsv4err_commit, 1232191783Srmacklem nfsv4err_create, 1233191783Srmacklem nfsv4err_delegpurge, 1234191783Srmacklem nfsv4err_delegreturn, 1235191783Srmacklem nfsv4err_getattr, 1236191783Srmacklem nfsv4err_getfh, 1237191783Srmacklem nfsv4err_link, 1238191783Srmacklem nfsv4err_lock, 1239191783Srmacklem nfsv4err_lockt, 1240191783Srmacklem nfsv4err_locku, 1241191783Srmacklem nfsv4err_lookup, 1242191783Srmacklem nfsv4err_lookupp, 1243191783Srmacklem nfsv4err_nverify, 1244191783Srmacklem nfsv4err_open, 1245191783Srmacklem nfsv4err_openattr, 1246191783Srmacklem nfsv4err_openconfirm, 1247191783Srmacklem nfsv4err_opendowngrade, 1248191783Srmacklem nfsv4err_putfh, 1249191783Srmacklem nfsv4err_putpubfh, 1250191783Srmacklem nfsv4err_putrootfh, 1251191783Srmacklem nfsv4err_read, 1252191783Srmacklem nfsv4err_readdir, 1253191783Srmacklem nfsv4err_readlink, 1254191783Srmacklem nfsv4err_remove, 1255191783Srmacklem nfsv4err_rename, 1256191783Srmacklem nfsv4err_renew, 1257191783Srmacklem nfsv4err_restorefh, 1258191783Srmacklem nfsv4err_savefh, 1259191783Srmacklem nfsv4err_secinfo, 1260191783Srmacklem nfsv4err_setattr, 1261191783Srmacklem nfsv4err_setclientid, 1262191783Srmacklem nfsv4err_setclientidconfirm, 1263191783Srmacklem nfsv4err_verify, 1264191783Srmacklem nfsv4err_write, 1265191783Srmacklem nfsv4err_releaselockowner, 1266191783Srmacklem}; 1267191783Srmacklem 1268191783Srmacklem/* 1269191783Srmacklem * A fiddled version of m_adj() that ensures null fill to a long 1270191783Srmacklem * boundary and only trims off the back end 1271191783Srmacklem */ 1272191783SrmacklemAPPLESTATIC void 1273191783Srmacklemnfsrv_adj(mbuf_t mp, int len, int nul) 1274191783Srmacklem{ 1275191783Srmacklem mbuf_t m; 1276191783Srmacklem int count, i; 1277191783Srmacklem char *cp; 1278191783Srmacklem 1279191783Srmacklem /* 1280191783Srmacklem * Trim from tail. Scan the mbuf chain, 1281191783Srmacklem * calculating its length and finding the last mbuf. 1282191783Srmacklem * If the adjustment only affects this mbuf, then just 1283191783Srmacklem * adjust and return. Otherwise, rescan and truncate 1284191783Srmacklem * after the remaining size. 1285191783Srmacklem */ 1286191783Srmacklem count = 0; 1287191783Srmacklem m = mp; 1288191783Srmacklem for (;;) { 1289191783Srmacklem count += mbuf_len(m); 1290191783Srmacklem if (mbuf_next(m) == NULL) 1291191783Srmacklem break; 1292191783Srmacklem m = mbuf_next(m); 1293191783Srmacklem } 1294191783Srmacklem if (mbuf_len(m) > len) { 1295191783Srmacklem mbuf_setlen(m, mbuf_len(m) - len); 1296191783Srmacklem if (nul > 0) { 1297191783Srmacklem cp = NFSMTOD(m, caddr_t) + mbuf_len(m) - nul; 1298191783Srmacklem for (i = 0; i < nul; i++) 1299191783Srmacklem *cp++ = '\0'; 1300191783Srmacklem } 1301191783Srmacklem return; 1302191783Srmacklem } 1303191783Srmacklem count -= len; 1304191783Srmacklem if (count < 0) 1305191783Srmacklem count = 0; 1306191783Srmacklem /* 1307191783Srmacklem * Correct length for chain is "count". 1308191783Srmacklem * Find the mbuf with last data, adjust its length, 1309191783Srmacklem * and toss data from remaining mbufs on chain. 1310191783Srmacklem */ 1311191783Srmacklem for (m = mp; m; m = mbuf_next(m)) { 1312191783Srmacklem if (mbuf_len(m) >= count) { 1313191783Srmacklem mbuf_setlen(m, count); 1314191783Srmacklem if (nul > 0) { 1315191783Srmacklem cp = NFSMTOD(m, caddr_t) + mbuf_len(m) - nul; 1316191783Srmacklem for (i = 0; i < nul; i++) 1317191783Srmacklem *cp++ = '\0'; 1318191783Srmacklem } 1319191783Srmacklem break; 1320191783Srmacklem } 1321191783Srmacklem count -= mbuf_len(m); 1322191783Srmacklem } 1323191783Srmacklem for (m = mbuf_next(m); m; m = mbuf_next(m)) 1324191783Srmacklem mbuf_setlen(m, 0); 1325191783Srmacklem} 1326191783Srmacklem 1327191783Srmacklem/* 1328191783Srmacklem * Make these functions instead of macros, so that the kernel text size 1329191783Srmacklem * doesn't get too big... 1330191783Srmacklem */ 1331191783SrmacklemAPPLESTATIC void 1332191783Srmacklemnfsrv_wcc(struct nfsrv_descript *nd, int before_ret, 1333191783Srmacklem struct nfsvattr *before_nvap, int after_ret, struct nfsvattr *after_nvap) 1334191783Srmacklem{ 1335191783Srmacklem u_int32_t *tl; 1336191783Srmacklem 1337191783Srmacklem if (before_ret) { 1338191783Srmacklem NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 1339191783Srmacklem *tl = newnfs_false; 1340191783Srmacklem } else { 1341191783Srmacklem NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED); 1342191783Srmacklem *tl++ = newnfs_true; 1343191783Srmacklem txdr_hyper(before_nvap->na_size, tl); 1344191783Srmacklem tl += 2; 1345191783Srmacklem txdr_nfsv3time(&(before_nvap->na_mtime), tl); 1346191783Srmacklem tl += 2; 1347191783Srmacklem txdr_nfsv3time(&(before_nvap->na_ctime), tl); 1348191783Srmacklem } 1349191783Srmacklem nfsrv_postopattr(nd, after_ret, after_nvap); 1350191783Srmacklem} 1351191783Srmacklem 1352191783SrmacklemAPPLESTATIC void 1353191783Srmacklemnfsrv_postopattr(struct nfsrv_descript *nd, int after_ret, 1354191783Srmacklem struct nfsvattr *after_nvap) 1355191783Srmacklem{ 1356191783Srmacklem u_int32_t *tl; 1357191783Srmacklem 1358191783Srmacklem NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 1359191783Srmacklem if (after_ret) 1360191783Srmacklem *tl = newnfs_false; 1361191783Srmacklem else { 1362191783Srmacklem *tl = newnfs_true; 1363191783Srmacklem nfsrv_fillattr(nd, after_nvap); 1364191783Srmacklem } 1365191783Srmacklem} 1366191783Srmacklem 1367191783Srmacklem/* 1368191783Srmacklem * Fill in file attributes for V2 and 3. For V4, call a separate 1369191783Srmacklem * routine that sifts through all the attribute bits. 1370191783Srmacklem */ 1371191783SrmacklemAPPLESTATIC void 1372191783Srmacklemnfsrv_fillattr(struct nfsrv_descript *nd, struct nfsvattr *nvap) 1373191783Srmacklem{ 1374191783Srmacklem struct nfs_fattr *fp; 1375191783Srmacklem int fattr_size; 1376191783Srmacklem 1377191783Srmacklem /* 1378191783Srmacklem * Build space for the attribute structure. 1379191783Srmacklem */ 1380191783Srmacklem if (nd->nd_flag & ND_NFSV3) 1381191783Srmacklem fattr_size = NFSX_V3FATTR; 1382191783Srmacklem else 1383191783Srmacklem fattr_size = NFSX_V2FATTR; 1384191783Srmacklem NFSM_BUILD(fp, struct nfs_fattr *, fattr_size); 1385191783Srmacklem 1386191783Srmacklem /* 1387191783Srmacklem * Now just fill it all in. 1388191783Srmacklem */ 1389191783Srmacklem fp->fa_nlink = txdr_unsigned(nvap->na_nlink); 1390191783Srmacklem fp->fa_uid = txdr_unsigned(nvap->na_uid); 1391191783Srmacklem fp->fa_gid = txdr_unsigned(nvap->na_gid); 1392191783Srmacklem if (nd->nd_flag & ND_NFSV3) { 1393191783Srmacklem fp->fa_type = vtonfsv34_type(nvap->na_type); 1394191783Srmacklem fp->fa_mode = vtonfsv34_mode(nvap->na_mode); 1395191783Srmacklem txdr_hyper(nvap->na_size, &fp->fa3_size); 1396191783Srmacklem txdr_hyper(nvap->na_bytes, &fp->fa3_used); 1397191783Srmacklem fp->fa3_rdev.specdata1 = txdr_unsigned(NFSMAJOR(nvap->na_rdev)); 1398191783Srmacklem fp->fa3_rdev.specdata2 = txdr_unsigned(NFSMINOR(nvap->na_rdev)); 1399191783Srmacklem fp->fa3_fsid.nfsuquad[0] = 0; 1400191783Srmacklem fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(nvap->na_fsid); 1401191783Srmacklem fp->fa3_fileid.nfsuquad[0] = 0; 1402191783Srmacklem fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(nvap->na_fileid); 1403191783Srmacklem txdr_nfsv3time(&nvap->na_atime, &fp->fa3_atime); 1404191783Srmacklem txdr_nfsv3time(&nvap->na_mtime, &fp->fa3_mtime); 1405191783Srmacklem txdr_nfsv3time(&nvap->na_ctime, &fp->fa3_ctime); 1406191783Srmacklem } else { 1407191783Srmacklem fp->fa_type = vtonfsv2_type(nvap->na_type); 1408191783Srmacklem fp->fa_mode = vtonfsv2_mode(nvap->na_type, nvap->na_mode); 1409191783Srmacklem fp->fa2_size = txdr_unsigned(nvap->na_size); 1410191783Srmacklem fp->fa2_blocksize = txdr_unsigned(nvap->na_blocksize); 1411191783Srmacklem if (nvap->na_type == VFIFO) 1412191783Srmacklem fp->fa2_rdev = 0xffffffff; 1413191783Srmacklem else 1414191783Srmacklem fp->fa2_rdev = txdr_unsigned(nvap->na_rdev); 1415191783Srmacklem fp->fa2_blocks = txdr_unsigned(nvap->na_bytes / NFS_FABLKSIZE); 1416191783Srmacklem fp->fa2_fsid = txdr_unsigned(nvap->na_fsid); 1417191783Srmacklem fp->fa2_fileid = txdr_unsigned(nvap->na_fileid); 1418191783Srmacklem txdr_nfsv2time(&nvap->na_atime, &fp->fa2_atime); 1419191783Srmacklem txdr_nfsv2time(&nvap->na_mtime, &fp->fa2_mtime); 1420191783Srmacklem txdr_nfsv2time(&nvap->na_ctime, &fp->fa2_ctime); 1421191783Srmacklem } 1422191783Srmacklem} 1423191783Srmacklem 1424191783Srmacklem/* 1425191783Srmacklem * This function gets a file handle out of an mbuf list. 1426191783Srmacklem * It returns 0 for success, EBADRPC otherwise. 1427191783Srmacklem * If sets the third flagp argument to 1 if the file handle is 1428191783Srmacklem * the public file handle. 1429191783Srmacklem * For NFSv4, if the length is incorrect, set nd_repstat == NFSERR_BADHANDLE 1430191783Srmacklem */ 1431191783SrmacklemAPPLESTATIC int 1432191783Srmacklemnfsrv_mtofh(struct nfsrv_descript *nd, struct nfsrvfh *fhp) 1433191783Srmacklem{ 1434191783Srmacklem u_int32_t *tl; 1435191783Srmacklem int error = 0, len, copylen; 1436191783Srmacklem 1437191783Srmacklem if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) { 1438191783Srmacklem NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 1439191783Srmacklem len = fxdr_unsigned(int, *tl); 1440191783Srmacklem if (len == 0 && nfs_pubfhset && (nd->nd_flag & ND_NFSV3) && 1441191783Srmacklem nd->nd_procnum == NFSPROC_LOOKUP) { 1442191783Srmacklem nd->nd_flag |= ND_PUBLOOKUP; 1443224086Szack goto nfsmout; 1444191783Srmacklem } 1445191783Srmacklem if (len < NFSRV_MINFH || len > NFSRV_MAXFH) { 1446191783Srmacklem if (nd->nd_flag & ND_NFSV4) { 1447191783Srmacklem if (len > 0 && len <= NFSX_V4FHMAX) { 1448191783Srmacklem error = nfsm_advance(nd, NFSM_RNDUP(len), -1); 1449191783Srmacklem if (error) 1450224086Szack goto nfsmout; 1451191783Srmacklem nd->nd_repstat = NFSERR_BADHANDLE; 1452224086Szack goto nfsmout; 1453191783Srmacklem } else { 1454224086Szack error = EBADRPC; 1455224086Szack goto nfsmout; 1456191783Srmacklem } 1457191783Srmacklem } else { 1458224086Szack error = EBADRPC; 1459224086Szack goto nfsmout; 1460191783Srmacklem } 1461191783Srmacklem } 1462191783Srmacklem copylen = len; 1463191783Srmacklem } else { 1464191783Srmacklem /* 1465191783Srmacklem * For NFSv2, the file handle is always 32 bytes on the 1466191783Srmacklem * wire, but this server only cares about the first 1467191783Srmacklem * NFSRV_MAXFH bytes. 1468191783Srmacklem */ 1469191783Srmacklem len = NFSX_V2FH; 1470191783Srmacklem copylen = NFSRV_MAXFH; 1471191783Srmacklem } 1472191783Srmacklem NFSM_DISSECT(tl, u_int32_t *, len); 1473191783Srmacklem if ((nd->nd_flag & ND_NFSV2) && nfs_pubfhset && 1474191783Srmacklem nd->nd_procnum == NFSPROC_LOOKUP && 1475191783Srmacklem !NFSBCMP((caddr_t)tl, nfs_v2pubfh, NFSX_V2FH)) { 1476191783Srmacklem nd->nd_flag |= ND_PUBLOOKUP; 1477224086Szack goto nfsmout; 1478191783Srmacklem } 1479191783Srmacklem NFSBCOPY(tl, (caddr_t)fhp->nfsrvfh_data, copylen); 1480191783Srmacklem fhp->nfsrvfh_len = copylen; 1481191783Srmacklemnfsmout: 1482224086Szack NFSEXITCODE2(error, nd); 1483191783Srmacklem return (error); 1484191783Srmacklem} 1485191783Srmacklem 1486191783Srmacklem/* 1487191783Srmacklem * Map errnos to NFS error numbers. For Version 3 and 4 also filter out error 1488191783Srmacklem * numbers not specified for the associated procedure. 1489191783Srmacklem * NFSPROC_NOOP is a special case, where the high order bits of nd_repstat 1490191783Srmacklem * should be cleared. NFSPROC_NOOP is used to return errors when a valid 1491191783Srmacklem * RPC procedure is not involved. 1492191783Srmacklem * Returns the error number in XDR. 1493191783Srmacklem */ 1494191783SrmacklemAPPLESTATIC int 1495191783Srmacklemnfsd_errmap(struct nfsrv_descript *nd) 1496191783Srmacklem{ 1497191783Srmacklem short *defaulterrp, *errp; 1498191783Srmacklem 1499191783Srmacklem if (!nd->nd_repstat) 1500191783Srmacklem return (0); 1501191783Srmacklem if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) { 1502191783Srmacklem if (nd->nd_procnum == NFSPROC_NOOP) 1503191783Srmacklem return (txdr_unsigned(nd->nd_repstat & 0xffff)); 1504191783Srmacklem if (nd->nd_flag & ND_NFSV3) 1505191783Srmacklem errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum]; 1506191783Srmacklem else if (nd->nd_repstat == EBADRPC) 1507191783Srmacklem return (txdr_unsigned(NFSERR_BADXDR)); 1508191783Srmacklem else if (nd->nd_repstat == NFSERR_MINORVERMISMATCH || 1509191783Srmacklem nd->nd_repstat == NFSERR_OPILLEGAL) 1510191783Srmacklem return (txdr_unsigned(nd->nd_repstat)); 1511269398Srmacklem else if ((nd->nd_flag & ND_NFSV41) != 0) { 1512269398Srmacklem if (nd->nd_repstat == EOPNOTSUPP) 1513269398Srmacklem nd->nd_repstat = NFSERR_NOTSUPP; 1514269398Srmacklem nd->nd_repstat = nfsrv_isannfserr(nd->nd_repstat); 1515269398Srmacklem return (txdr_unsigned(nd->nd_repstat)); 1516269398Srmacklem } else 1517191783Srmacklem errp = defaulterrp = nfsrv_v4errmap[nd->nd_procnum]; 1518191783Srmacklem while (*++errp) 1519191783Srmacklem if (*errp == nd->nd_repstat) 1520191783Srmacklem return (txdr_unsigned(nd->nd_repstat)); 1521191783Srmacklem return (txdr_unsigned(*defaulterrp)); 1522191783Srmacklem } 1523269398Srmacklem if (nd->nd_repstat <= NFSERR_REMOTE) 1524191783Srmacklem return (txdr_unsigned(nfsrv_v2errmap[nd->nd_repstat - 1])); 1525191783Srmacklem return (txdr_unsigned(NFSERR_IO)); 1526191783Srmacklem} 1527191783Srmacklem 1528191783Srmacklem/* 1529269398Srmacklem * Check to see if the error is a valid NFS one. If not, replace it with 1530269398Srmacklem * NFSERR_IO. 1531269398Srmacklem */ 1532269398Srmacklemstatic u_int32_t 1533269398Srmacklemnfsrv_isannfserr(u_int32_t errval) 1534269398Srmacklem{ 1535269398Srmacklem 1536269398Srmacklem if (errval == NFSERR_OK) 1537269398Srmacklem return (errval); 1538269398Srmacklem if (errval >= NFSERR_BADHANDLE && errval <= NFSERR_DELEGREVOKED) 1539269398Srmacklem return (errval); 1540269398Srmacklem if (errval > 0 && errval <= NFSERR_REMOTE) 1541269398Srmacklem return (nfsrv_v2errmap[errval - 1]); 1542269398Srmacklem return (NFSERR_IO); 1543269398Srmacklem} 1544269398Srmacklem 1545269398Srmacklem/* 1546191783Srmacklem * Check to see if setting a uid/gid is permitted when creating a new 1547191783Srmacklem * file object. (Called when uid and/or gid is specified in the 1548191783Srmacklem * settable attributes for V4. 1549191783Srmacklem */ 1550191783SrmacklemAPPLESTATIC int 1551191783Srmacklemnfsrv_checkuidgid(struct nfsrv_descript *nd, struct nfsvattr *nvap) 1552191783Srmacklem{ 1553224086Szack int error = 0; 1554191783Srmacklem 1555191783Srmacklem /* 1556191783Srmacklem * If not setting either uid nor gid, it's OK. 1557191783Srmacklem */ 1558191783Srmacklem if (NFSVNO_NOTSETUID(nvap) && NFSVNO_NOTSETGID(nvap)) 1559224086Szack goto out; 1560273877Saraujo if ((NFSVNO_ISSETUID(nvap) && nvap->na_uid == nfsrv_defaultuid && 1561273877Saraujo enable_nobodycheck == 1) 1562273877Saraujo || (NFSVNO_ISSETGID(nvap) && nvap->na_gid == nfsrv_defaultgid && 1563273877Saraujo enable_nogroupcheck == 1)) { 1564224086Szack error = NFSERR_BADOWNER; 1565224086Szack goto out; 1566224086Szack } 1567191783Srmacklem if (nd->nd_cred->cr_uid == 0) 1568224086Szack goto out; 1569191783Srmacklem if ((NFSVNO_ISSETUID(nvap) && nvap->na_uid != nd->nd_cred->cr_uid) || 1570191783Srmacklem (NFSVNO_ISSETGID(nvap) && nvap->na_gid != nd->nd_cred->cr_gid && 1571191783Srmacklem !groupmember(nvap->na_gid, nd->nd_cred))) 1572224086Szack error = NFSERR_PERM; 1573224086Szack 1574224086Szackout: 1575224086Szack NFSEXITCODE2(error, nd); 1576224086Szack return (error); 1577191783Srmacklem} 1578191783Srmacklem 1579191783Srmacklem/* 1580191783Srmacklem * and this routine fixes up the settable attributes for V4 if allowed 1581191783Srmacklem * by nfsrv_checkuidgid(). 1582191783Srmacklem */ 1583191783SrmacklemAPPLESTATIC void 1584191783Srmacklemnfsrv_fixattr(struct nfsrv_descript *nd, vnode_t vp, 1585191783Srmacklem struct nfsvattr *nvap, NFSACL_T *aclp, NFSPROC_T *p, nfsattrbit_t *attrbitp, 1586191783Srmacklem struct nfsexstuff *exp) 1587191783Srmacklem{ 1588191783Srmacklem int change = 0; 1589191783Srmacklem struct nfsvattr nva; 1590191783Srmacklem uid_t tuid; 1591191783Srmacklem int error; 1592191783Srmacklem nfsattrbit_t nattrbits; 1593191783Srmacklem 1594191783Srmacklem /* 1595191783Srmacklem * Maybe this should be done for V2 and 3 but it never has been 1596191783Srmacklem * and nobody seems to be upset, so I think it's best not to change 1597191783Srmacklem * the V2 and 3 semantics. 1598191783Srmacklem */ 1599191783Srmacklem if ((nd->nd_flag & ND_NFSV4) == 0) 1600224086Szack goto out; 1601191783Srmacklem NFSVNO_ATTRINIT(&nva); 1602191783Srmacklem NFSZERO_ATTRBIT(&nattrbits); 1603191783Srmacklem tuid = nd->nd_cred->cr_uid; 1604191783Srmacklem if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNER) && 1605191783Srmacklem NFSVNO_ISSETUID(nvap) && 1606191783Srmacklem nvap->na_uid != nd->nd_cred->cr_uid) { 1607191783Srmacklem if (nd->nd_cred->cr_uid == 0) { 1608191783Srmacklem nva.na_uid = nvap->na_uid; 1609191783Srmacklem change++; 1610191783Srmacklem NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_OWNER); 1611191783Srmacklem } else { 1612191783Srmacklem NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_OWNER); 1613191783Srmacklem } 1614191783Srmacklem } 1615191783Srmacklem if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_TIMEACCESSSET) && 1616191783Srmacklem NFSVNO_ISSETATIME(nvap)) { 1617191783Srmacklem nva.na_atime = nvap->na_atime; 1618191783Srmacklem change++; 1619191783Srmacklem NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_TIMEACCESSSET); 1620191783Srmacklem } 1621191783Srmacklem if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_TIMEMODIFYSET) && 1622191783Srmacklem NFSVNO_ISSETMTIME(nvap)) { 1623191783Srmacklem nva.na_mtime = nvap->na_mtime; 1624191783Srmacklem change++; 1625191783Srmacklem NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_TIMEMODIFYSET); 1626191783Srmacklem } 1627191783Srmacklem if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP) && 1628191783Srmacklem NFSVNO_ISSETGID(nvap)) { 1629191783Srmacklem if (nvap->na_gid == nd->nd_cred->cr_gid || 1630191783Srmacklem groupmember(nvap->na_gid, nd->nd_cred)) { 1631191783Srmacklem nd->nd_cred->cr_uid = 0; 1632191783Srmacklem nva.na_gid = nvap->na_gid; 1633191783Srmacklem change++; 1634191783Srmacklem NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_OWNERGROUP); 1635191783Srmacklem } else { 1636191783Srmacklem NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP); 1637191783Srmacklem } 1638191783Srmacklem } 1639191783Srmacklem if (change) { 1640191783Srmacklem error = nfsvno_setattr(vp, &nva, nd->nd_cred, p, exp); 1641191783Srmacklem if (error) { 1642191783Srmacklem NFSCLRALL_ATTRBIT(attrbitp, &nattrbits); 1643191783Srmacklem } 1644191783Srmacklem } 1645191783Srmacklem if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SIZE) && 1646191783Srmacklem NFSVNO_ISSETSIZE(nvap) && nvap->na_size != (u_quad_t)0) { 1647191783Srmacklem NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_SIZE); 1648191783Srmacklem } 1649191783Srmacklem#ifdef NFS4_ACL_EXTATTR_NAME 1650191783Srmacklem if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ACL) && 1651191783Srmacklem nfsrv_useacl != 0 && aclp != NULL) { 1652191783Srmacklem if (aclp->acl_cnt > 0) { 1653191783Srmacklem error = nfsrv_setacl(vp, aclp, nd->nd_cred, p); 1654191783Srmacklem if (error) { 1655191783Srmacklem NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_ACL); 1656191783Srmacklem } 1657191783Srmacklem } 1658191783Srmacklem } else 1659191783Srmacklem#endif 1660191783Srmacklem NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_ACL); 1661191783Srmacklem nd->nd_cred->cr_uid = tuid; 1662224086Szack 1663224086Szackout: 1664224086Szack NFSEXITCODE2(0, nd); 1665191783Srmacklem} 1666191783Srmacklem 1667191783Srmacklem/* 1668191783Srmacklem * Translate an ASCII hex digit to it's binary value. Return -1 if the 1669191783Srmacklem * char isn't a hex digit. 1670191783Srmacklem */ 1671191783Srmacklemstatic char 1672191783Srmacklemnfsrv_hexdigit(char c, int *err) 1673191783Srmacklem{ 1674191783Srmacklem 1675191783Srmacklem *err = 0; 1676191783Srmacklem if (c >= '0' && c <= '9') 1677191783Srmacklem return (c - '0'); 1678191783Srmacklem if (c >= 'a' && c <= 'f') 1679191783Srmacklem return (c - 'a' + ((char)10)); 1680191783Srmacklem if (c >= 'A' && c <= 'F') 1681191783Srmacklem return (c - 'A' + ((char)10)); 1682191783Srmacklem /* Not valid ! */ 1683191783Srmacklem *err = 1; 1684191783Srmacklem return (1); /* BOGUS */ 1685191783Srmacklem} 1686191783Srmacklem 1687191783Srmacklem/* 1688191783Srmacklem * Check to see if NFSERR_MOVED can be returned for this op. Return 1 iff 1689191783Srmacklem * it can be. 1690191783Srmacklem */ 1691191783SrmacklemAPPLESTATIC int 1692191783Srmacklemnfsrv_errmoved(int op) 1693191783Srmacklem{ 1694191783Srmacklem short *errp; 1695191783Srmacklem 1696191783Srmacklem errp = nfsrv_v4errmap[op]; 1697191783Srmacklem while (*errp != 0) { 1698191783Srmacklem if (*errp == NFSERR_MOVED) 1699191783Srmacklem return (1); 1700191783Srmacklem errp++; 1701191783Srmacklem } 1702191783Srmacklem return (0); 1703191783Srmacklem} 1704191783Srmacklem 1705191783Srmacklem/* 1706191783Srmacklem * Fill in attributes for a Referral. 1707191783Srmacklem * (Return the number of bytes of XDR created.) 1708191783Srmacklem */ 1709191783SrmacklemAPPLESTATIC int 1710191783Srmacklemnfsrv_putreferralattr(struct nfsrv_descript *nd, nfsattrbit_t *retbitp, 1711191783Srmacklem struct nfsreferral *refp, int getattr, int *reterrp) 1712191783Srmacklem{ 1713191783Srmacklem u_int32_t *tl, *retnump; 1714191783Srmacklem u_char *cp, *cp2; 1715191783Srmacklem int prefixnum, retnum = 0, i, len, bitpos, rderrbit = 0, nonrefbit = 0; 1716191783Srmacklem int fslocationsbit = 0; 1717191783Srmacklem nfsattrbit_t tmpbits, refbits; 1718191783Srmacklem 1719191783Srmacklem NFSREFERRAL_ATTRBIT(&refbits); 1720191783Srmacklem if (getattr) 1721191783Srmacklem NFSCLRBIT_ATTRBIT(&refbits, NFSATTRBIT_RDATTRERROR); 1722191783Srmacklem else if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_RDATTRERROR)) 1723191783Srmacklem rderrbit = 1; 1724191783Srmacklem if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_FSLOCATIONS)) 1725191783Srmacklem fslocationsbit = 1; 1726191783Srmacklem 1727191783Srmacklem /* 1728191783Srmacklem * Check for the case where unsupported referral attributes are 1729191783Srmacklem * requested. 1730191783Srmacklem */ 1731191783Srmacklem NFSSET_ATTRBIT(&tmpbits, retbitp); 1732191783Srmacklem NFSCLRALL_ATTRBIT(&tmpbits, &refbits); 1733191783Srmacklem if (NFSNONZERO_ATTRBIT(&tmpbits)) 1734191783Srmacklem nonrefbit = 1; 1735191783Srmacklem 1736191783Srmacklem if (nonrefbit && !fslocationsbit && (getattr || !rderrbit)) { 1737191783Srmacklem *reterrp = NFSERR_MOVED; 1738191783Srmacklem return (0); 1739191783Srmacklem } 1740191783Srmacklem 1741191783Srmacklem /* 1742191783Srmacklem * Now we can fill in the attributes. 1743191783Srmacklem */ 1744191783Srmacklem NFSSET_ATTRBIT(&tmpbits, retbitp); 1745191783Srmacklem NFSCLRNOT_ATTRBIT(&tmpbits, &refbits); 1746191783Srmacklem 1747191783Srmacklem /* 1748191783Srmacklem * Put out the attribute bitmap for the ones being filled in 1749191783Srmacklem * and get the field for the number of attributes returned. 1750191783Srmacklem */ 1751191783Srmacklem prefixnum = nfsrv_putattrbit(nd, &tmpbits); 1752191783Srmacklem NFSM_BUILD(retnump, u_int32_t *, NFSX_UNSIGNED); 1753191783Srmacklem prefixnum += NFSX_UNSIGNED; 1754191783Srmacklem 1755191783Srmacklem /* 1756191783Srmacklem * Now, loop around filling in the attributes for each bit set. 1757191783Srmacklem */ 1758191783Srmacklem for (bitpos = 0; bitpos < NFSATTRBIT_MAX; bitpos++) { 1759191783Srmacklem if (NFSISSET_ATTRBIT(&tmpbits, bitpos)) { 1760191783Srmacklem switch (bitpos) { 1761191783Srmacklem case NFSATTRBIT_TYPE: 1762191783Srmacklem NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 1763191783Srmacklem *tl = txdr_unsigned(NFDIR); 1764191783Srmacklem retnum += NFSX_UNSIGNED; 1765191783Srmacklem break; 1766191783Srmacklem case NFSATTRBIT_FSID: 1767191783Srmacklem NFSM_BUILD(tl, u_int32_t *, NFSX_V4FSID); 1768191783Srmacklem *tl++ = 0; 1769191783Srmacklem *tl++ = txdr_unsigned(NFSV4ROOT_FSID0); 1770191783Srmacklem *tl++ = 0; 1771191783Srmacklem *tl = txdr_unsigned(NFSV4ROOT_REFERRAL); 1772191783Srmacklem retnum += NFSX_V4FSID; 1773191783Srmacklem break; 1774191783Srmacklem case NFSATTRBIT_RDATTRERROR: 1775191783Srmacklem NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 1776191783Srmacklem if (nonrefbit) 1777191783Srmacklem *tl = txdr_unsigned(NFSERR_MOVED); 1778191783Srmacklem else 1779191783Srmacklem *tl = 0; 1780191783Srmacklem retnum += NFSX_UNSIGNED; 1781191783Srmacklem break; 1782191783Srmacklem case NFSATTRBIT_FSLOCATIONS: 1783191783Srmacklem retnum += nfsm_strtom(nd, "/", 1); 1784191783Srmacklem NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 1785191783Srmacklem *tl = txdr_unsigned(refp->nfr_srvcnt); 1786191783Srmacklem retnum += NFSX_UNSIGNED; 1787191783Srmacklem cp = refp->nfr_srvlist; 1788191783Srmacklem for (i = 0; i < refp->nfr_srvcnt; i++) { 1789191783Srmacklem NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 1790191783Srmacklem *tl = txdr_unsigned(1); 1791191783Srmacklem retnum += NFSX_UNSIGNED; 1792191783Srmacklem cp2 = STRCHR(cp, ':'); 1793191783Srmacklem if (cp2 != NULL) 1794191783Srmacklem len = cp2 - cp; 1795191783Srmacklem else 1796191783Srmacklem len = 1; 1797191783Srmacklem retnum += nfsm_strtom(nd, cp, len); 1798191783Srmacklem if (cp2 != NULL) 1799191783Srmacklem cp = cp2 + 1; 1800191783Srmacklem cp2 = STRCHR(cp, ','); 1801191783Srmacklem if (cp2 != NULL) 1802191783Srmacklem len = cp2 - cp; 1803191783Srmacklem else 1804191783Srmacklem len = strlen(cp); 1805191783Srmacklem retnum += nfsm_strtom(nd, cp, len); 1806191783Srmacklem if (cp2 != NULL) 1807191783Srmacklem cp = cp2 + 1; 1808191783Srmacklem } 1809191783Srmacklem break; 1810191783Srmacklem case NFSATTRBIT_MOUNTEDONFILEID: 1811191783Srmacklem NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER); 1812191783Srmacklem *tl++ = 0; 1813191783Srmacklem *tl = txdr_unsigned(refp->nfr_dfileno); 1814191783Srmacklem retnum += NFSX_HYPER; 1815191783Srmacklem break; 1816191783Srmacklem default: 1817191783Srmacklem printf("EEK! Bad V4 refattr bitpos=%d\n", bitpos); 1818191783Srmacklem }; 1819191783Srmacklem } 1820191783Srmacklem } 1821191783Srmacklem *retnump = txdr_unsigned(retnum); 1822191783Srmacklem return (retnum + prefixnum); 1823191783Srmacklem} 1824191783Srmacklem 1825191783Srmacklem/* 1826191783Srmacklem * Parse a file name out of a request. 1827191783Srmacklem */ 1828191783SrmacklemAPPLESTATIC int 1829191783Srmacklemnfsrv_parsename(struct nfsrv_descript *nd, char *bufp, u_long *hashp, 1830191783Srmacklem NFSPATHLEN_T *outlenp) 1831191783Srmacklem{ 1832191783Srmacklem char *fromcp, *tocp, val = '\0'; 1833191783Srmacklem mbuf_t md; 1834191783Srmacklem int i; 1835191783Srmacklem int rem, len, error = 0, pubtype = 0, outlen = 0, percent = 0; 1836191783Srmacklem char digit; 1837191783Srmacklem u_int32_t *tl; 1838191783Srmacklem u_long hash = 0; 1839191783Srmacklem 1840191783Srmacklem if (hashp != NULL) 1841191783Srmacklem *hashp = 0; 1842191783Srmacklem tocp = bufp; 1843191783Srmacklem /* 1844191783Srmacklem * For V4, check for lookup parent. 1845191783Srmacklem * Otherwise, get the component name. 1846191783Srmacklem */ 1847191783Srmacklem if ((nd->nd_flag & ND_NFSV4) && nd->nd_procnum == NFSV4OP_LOOKUPP) { 1848191783Srmacklem *tocp++ = '.'; 1849191783Srmacklem hash += ((u_char)'.'); 1850191783Srmacklem *tocp++ = '.'; 1851191783Srmacklem hash += ((u_char)'.'); 1852191783Srmacklem outlen = 2; 1853191783Srmacklem } else { 1854191783Srmacklem /* 1855191783Srmacklem * First, get the name length. 1856191783Srmacklem */ 1857191783Srmacklem NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 1858191783Srmacklem len = fxdr_unsigned(int, *tl); 1859191783Srmacklem if (len > NFS_MAXNAMLEN) { 1860191783Srmacklem nd->nd_repstat = NFSERR_NAMETOL; 1861224086Szack error = 0; 1862224086Szack goto nfsmout; 1863191783Srmacklem } else if (len <= 0) { 1864191783Srmacklem nd->nd_repstat = NFSERR_INVAL; 1865224086Szack error = 0; 1866224086Szack goto nfsmout; 1867191783Srmacklem } 1868191783Srmacklem 1869191783Srmacklem /* 1870191783Srmacklem * Now, copy the component name into the buffer. 1871191783Srmacklem */ 1872191783Srmacklem fromcp = nd->nd_dpos; 1873191783Srmacklem md = nd->nd_md; 1874191783Srmacklem rem = NFSMTOD(md, caddr_t) + mbuf_len(md) - fromcp; 1875191783Srmacklem for (i = 0; i < len; i++) { 1876191783Srmacklem while (rem == 0) { 1877191783Srmacklem md = mbuf_next(md); 1878224086Szack if (md == NULL) { 1879224086Szack error = EBADRPC; 1880224086Szack goto nfsmout; 1881224086Szack } 1882191783Srmacklem fromcp = NFSMTOD(md, caddr_t); 1883191783Srmacklem rem = mbuf_len(md); 1884191783Srmacklem } 1885191783Srmacklem if (*fromcp == '\0') { 1886191783Srmacklem nd->nd_repstat = EACCES; 1887224086Szack error = 0; 1888224086Szack goto nfsmout; 1889191783Srmacklem } 1890191783Srmacklem /* 1891191783Srmacklem * For lookups on the public filehandle, do some special 1892191783Srmacklem * processing on the name. (The public file handle is the 1893191783Srmacklem * root of the public file system for this server.) 1894191783Srmacklem */ 1895191783Srmacklem if (nd->nd_flag & ND_PUBLOOKUP) { 1896191783Srmacklem /* 1897191783Srmacklem * If the first char is ASCII, it is a canonical 1898191783Srmacklem * path, otherwise it is a native path. (RFC2054 1899191783Srmacklem * doesn't actually state what it is if the first 1900191783Srmacklem * char isn't ASCII or 0x80, so I assume native.) 1901191783Srmacklem * pubtype == 1 -> native path 1902191783Srmacklem * pubtype == 2 -> canonical path 1903191783Srmacklem */ 1904191783Srmacklem if (i == 0) { 1905191783Srmacklem if (*fromcp & 0x80) { 1906191783Srmacklem /* 1907191783Srmacklem * Since RFC2054 doesn't indicate 1908191783Srmacklem * that a native path of just 0x80 1909191783Srmacklem * isn't allowed, I'll replace the 1910191783Srmacklem * 0x80 with '/' instead of just 1911191783Srmacklem * throwing it away. 1912191783Srmacklem */ 1913191783Srmacklem *fromcp = '/'; 1914191783Srmacklem pubtype = 1; 1915191783Srmacklem } else { 1916191783Srmacklem pubtype = 2; 1917191783Srmacklem } 1918191783Srmacklem } 1919191783Srmacklem /* 1920191783Srmacklem * '/' only allowed in a native path 1921191783Srmacklem */ 1922191783Srmacklem if (*fromcp == '/' && pubtype != 1) { 1923191783Srmacklem nd->nd_repstat = EACCES; 1924224086Szack error = 0; 1925224086Szack goto nfsmout; 1926191783Srmacklem } 1927191783Srmacklem 1928191783Srmacklem /* 1929191783Srmacklem * For the special case of 2 hex digits after a 1930191783Srmacklem * '%' in an absolute path, calculate the value. 1931191783Srmacklem * percent == 1 -> indicates "get first hex digit" 1932191783Srmacklem * percent == 2 -> indicates "get second hex digit" 1933191783Srmacklem */ 1934191783Srmacklem if (percent > 0) { 1935191783Srmacklem digit = nfsrv_hexdigit(*fromcp, &error); 1936191783Srmacklem if (error) { 1937191783Srmacklem nd->nd_repstat = EACCES; 1938224086Szack error = 0; 1939224086Szack goto nfsmout; 1940191783Srmacklem } 1941191783Srmacklem if (percent == 1) { 1942191783Srmacklem val = (digit << 4); 1943191783Srmacklem percent = 2; 1944191783Srmacklem } else { 1945191783Srmacklem val += digit; 1946191783Srmacklem percent = 0; 1947191783Srmacklem *tocp++ = val; 1948191783Srmacklem hash += ((u_char)val); 1949191783Srmacklem outlen++; 1950191783Srmacklem } 1951191783Srmacklem } else { 1952191783Srmacklem if (*fromcp == '%' && pubtype == 2) { 1953191783Srmacklem /* 1954191783Srmacklem * Must be followed by 2 hex digits 1955191783Srmacklem */ 1956191783Srmacklem if ((len - i) < 3) { 1957191783Srmacklem nd->nd_repstat = EACCES; 1958224086Szack error = 0; 1959224086Szack goto nfsmout; 1960191783Srmacklem } 1961191783Srmacklem percent = 1; 1962191783Srmacklem } else { 1963191783Srmacklem *tocp++ = *fromcp; 1964191783Srmacklem hash += ((u_char)*fromcp); 1965191783Srmacklem outlen++; 1966191783Srmacklem } 1967191783Srmacklem } 1968191783Srmacklem } else { 1969191783Srmacklem /* 1970191783Srmacklem * Normal, non lookup on public, name. 1971191783Srmacklem */ 1972191783Srmacklem if (*fromcp == '/') { 1973191783Srmacklem if (nd->nd_flag & ND_NFSV4) 1974191783Srmacklem nd->nd_repstat = NFSERR_BADNAME; 1975191783Srmacklem else 1976191783Srmacklem nd->nd_repstat = EACCES; 1977224086Szack error = 0; 1978224086Szack goto nfsmout; 1979191783Srmacklem } 1980191783Srmacklem hash += ((u_char)*fromcp); 1981191783Srmacklem *tocp++ = *fromcp; 1982191783Srmacklem outlen++; 1983191783Srmacklem } 1984191783Srmacklem fromcp++; 1985191783Srmacklem rem--; 1986191783Srmacklem } 1987191783Srmacklem nd->nd_md = md; 1988191783Srmacklem nd->nd_dpos = fromcp; 1989191783Srmacklem i = NFSM_RNDUP(len) - len; 1990191783Srmacklem if (i > 0) { 1991191783Srmacklem if (rem >= i) { 1992191783Srmacklem nd->nd_dpos += i; 1993191783Srmacklem } else { 1994191783Srmacklem error = nfsm_advance(nd, i, rem); 1995191783Srmacklem if (error) 1996224086Szack goto nfsmout; 1997191783Srmacklem } 1998191783Srmacklem } 1999191783Srmacklem 2000191783Srmacklem /* 2001191783Srmacklem * For v4, don't allow lookups of '.' or '..' and 2002191783Srmacklem * also check for non-utf8 strings. 2003191783Srmacklem */ 2004191783Srmacklem if (nd->nd_flag & ND_NFSV4) { 2005191783Srmacklem if ((outlen == 1 && bufp[0] == '.') || 2006191783Srmacklem (outlen == 2 && bufp[0] == '.' && 2007191783Srmacklem bufp[1] == '.')) { 2008191783Srmacklem nd->nd_repstat = NFSERR_BADNAME; 2009224086Szack error = 0; 2010224086Szack goto nfsmout; 2011191783Srmacklem } 2012228260Srmacklem if (disable_checkutf8 == 0 && 2013228260Srmacklem nfsrv_checkutf8((u_int8_t *)bufp, outlen)) { 2014191783Srmacklem nd->nd_repstat = NFSERR_INVAL; 2015224086Szack error = 0; 2016224086Szack goto nfsmout; 2017191783Srmacklem } 2018191783Srmacklem } 2019191783Srmacklem } 2020191783Srmacklem *tocp = '\0'; 2021191783Srmacklem *outlenp = (size_t)outlen; 2022191783Srmacklem if (hashp != NULL) 2023191783Srmacklem *hashp = hash; 2024191783Srmacklemnfsmout: 2025224086Szack NFSEXITCODE2(error, nd); 2026191783Srmacklem return (error); 2027191783Srmacklem} 2028191783Srmacklem 2029191783Srmacklemvoid 2030191783Srmacklemnfsd_init(void) 2031191783Srmacklem{ 2032191783Srmacklem int i; 2033191783Srmacklem static int inited = 0; 2034191783Srmacklem 2035191783Srmacklem if (inited) 2036191783Srmacklem return; 2037191783Srmacklem inited = 1; 2038191783Srmacklem 2039191783Srmacklem /* 2040191783Srmacklem * Initialize client queues. Don't free/reinitialize 2041191783Srmacklem * them when nfsds are restarted. 2042191783Srmacklem */ 2043284216Srmacklem nfsclienthash = malloc(sizeof(struct nfsclienthashhead) * 2044284216Srmacklem nfsrv_clienthashsize, M_NFSDCLIENT, M_WAITOK | M_ZERO); 2045284216Srmacklem for (i = 0; i < nfsrv_clienthashsize; i++) 2046191783Srmacklem LIST_INIT(&nfsclienthash[i]); 2047284216Srmacklem nfslockhash = malloc(sizeof(struct nfslockhashhead) * 2048284216Srmacklem nfsrv_lockhashsize, M_NFSDLOCKFILE, M_WAITOK | M_ZERO); 2049284216Srmacklem for (i = 0; i < nfsrv_lockhashsize; i++) 2050191783Srmacklem LIST_INIT(&nfslockhash[i]); 2051284216Srmacklem nfssessionhash = malloc(sizeof(struct nfssessionhash) * 2052284216Srmacklem nfsrv_sessionhashsize, M_NFSDSESSION, M_WAITOK | M_ZERO); 2053284216Srmacklem for (i = 0; i < nfsrv_sessionhashsize; i++) { 2054284216Srmacklem mtx_init(&nfssessionhash[i].mtx, "nfssm", NULL, MTX_DEF); 2055269398Srmacklem LIST_INIT(&nfssessionhash[i].list); 2056284216Srmacklem } 2057191783Srmacklem 2058191783Srmacklem /* and the v2 pubfh should be all zeros */ 2059191783Srmacklem NFSBZERO(nfs_v2pubfh, NFSX_V2FH); 2060191783Srmacklem} 2061191783Srmacklem 2062192121Srmacklem/* 2063192121Srmacklem * Check the v4 root exports. 2064192121Srmacklem * Return 0 if ok, 1 otherwise. 2065192121Srmacklem */ 2066192121Srmacklemint 2067192121Srmacklemnfsd_checkrootexp(struct nfsrv_descript *nd) 2068192121Srmacklem{ 2069192121Srmacklem 2070192121Srmacklem if ((nd->nd_flag & (ND_GSS | ND_EXAUTHSYS)) == ND_EXAUTHSYS) 2071192121Srmacklem return (0); 2072192121Srmacklem if ((nd->nd_flag & (ND_GSSINTEGRITY | ND_EXGSSINTEGRITY)) == 2073192121Srmacklem (ND_GSSINTEGRITY | ND_EXGSSINTEGRITY)) 2074192121Srmacklem return (0); 2075192121Srmacklem if ((nd->nd_flag & (ND_GSSPRIVACY | ND_EXGSSPRIVACY)) == 2076192121Srmacklem (ND_GSSPRIVACY | ND_EXGSSPRIVACY)) 2077192121Srmacklem return (0); 2078192121Srmacklem if ((nd->nd_flag & (ND_GSS | ND_GSSINTEGRITY | ND_GSSPRIVACY | 2079192121Srmacklem ND_EXGSS)) == (ND_GSS | ND_EXGSS)) 2080192121Srmacklem return (0); 2081192121Srmacklem return (1); 2082192121Srmacklem} 2083192121Srmacklem 2084269398Srmacklem/* 2085269398Srmacklem * Parse the first part of an NFSv4 compound to find out what the minor 2086269398Srmacklem * version# is. 2087269398Srmacklem */ 2088269398Srmacklemvoid 2089269398Srmacklemnfsd_getminorvers(struct nfsrv_descript *nd, u_char *tag, u_char **tagstrp, 2090269398Srmacklem int *taglenp, u_int32_t *minversp) 2091269398Srmacklem{ 2092269398Srmacklem uint32_t *tl; 2093269398Srmacklem int error = 0, taglen = -1; 2094269398Srmacklem u_char *tagstr = NULL; 2095269398Srmacklem 2096269398Srmacklem NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); 2097269398Srmacklem taglen = fxdr_unsigned(int, *tl); 2098269398Srmacklem if (taglen < 0 || taglen > NFSV4_OPAQUELIMIT) { 2099269398Srmacklem error = EBADRPC; 2100269398Srmacklem goto nfsmout; 2101269398Srmacklem } 2102269398Srmacklem if (taglen <= NFSV4_SMALLSTR) 2103269398Srmacklem tagstr = tag; 2104269398Srmacklem else 2105269398Srmacklem tagstr = malloc(taglen + 1, M_TEMP, M_WAITOK); 2106269398Srmacklem error = nfsrv_mtostr(nd, tagstr, taglen); 2107269398Srmacklem if (error != 0) 2108269398Srmacklem goto nfsmout; 2109269398Srmacklem NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); 2110269398Srmacklem *minversp = fxdr_unsigned(u_int32_t, *tl); 2111269398Srmacklem *tagstrp = tagstr; 2112269398Srmacklem if (*minversp == NFSV41_MINORVERSION) 2113269398Srmacklem nd->nd_flag |= ND_NFSV41; 2114269398Srmacklemnfsmout: 2115269398Srmacklem if (error != 0) { 2116269398Srmacklem if (tagstr != NULL && taglen > NFSV4_SMALLSTR) 2117269398Srmacklem free(tagstr, M_TEMP); 2118269398Srmacklem taglen = -1; 2119269398Srmacklem } 2120269398Srmacklem *taglenp = taglen; 2121269398Srmacklem} 2122269398Srmacklem 2123