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