xref: /freebsd-src/sys/fs/nfsserver/nfs_nfsdsubs.c (revision caa309c8811d62a24cd07e3a1f6e9095eaf10c90)
19ec7b004SRick Macklem /*-
251369649SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
351369649SPedro F. Giffuni  *
49ec7b004SRick Macklem  * Copyright (c) 1989, 1993
59ec7b004SRick Macklem  *	The Regents of the University of California.  All rights reserved.
69ec7b004SRick Macklem  *
79ec7b004SRick Macklem  * This code is derived from software contributed to Berkeley by
89ec7b004SRick Macklem  * Rick Macklem at The University of Guelph.
99ec7b004SRick Macklem  *
109ec7b004SRick Macklem  * Redistribution and use in source and binary forms, with or without
119ec7b004SRick Macklem  * modification, are permitted provided that the following conditions
129ec7b004SRick Macklem  * are met:
139ec7b004SRick Macklem  * 1. Redistributions of source code must retain the above copyright
149ec7b004SRick Macklem  *    notice, this list of conditions and the following disclaimer.
159ec7b004SRick Macklem  * 2. Redistributions in binary form must reproduce the above copyright
169ec7b004SRick Macklem  *    notice, this list of conditions and the following disclaimer in the
179ec7b004SRick Macklem  *    documentation and/or other materials provided with the distribution.
18fbbd9655SWarner Losh  * 3. Neither the name of the University nor the names of its contributors
199ec7b004SRick Macklem  *    may be used to endorse or promote products derived from this software
209ec7b004SRick Macklem  *    without specific prior written permission.
219ec7b004SRick Macklem  *
229ec7b004SRick Macklem  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
239ec7b004SRick Macklem  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
249ec7b004SRick Macklem  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
259ec7b004SRick Macklem  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
269ec7b004SRick Macklem  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
279ec7b004SRick Macklem  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
289ec7b004SRick Macklem  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
299ec7b004SRick Macklem  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
309ec7b004SRick Macklem  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
319ec7b004SRick Macklem  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
329ec7b004SRick Macklem  * SUCH DAMAGE.
339ec7b004SRick Macklem  *
349ec7b004SRick Macklem  */
359ec7b004SRick Macklem 
369ec7b004SRick Macklem #include <sys/cdefs.h>
379ec7b004SRick Macklem /*
389ec7b004SRick Macklem  * These functions support the macros and help fiddle mbuf chains for
399ec7b004SRick Macklem  * the nfs op functions. They do things like create the rpc header and
409ec7b004SRick Macklem  * copy data between mbuf chains and uio lists.
419ec7b004SRick Macklem  */
429ec7b004SRick Macklem #include <fs/nfs/nfsport.h>
439ec7b004SRick Macklem 
449ec7b004SRick Macklem extern u_int32_t newnfs_true, newnfs_false;
459ec7b004SRick Macklem extern int nfs_pubfhset;
461f54e596SRick Macklem extern int nfsrv_clienthashsize;
471f54e596SRick Macklem extern int nfsrv_lockhashsize;
481f54e596SRick Macklem extern int nfsrv_sessionhashsize;
499ec7b004SRick Macklem extern int nfsrv_useacl;
509ec7b004SRick Macklem extern uid_t nfsrv_defaultuid;
519ec7b004SRick Macklem extern gid_t nfsrv_defaultgid;
529ec7b004SRick Macklem 
537e44856eSRick Macklem NFSD_VNET_DECLARE(struct nfsclienthashhead *, nfsclienthash);
547e44856eSRick Macklem NFSD_VNET_DECLARE(struct nfslockhashhead *, nfslockhash);
557e44856eSRick Macklem NFSD_VNET_DECLARE(struct nfssessionhash *, nfssessionhash);
567e44856eSRick Macklem NFSD_VNET_DECLARE(int, nfs_rootfhset);
577e44856eSRick Macklem NFSD_VNET_DECLARE(uid_t, nfsrv_defaultuid);
587e44856eSRick Macklem NFSD_VNET_DECLARE(gid_t, nfsrv_defaultgid);
597e44856eSRick Macklem 
609ec7b004SRick Macklem char nfs_v2pubfh[NFSX_V2FH];
6190d2dfabSRick Macklem struct nfsdontlisthead nfsrv_dontlisthead;
6290d2dfabSRick Macklem struct nfslayouthead nfsrv_recalllisthead;
639ec7b004SRick Macklem static nfstype newnfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK,
649ec7b004SRick Macklem     NFNON, NFCHR, NFNON };
659ec7b004SRick Macklem extern nfstype nfsv34_type[9];
669ec7b004SRick Macklem 
67c59e4cc3SRick Macklem static u_int32_t nfsrv_isannfserr(u_int32_t);
68c59e4cc3SRick Macklem 
6934f2e649SRick Macklem SYSCTL_DECL(_vfs_nfsd);
7034f2e649SRick Macklem 
71f9246664SMarcelo Araujo static int	enable_checkutf8 = 1;
72f9246664SMarcelo Araujo SYSCTL_INT(_vfs_nfsd, OID_AUTO, enable_checkutf8, CTLFLAG_RW,
73f9246664SMarcelo Araujo     &enable_checkutf8, 0,
74f9246664SMarcelo Araujo     "Enable the NFSv4 check for the UTF8 compliant name required by rfc3530");
7534f2e649SRick Macklem 
763dd6b7ffSMarcelo Araujo static int    enable_nobodycheck = 1;
773dd6b7ffSMarcelo Araujo SYSCTL_INT(_vfs_nfsd, OID_AUTO, enable_nobodycheck, CTLFLAG_RW,
783dd6b7ffSMarcelo Araujo     &enable_nobodycheck, 0,
793dd6b7ffSMarcelo Araujo     "Enable the NFSv4 check when setting user nobody as owner");
803dd6b7ffSMarcelo Araujo 
813dd6b7ffSMarcelo Araujo static int    enable_nogroupcheck = 1;
823dd6b7ffSMarcelo Araujo SYSCTL_INT(_vfs_nfsd, OID_AUTO, enable_nogroupcheck, CTLFLAG_RW,
833dd6b7ffSMarcelo Araujo     &enable_nogroupcheck, 0,
843dd6b7ffSMarcelo Araujo     "Enable the NFSv4 check when setting group nogroup as owner");
853dd6b7ffSMarcelo Araujo 
869ec7b004SRick Macklem static char nfsrv_hexdigit(char, int *);
879ec7b004SRick Macklem 
889ec7b004SRick Macklem /*
899ec7b004SRick Macklem  * Maps errno values to nfs error numbers.
909ec7b004SRick Macklem  * Use NFSERR_IO as the catch all for ones not specifically defined in
91c59e4cc3SRick Macklem  * RFC 1094. (It now includes the errors added for NFSv3.)
929ec7b004SRick Macklem  */
93c59e4cc3SRick Macklem static u_char nfsrv_v2errmap[NFSERR_REMOTE] = {
949ec7b004SRick Macklem   NFSERR_PERM,	NFSERR_NOENT,	NFSERR_IO,	NFSERR_IO,	NFSERR_IO,
959ec7b004SRick Macklem   NFSERR_NXIO,	NFSERR_IO,	NFSERR_IO,	NFSERR_IO,	NFSERR_IO,
969ec7b004SRick Macklem   NFSERR_IO,	NFSERR_IO,	NFSERR_ACCES,	NFSERR_IO,	NFSERR_IO,
97c59e4cc3SRick Macklem   NFSERR_IO,	NFSERR_EXIST,	NFSERR_XDEV,	NFSERR_NODEV,	NFSERR_NOTDIR,
98c59e4cc3SRick Macklem   NFSERR_ISDIR,	NFSERR_INVAL,	NFSERR_IO,	NFSERR_IO,	NFSERR_IO,
999ec7b004SRick Macklem   NFSERR_IO,	NFSERR_FBIG,	NFSERR_NOSPC,	NFSERR_IO,	NFSERR_ROFS,
100c59e4cc3SRick Macklem   NFSERR_MLINK,	NFSERR_IO,	NFSERR_IO,	NFSERR_IO,	NFSERR_IO,
1019ec7b004SRick Macklem   NFSERR_IO,	NFSERR_IO,	NFSERR_IO,	NFSERR_IO,	NFSERR_IO,
1029ec7b004SRick Macklem   NFSERR_IO,	NFSERR_IO,	NFSERR_IO,	NFSERR_IO,	NFSERR_IO,
1039ec7b004SRick Macklem   NFSERR_IO,	NFSERR_IO,	NFSERR_IO,	NFSERR_IO,	NFSERR_IO,
1049ec7b004SRick Macklem   NFSERR_IO,	NFSERR_IO,	NFSERR_IO,	NFSERR_IO,	NFSERR_IO,
1059ec7b004SRick Macklem   NFSERR_IO,	NFSERR_IO,	NFSERR_IO,	NFSERR_IO,	NFSERR_IO,
1069ec7b004SRick Macklem   NFSERR_IO,	NFSERR_IO,	NFSERR_NAMETOL,	NFSERR_IO,	NFSERR_IO,
1079ec7b004SRick Macklem   NFSERR_NOTEMPTY, NFSERR_IO,	NFSERR_IO,	NFSERR_DQUOT,	NFSERR_STALE,
108c59e4cc3SRick Macklem   NFSERR_REMOTE,
1099ec7b004SRick Macklem };
1109ec7b004SRick Macklem 
1119ec7b004SRick Macklem /*
1129ec7b004SRick Macklem  * Maps errno values to nfs error numbers.
1139ec7b004SRick Macklem  * Although it is not obvious whether or not NFS clients really care if
1149ec7b004SRick Macklem  * a returned error value is in the specified list for the procedure, the
1159ec7b004SRick Macklem  * safest thing to do is filter them appropriately. For Version 2, the
1169ec7b004SRick Macklem  * X/Open XNFS document is the only specification that defines error values
1179ec7b004SRick Macklem  * for each RPC (The RFC simply lists all possible error values for all RPCs),
1189ec7b004SRick Macklem  * so I have decided to not do this for Version 2.
1199ec7b004SRick Macklem  * The first entry is the default error return and the rest are the valid
1209ec7b004SRick Macklem  * errors for that RPC in increasing numeric order.
1219ec7b004SRick Macklem  */
1229ec7b004SRick Macklem static short nfsv3err_null[] = {
1239ec7b004SRick Macklem 	0,
1249ec7b004SRick Macklem 	0,
1259ec7b004SRick Macklem };
1269ec7b004SRick Macklem 
1279ec7b004SRick Macklem static short nfsv3err_getattr[] = {
1289ec7b004SRick Macklem 	NFSERR_IO,
1299ec7b004SRick Macklem 	NFSERR_IO,
1309ec7b004SRick Macklem 	NFSERR_STALE,
1319ec7b004SRick Macklem 	NFSERR_BADHANDLE,
1329ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
1339ec7b004SRick Macklem 	NFSERR_DELAY,
1349ec7b004SRick Macklem 	0,
1359ec7b004SRick Macklem };
1369ec7b004SRick Macklem 
1379ec7b004SRick Macklem static short nfsv3err_setattr[] = {
1389ec7b004SRick Macklem 	NFSERR_IO,
1399ec7b004SRick Macklem 	NFSERR_ACCES,
1409ec7b004SRick Macklem 	NFSERR_PERM,
1419ec7b004SRick Macklem 	NFSERR_IO,
1429ec7b004SRick Macklem 	NFSERR_INVAL,
1439ec7b004SRick Macklem 	NFSERR_NOSPC,
1449ec7b004SRick Macklem 	NFSERR_ROFS,
1459ec7b004SRick Macklem 	NFSERR_DQUOT,
1469ec7b004SRick Macklem 	NFSERR_STALE,
1479ec7b004SRick Macklem 	NFSERR_BADHANDLE,
1489ec7b004SRick Macklem 	NFSERR_NOT_SYNC,
1499ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
1509ec7b004SRick Macklem 	NFSERR_DELAY,
1519ec7b004SRick Macklem 	0,
1529ec7b004SRick Macklem };
1539ec7b004SRick Macklem 
1549ec7b004SRick Macklem static short nfsv3err_lookup[] = {
1559ec7b004SRick Macklem 	NFSERR_IO,
1569ec7b004SRick Macklem 	NFSERR_NOENT,
1579ec7b004SRick Macklem 	NFSERR_ACCES,
1589ec7b004SRick Macklem 	NFSERR_NAMETOL,
1599ec7b004SRick Macklem 	NFSERR_IO,
1609ec7b004SRick Macklem 	NFSERR_NOTDIR,
1619ec7b004SRick Macklem 	NFSERR_STALE,
1629ec7b004SRick Macklem 	NFSERR_BADHANDLE,
1639ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
1649ec7b004SRick Macklem 	NFSERR_DELAY,
1659ec7b004SRick Macklem 	0,
1669ec7b004SRick Macklem };
1679ec7b004SRick Macklem 
1689ec7b004SRick Macklem static short nfsv3err_access[] = {
1699ec7b004SRick Macklem 	NFSERR_IO,
1709ec7b004SRick Macklem 	NFSERR_IO,
1719ec7b004SRick Macklem 	NFSERR_STALE,
1729ec7b004SRick Macklem 	NFSERR_BADHANDLE,
1739ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
1749ec7b004SRick Macklem 	NFSERR_DELAY,
1759ec7b004SRick Macklem 	0,
1769ec7b004SRick Macklem };
1779ec7b004SRick Macklem 
1789ec7b004SRick Macklem static short nfsv3err_readlink[] = {
1799ec7b004SRick Macklem 	NFSERR_IO,
1809ec7b004SRick Macklem 	NFSERR_IO,
1819ec7b004SRick Macklem 	NFSERR_ACCES,
1829ec7b004SRick Macklem 	NFSERR_INVAL,
1839ec7b004SRick Macklem 	NFSERR_STALE,
1849ec7b004SRick Macklem 	NFSERR_BADHANDLE,
1859ec7b004SRick Macklem 	NFSERR_NOTSUPP,
1869ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
1879ec7b004SRick Macklem 	NFSERR_DELAY,
1889ec7b004SRick Macklem 	0,
1899ec7b004SRick Macklem };
1909ec7b004SRick Macklem 
1919ec7b004SRick Macklem static short nfsv3err_read[] = {
1929ec7b004SRick Macklem 	NFSERR_IO,
1939ec7b004SRick Macklem 	NFSERR_IO,
1949ec7b004SRick Macklem 	NFSERR_NXIO,
1959ec7b004SRick Macklem 	NFSERR_ACCES,
1969ec7b004SRick Macklem 	NFSERR_INVAL,
1979ec7b004SRick Macklem 	NFSERR_STALE,
1989ec7b004SRick Macklem 	NFSERR_BADHANDLE,
1999ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
2009ec7b004SRick Macklem 	NFSERR_DELAY,
2019ec7b004SRick Macklem 	0,
2029ec7b004SRick Macklem };
2039ec7b004SRick Macklem 
2049ec7b004SRick Macklem static short nfsv3err_write[] = {
2059ec7b004SRick Macklem 	NFSERR_IO,
2069ec7b004SRick Macklem 	NFSERR_IO,
2079ec7b004SRick Macklem 	NFSERR_ACCES,
2089ec7b004SRick Macklem 	NFSERR_NOSPC,
2099ec7b004SRick Macklem 	NFSERR_INVAL,
2109ec7b004SRick Macklem 	NFSERR_FBIG,
2119ec7b004SRick Macklem 	NFSERR_ROFS,
2129ec7b004SRick Macklem 	NFSERR_DQUOT,
2139ec7b004SRick Macklem 	NFSERR_STALE,
2149ec7b004SRick Macklem 	NFSERR_BADHANDLE,
2159ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
2169ec7b004SRick Macklem 	NFSERR_DELAY,
2179ec7b004SRick Macklem 	0,
2189ec7b004SRick Macklem };
2199ec7b004SRick Macklem 
2209ec7b004SRick Macklem static short nfsv3err_create[] = {
2219ec7b004SRick Macklem 	NFSERR_IO,
2229ec7b004SRick Macklem 	NFSERR_EXIST,
2239ec7b004SRick Macklem 	NFSERR_NAMETOL,
2249ec7b004SRick Macklem 	NFSERR_ACCES,
2259ec7b004SRick Macklem 	NFSERR_IO,
2269ec7b004SRick Macklem 	NFSERR_NOTDIR,
2279ec7b004SRick Macklem 	NFSERR_NOSPC,
2289ec7b004SRick Macklem 	NFSERR_ROFS,
2299ec7b004SRick Macklem 	NFSERR_DQUOT,
2309ec7b004SRick Macklem 	NFSERR_STALE,
2319ec7b004SRick Macklem 	NFSERR_BADHANDLE,
2329ec7b004SRick Macklem 	NFSERR_NOTSUPP,
2339ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
2349ec7b004SRick Macklem 	NFSERR_DELAY,
2359ec7b004SRick Macklem 	0,
2369ec7b004SRick Macklem };
2379ec7b004SRick Macklem 
2389ec7b004SRick Macklem static short nfsv3err_mkdir[] = {
2399ec7b004SRick Macklem 	NFSERR_IO,
2409ec7b004SRick Macklem 	NFSERR_EXIST,
2419ec7b004SRick Macklem 	NFSERR_ACCES,
2429ec7b004SRick Macklem 	NFSERR_NAMETOL,
2439ec7b004SRick Macklem 	NFSERR_IO,
2449ec7b004SRick Macklem 	NFSERR_NOTDIR,
2459ec7b004SRick Macklem 	NFSERR_NOSPC,
2469ec7b004SRick Macklem 	NFSERR_ROFS,
2479ec7b004SRick Macklem 	NFSERR_DQUOT,
2489ec7b004SRick Macklem 	NFSERR_STALE,
2499ec7b004SRick Macklem 	NFSERR_BADHANDLE,
2509ec7b004SRick Macklem 	NFSERR_NOTSUPP,
2519ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
2529ec7b004SRick Macklem 	NFSERR_DELAY,
2539ec7b004SRick Macklem 	0,
2549ec7b004SRick Macklem };
2559ec7b004SRick Macklem 
2569ec7b004SRick Macklem static short nfsv3err_symlink[] = {
2579ec7b004SRick Macklem 	NFSERR_IO,
2589ec7b004SRick Macklem 	NFSERR_ACCES,
2599ec7b004SRick Macklem 	NFSERR_EXIST,
2609ec7b004SRick Macklem 	NFSERR_NAMETOL,
2619ec7b004SRick Macklem 	NFSERR_NOSPC,
2629ec7b004SRick Macklem 	NFSERR_IO,
2639ec7b004SRick Macklem 	NFSERR_NOTDIR,
2649ec7b004SRick Macklem 	NFSERR_ROFS,
2659ec7b004SRick Macklem 	NFSERR_DQUOT,
2669ec7b004SRick Macklem 	NFSERR_STALE,
2679ec7b004SRick Macklem 	NFSERR_BADHANDLE,
2689ec7b004SRick Macklem 	NFSERR_NOTSUPP,
2699ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
2709ec7b004SRick Macklem 	NFSERR_DELAY,
2719ec7b004SRick Macklem 	0,
2729ec7b004SRick Macklem };
2739ec7b004SRick Macklem 
2749ec7b004SRick Macklem static short nfsv3err_mknod[] = {
2759ec7b004SRick Macklem 	NFSERR_IO,
2769ec7b004SRick Macklem 	NFSERR_ACCES,
2779ec7b004SRick Macklem 	NFSERR_EXIST,
2789ec7b004SRick Macklem 	NFSERR_NAMETOL,
2799ec7b004SRick Macklem 	NFSERR_NOSPC,
2809ec7b004SRick Macklem 	NFSERR_IO,
2819ec7b004SRick Macklem 	NFSERR_NOTDIR,
2829ec7b004SRick Macklem 	NFSERR_ROFS,
2839ec7b004SRick Macklem 	NFSERR_DQUOT,
2849ec7b004SRick Macklem 	NFSERR_STALE,
2859ec7b004SRick Macklem 	NFSERR_BADHANDLE,
2869ec7b004SRick Macklem 	NFSERR_NOTSUPP,
2879ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
2889ec7b004SRick Macklem 	NFSERR_DELAY,
2899ec7b004SRick Macklem 	NFSERR_BADTYPE,
2909ec7b004SRick Macklem 	0,
2919ec7b004SRick Macklem };
2929ec7b004SRick Macklem 
2939ec7b004SRick Macklem static short nfsv3err_remove[] = {
2949ec7b004SRick Macklem 	NFSERR_IO,
2959ec7b004SRick Macklem 	NFSERR_NOENT,
2969ec7b004SRick Macklem 	NFSERR_ACCES,
2979ec7b004SRick Macklem 	NFSERR_NAMETOL,
2989ec7b004SRick Macklem 	NFSERR_IO,
2999ec7b004SRick Macklem 	NFSERR_NOTDIR,
3009ec7b004SRick Macklem 	NFSERR_ROFS,
3019ec7b004SRick Macklem 	NFSERR_STALE,
3029ec7b004SRick Macklem 	NFSERR_BADHANDLE,
3039ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
3049ec7b004SRick Macklem 	NFSERR_DELAY,
3059ec7b004SRick Macklem 	0,
3069ec7b004SRick Macklem };
3079ec7b004SRick Macklem 
3089ec7b004SRick Macklem static short nfsv3err_rmdir[] = {
3099ec7b004SRick Macklem 	NFSERR_IO,
3109ec7b004SRick Macklem 	NFSERR_NOENT,
3119ec7b004SRick Macklem 	NFSERR_ACCES,
3129ec7b004SRick Macklem 	NFSERR_NOTDIR,
3139ec7b004SRick Macklem 	NFSERR_NAMETOL,
3149ec7b004SRick Macklem 	NFSERR_IO,
3159ec7b004SRick Macklem 	NFSERR_EXIST,
3169ec7b004SRick Macklem 	NFSERR_INVAL,
3179ec7b004SRick Macklem 	NFSERR_ROFS,
3189ec7b004SRick Macklem 	NFSERR_NOTEMPTY,
3199ec7b004SRick Macklem 	NFSERR_STALE,
3209ec7b004SRick Macklem 	NFSERR_BADHANDLE,
3219ec7b004SRick Macklem 	NFSERR_NOTSUPP,
3229ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
3239ec7b004SRick Macklem 	NFSERR_DELAY,
3249ec7b004SRick Macklem 	0,
3259ec7b004SRick Macklem };
3269ec7b004SRick Macklem 
3279ec7b004SRick Macklem static short nfsv3err_rename[] = {
3289ec7b004SRick Macklem 	NFSERR_IO,
3299ec7b004SRick Macklem 	NFSERR_NOENT,
3309ec7b004SRick Macklem 	NFSERR_ACCES,
3319ec7b004SRick Macklem 	NFSERR_EXIST,
3329ec7b004SRick Macklem 	NFSERR_NAMETOL,
3339ec7b004SRick Macklem 	NFSERR_XDEV,
3349ec7b004SRick Macklem 	NFSERR_IO,
3359ec7b004SRick Macklem 	NFSERR_NOTDIR,
3369ec7b004SRick Macklem 	NFSERR_ISDIR,
3379ec7b004SRick Macklem 	NFSERR_INVAL,
3389ec7b004SRick Macklem 	NFSERR_NOSPC,
3399ec7b004SRick Macklem 	NFSERR_ROFS,
3409ec7b004SRick Macklem 	NFSERR_MLINK,
3419ec7b004SRick Macklem 	NFSERR_NOTEMPTY,
3429ec7b004SRick Macklem 	NFSERR_DQUOT,
3439ec7b004SRick Macklem 	NFSERR_STALE,
3449ec7b004SRick Macklem 	NFSERR_BADHANDLE,
3459ec7b004SRick Macklem 	NFSERR_NOTSUPP,
3469ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
3479ec7b004SRick Macklem 	NFSERR_DELAY,
3489ec7b004SRick Macklem 	0,
3499ec7b004SRick Macklem };
3509ec7b004SRick Macklem 
3519ec7b004SRick Macklem static short nfsv3err_link[] = {
3529ec7b004SRick Macklem 	NFSERR_IO,
3539ec7b004SRick Macklem 	NFSERR_ACCES,
3549ec7b004SRick Macklem 	NFSERR_EXIST,
3559ec7b004SRick Macklem 	NFSERR_NAMETOL,
3569ec7b004SRick Macklem 	NFSERR_IO,
3579ec7b004SRick Macklem 	NFSERR_XDEV,
3589ec7b004SRick Macklem 	NFSERR_NOTDIR,
3599ec7b004SRick Macklem 	NFSERR_INVAL,
3609ec7b004SRick Macklem 	NFSERR_NOSPC,
3619ec7b004SRick Macklem 	NFSERR_ROFS,
3629ec7b004SRick Macklem 	NFSERR_MLINK,
3639ec7b004SRick Macklem 	NFSERR_DQUOT,
3649ec7b004SRick Macklem 	NFSERR_STALE,
3659ec7b004SRick Macklem 	NFSERR_BADHANDLE,
3669ec7b004SRick Macklem 	NFSERR_NOTSUPP,
3679ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
3689ec7b004SRick Macklem 	NFSERR_DELAY,
3699ec7b004SRick Macklem 	0,
3709ec7b004SRick Macklem };
3719ec7b004SRick Macklem 
3729ec7b004SRick Macklem static short nfsv3err_readdir[] = {
3739ec7b004SRick Macklem 	NFSERR_IO,
3749ec7b004SRick Macklem 	NFSERR_ACCES,
3759ec7b004SRick Macklem 	NFSERR_NOTDIR,
3769ec7b004SRick Macklem 	NFSERR_IO,
3779ec7b004SRick Macklem 	NFSERR_STALE,
3789ec7b004SRick Macklem 	NFSERR_BADHANDLE,
3799ec7b004SRick Macklem 	NFSERR_BAD_COOKIE,
3809ec7b004SRick Macklem 	NFSERR_TOOSMALL,
3819ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
3829ec7b004SRick Macklem 	NFSERR_DELAY,
3839ec7b004SRick Macklem 	0,
3849ec7b004SRick Macklem };
3859ec7b004SRick Macklem 
3869ec7b004SRick Macklem static short nfsv3err_readdirplus[] = {
3879ec7b004SRick Macklem 	NFSERR_IO,
3889ec7b004SRick Macklem 	NFSERR_ACCES,
3899ec7b004SRick Macklem 	NFSERR_NOTDIR,
3909ec7b004SRick Macklem 	NFSERR_IO,
3919ec7b004SRick Macklem 	NFSERR_STALE,
3929ec7b004SRick Macklem 	NFSERR_BADHANDLE,
3939ec7b004SRick Macklem 	NFSERR_BAD_COOKIE,
3949ec7b004SRick Macklem 	NFSERR_NOTSUPP,
3959ec7b004SRick Macklem 	NFSERR_TOOSMALL,
3969ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
3979ec7b004SRick Macklem 	NFSERR_DELAY,
3989ec7b004SRick Macklem 	0,
3999ec7b004SRick Macklem };
4009ec7b004SRick Macklem 
4019ec7b004SRick Macklem static short nfsv3err_fsstat[] = {
4029ec7b004SRick Macklem 	NFSERR_IO,
4039ec7b004SRick Macklem 	NFSERR_IO,
4049ec7b004SRick Macklem 	NFSERR_STALE,
4059ec7b004SRick Macklem 	NFSERR_BADHANDLE,
4069ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
4079ec7b004SRick Macklem 	NFSERR_DELAY,
4089ec7b004SRick Macklem 	0,
4099ec7b004SRick Macklem };
4109ec7b004SRick Macklem 
4119ec7b004SRick Macklem static short nfsv3err_fsinfo[] = {
4129ec7b004SRick Macklem 	NFSERR_STALE,
4139ec7b004SRick Macklem 	NFSERR_STALE,
4149ec7b004SRick Macklem 	NFSERR_BADHANDLE,
4159ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
4169ec7b004SRick Macklem 	NFSERR_DELAY,
4179ec7b004SRick Macklem 	0,
4189ec7b004SRick Macklem };
4199ec7b004SRick Macklem 
4209ec7b004SRick Macklem static short nfsv3err_pathconf[] = {
4219ec7b004SRick Macklem 	NFSERR_STALE,
4229ec7b004SRick Macklem 	NFSERR_STALE,
4239ec7b004SRick Macklem 	NFSERR_BADHANDLE,
4249ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
4259ec7b004SRick Macklem 	NFSERR_DELAY,
4269ec7b004SRick Macklem 	0,
4279ec7b004SRick Macklem };
4289ec7b004SRick Macklem 
4299ec7b004SRick Macklem static short nfsv3err_commit[] = {
4309ec7b004SRick Macklem 	NFSERR_IO,
4319ec7b004SRick Macklem 	NFSERR_IO,
4329ec7b004SRick Macklem 	NFSERR_STALE,
4339ec7b004SRick Macklem 	NFSERR_BADHANDLE,
4349ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
4359ec7b004SRick Macklem 	NFSERR_DELAY,
4369ec7b004SRick Macklem 	0,
4379ec7b004SRick Macklem };
4389ec7b004SRick Macklem 
4399ec7b004SRick Macklem static short *nfsrv_v3errmap[] = {
4409ec7b004SRick Macklem 	nfsv3err_null,
4419ec7b004SRick Macklem 	nfsv3err_getattr,
4429ec7b004SRick Macklem 	nfsv3err_setattr,
4439ec7b004SRick Macklem 	nfsv3err_lookup,
4449ec7b004SRick Macklem 	nfsv3err_access,
4459ec7b004SRick Macklem 	nfsv3err_readlink,
4469ec7b004SRick Macklem 	nfsv3err_read,
4479ec7b004SRick Macklem 	nfsv3err_write,
4489ec7b004SRick Macklem 	nfsv3err_create,
4499ec7b004SRick Macklem 	nfsv3err_mkdir,
4509ec7b004SRick Macklem 	nfsv3err_symlink,
4519ec7b004SRick Macklem 	nfsv3err_mknod,
4529ec7b004SRick Macklem 	nfsv3err_remove,
4539ec7b004SRick Macklem 	nfsv3err_rmdir,
4549ec7b004SRick Macklem 	nfsv3err_rename,
4559ec7b004SRick Macklem 	nfsv3err_link,
4569ec7b004SRick Macklem 	nfsv3err_readdir,
4579ec7b004SRick Macklem 	nfsv3err_readdirplus,
4589ec7b004SRick Macklem 	nfsv3err_fsstat,
4599ec7b004SRick Macklem 	nfsv3err_fsinfo,
4609ec7b004SRick Macklem 	nfsv3err_pathconf,
4619ec7b004SRick Macklem 	nfsv3err_commit,
4629ec7b004SRick Macklem };
4639ec7b004SRick Macklem 
4649ec7b004SRick Macklem /*
4659ec7b004SRick Macklem  * And the same for V4.
4669ec7b004SRick Macklem  */
4679ec7b004SRick Macklem static short nfsv4err_null[] = {
4689ec7b004SRick Macklem 	0,
4699ec7b004SRick Macklem 	0,
4709ec7b004SRick Macklem };
4719ec7b004SRick Macklem 
4729ec7b004SRick Macklem static short nfsv4err_access[] = {
4739ec7b004SRick Macklem 	NFSERR_IO,
4749ec7b004SRick Macklem 	NFSERR_ACCES,
4759ec7b004SRick Macklem 	NFSERR_BADHANDLE,
4769ec7b004SRick Macklem 	NFSERR_BADXDR,
4779ec7b004SRick Macklem 	NFSERR_DELAY,
4789ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
4799ec7b004SRick Macklem 	NFSERR_INVAL,
4809ec7b004SRick Macklem 	NFSERR_IO,
4819ec7b004SRick Macklem 	NFSERR_MOVED,
4829ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
4839ec7b004SRick Macklem 	NFSERR_RESOURCE,
4849ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
4859ec7b004SRick Macklem 	NFSERR_STALE,
4869ec7b004SRick Macklem 	0,
4879ec7b004SRick Macklem };
4889ec7b004SRick Macklem 
4899ec7b004SRick Macklem static short nfsv4err_close[] = {
4909ec7b004SRick Macklem 	NFSERR_EXPIRED,
4919ec7b004SRick Macklem 	NFSERR_ADMINREVOKED,
4929ec7b004SRick Macklem 	NFSERR_BADHANDLE,
4939ec7b004SRick Macklem 	NFSERR_BADSEQID,
4949ec7b004SRick Macklem 	NFSERR_BADSTATEID,
4959ec7b004SRick Macklem 	NFSERR_BADXDR,
4969ec7b004SRick Macklem 	NFSERR_DELAY,
4979ec7b004SRick Macklem 	NFSERR_EXPIRED,
4989ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
4999ec7b004SRick Macklem 	NFSERR_INVAL,
5009ec7b004SRick Macklem 	NFSERR_ISDIR,
5019ec7b004SRick Macklem 	NFSERR_LEASEMOVED,
5029ec7b004SRick Macklem 	NFSERR_LOCKSHELD,
5039ec7b004SRick Macklem 	NFSERR_MOVED,
5049ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
5059ec7b004SRick Macklem 	NFSERR_OLDSTATEID,
5069ec7b004SRick Macklem 	NFSERR_RESOURCE,
5079ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
5089ec7b004SRick Macklem 	NFSERR_STALE,
5099ec7b004SRick Macklem 	NFSERR_STALESTATEID,
5109ec7b004SRick Macklem 	0,
5119ec7b004SRick Macklem };
5129ec7b004SRick Macklem 
5139ec7b004SRick Macklem static short nfsv4err_commit[] = {
5149ec7b004SRick Macklem 	NFSERR_IO,
5159ec7b004SRick Macklem 	NFSERR_ACCES,
5169ec7b004SRick Macklem 	NFSERR_BADHANDLE,
5179ec7b004SRick Macklem 	NFSERR_BADXDR,
5189ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
5199ec7b004SRick Macklem 	NFSERR_INVAL,
5209ec7b004SRick Macklem 	NFSERR_IO,
5219ec7b004SRick Macklem 	NFSERR_ISDIR,
5229ec7b004SRick Macklem 	NFSERR_MOVED,
5239ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
5249ec7b004SRick Macklem 	NFSERR_RESOURCE,
5259ec7b004SRick Macklem 	NFSERR_ROFS,
5269ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
5279ec7b004SRick Macklem 	NFSERR_STALE,
5289ec7b004SRick Macklem 	0,
5299ec7b004SRick Macklem };
5309ec7b004SRick Macklem 
5319ec7b004SRick Macklem static short nfsv4err_create[] = {
5329ec7b004SRick Macklem 	NFSERR_IO,
5339ec7b004SRick Macklem 	NFSERR_ACCES,
5349ec7b004SRick Macklem 	NFSERR_ATTRNOTSUPP,
5359ec7b004SRick Macklem 	NFSERR_BADCHAR,
5369ec7b004SRick Macklem 	NFSERR_BADHANDLE,
5379ec7b004SRick Macklem 	NFSERR_BADNAME,
5389ec7b004SRick Macklem 	NFSERR_BADOWNER,
5399ec7b004SRick Macklem 	NFSERR_BADTYPE,
5409ec7b004SRick Macklem 	NFSERR_BADXDR,
5419ec7b004SRick Macklem 	NFSERR_DELAY,
5429ec7b004SRick Macklem 	NFSERR_DQUOT,
5439ec7b004SRick Macklem 	NFSERR_EXIST,
5449ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
5459ec7b004SRick Macklem 	NFSERR_INVAL,
5469ec7b004SRick Macklem 	NFSERR_IO,
5479ec7b004SRick Macklem 	NFSERR_MOVED,
5489ec7b004SRick Macklem 	NFSERR_NAMETOL,
5499ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
5509ec7b004SRick Macklem 	NFSERR_NOSPC,
5519ec7b004SRick Macklem 	NFSERR_NOTDIR,
5529ec7b004SRick Macklem 	NFSERR_PERM,
5539ec7b004SRick Macklem 	NFSERR_RESOURCE,
5549ec7b004SRick Macklem 	NFSERR_ROFS,
5559ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
5569ec7b004SRick Macklem 	NFSERR_STALE,
5579ec7b004SRick Macklem 	0,
5589ec7b004SRick Macklem };
5599ec7b004SRick Macklem 
5609ec7b004SRick Macklem static short nfsv4err_delegpurge[] = {
5619ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
5629ec7b004SRick Macklem 	NFSERR_BADXDR,
5639ec7b004SRick Macklem 	NFSERR_NOTSUPP,
5649ec7b004SRick Macklem 	NFSERR_LEASEMOVED,
5659ec7b004SRick Macklem 	NFSERR_MOVED,
5669ec7b004SRick Macklem 	NFSERR_RESOURCE,
5679ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
5689ec7b004SRick Macklem 	NFSERR_STALECLIENTID,
5699ec7b004SRick Macklem 	0,
5709ec7b004SRick Macklem };
5719ec7b004SRick Macklem 
5729ec7b004SRick Macklem static short nfsv4err_delegreturn[] = {
5739ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
5749ec7b004SRick Macklem 	NFSERR_ADMINREVOKED,
5759ec7b004SRick Macklem 	NFSERR_BADSTATEID,
5769ec7b004SRick Macklem 	NFSERR_BADXDR,
5779ec7b004SRick Macklem 	NFSERR_EXPIRED,
5789ec7b004SRick Macklem 	NFSERR_INVAL,
5799ec7b004SRick Macklem 	NFSERR_LEASEMOVED,
5809ec7b004SRick Macklem 	NFSERR_MOVED,
5819ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
5829ec7b004SRick Macklem 	NFSERR_NOTSUPP,
5839ec7b004SRick Macklem 	NFSERR_OLDSTATEID,
5849ec7b004SRick Macklem 	NFSERR_RESOURCE,
5859ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
5869ec7b004SRick Macklem 	NFSERR_STALE,
5879ec7b004SRick Macklem 	NFSERR_STALESTATEID,
5889ec7b004SRick Macklem 	0,
5899ec7b004SRick Macklem };
5909ec7b004SRick Macklem 
5919ec7b004SRick Macklem static short nfsv4err_getattr[] = {
5929ec7b004SRick Macklem 	NFSERR_IO,
5939ec7b004SRick Macklem 	NFSERR_ACCES,
5949ec7b004SRick Macklem 	NFSERR_BADHANDLE,
5959ec7b004SRick Macklem 	NFSERR_BADXDR,
5969ec7b004SRick Macklem 	NFSERR_DELAY,
5979ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
5989ec7b004SRick Macklem 	NFSERR_INVAL,
5999ec7b004SRick Macklem 	NFSERR_IO,
6009ec7b004SRick Macklem 	NFSERR_MOVED,
6019ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
6029ec7b004SRick Macklem 	NFSERR_RESOURCE,
6039ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
6049ec7b004SRick Macklem 	NFSERR_STALE,
6059ec7b004SRick Macklem 	0,
6069ec7b004SRick Macklem };
6079ec7b004SRick Macklem 
6089ec7b004SRick Macklem static short nfsv4err_getfh[] = {
6099ec7b004SRick Macklem 	NFSERR_BADHANDLE,
6109ec7b004SRick Macklem 	NFSERR_BADHANDLE,
6119ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
6129ec7b004SRick Macklem 	NFSERR_MOVED,
6139ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
6149ec7b004SRick Macklem 	NFSERR_RESOURCE,
6159ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
6169ec7b004SRick Macklem 	NFSERR_STALE,
6179ec7b004SRick Macklem 	0,
6189ec7b004SRick Macklem };
6199ec7b004SRick Macklem 
6209ec7b004SRick Macklem static short nfsv4err_link[] = {
6219ec7b004SRick Macklem 	NFSERR_IO,
6229ec7b004SRick Macklem 	NFSERR_ACCES,
6239ec7b004SRick Macklem 	NFSERR_BADCHAR,
6249ec7b004SRick Macklem 	NFSERR_BADHANDLE,
6259ec7b004SRick Macklem 	NFSERR_BADNAME,
6269ec7b004SRick Macklem 	NFSERR_BADXDR,
6279ec7b004SRick Macklem 	NFSERR_DELAY,
6289ec7b004SRick Macklem 	NFSERR_DQUOT,
6299ec7b004SRick Macklem 	NFSERR_EXIST,
6309ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
6319ec7b004SRick Macklem 	NFSERR_FILEOPEN,
6329ec7b004SRick Macklem 	NFSERR_INVAL,
6339ec7b004SRick Macklem 	NFSERR_IO,
6349ec7b004SRick Macklem 	NFSERR_ISDIR,
6359ec7b004SRick Macklem 	NFSERR_MLINK,
6369ec7b004SRick Macklem 	NFSERR_MOVED,
6379ec7b004SRick Macklem 	NFSERR_NAMETOL,
6389ec7b004SRick Macklem 	NFSERR_NOENT,
6399ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
6409ec7b004SRick Macklem 	NFSERR_NOSPC,
6419ec7b004SRick Macklem 	NFSERR_NOTDIR,
6429ec7b004SRick Macklem 	NFSERR_NOTSUPP,
6439ec7b004SRick Macklem 	NFSERR_RESOURCE,
6449ec7b004SRick Macklem 	NFSERR_ROFS,
6459ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
6469ec7b004SRick Macklem 	NFSERR_STALE,
6479ec7b004SRick Macklem 	NFSERR_WRONGSEC,
6489ec7b004SRick Macklem 	NFSERR_XDEV,
6499ec7b004SRick Macklem 	0,
6509ec7b004SRick Macklem };
6519ec7b004SRick Macklem 
6529ec7b004SRick Macklem static short nfsv4err_lock[] = {
6539ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
6549ec7b004SRick Macklem 	NFSERR_ACCES,
6559ec7b004SRick Macklem 	NFSERR_ADMINREVOKED,
6569ec7b004SRick Macklem 	NFSERR_BADHANDLE,
6579ec7b004SRick Macklem 	NFSERR_BADRANGE,
6589ec7b004SRick Macklem 	NFSERR_BADSEQID,
6599ec7b004SRick Macklem 	NFSERR_BADSTATEID,
6609ec7b004SRick Macklem 	NFSERR_BADXDR,
6619ec7b004SRick Macklem 	NFSERR_DEADLOCK,
6629ec7b004SRick Macklem 	NFSERR_DELAY,
6639ec7b004SRick Macklem 	NFSERR_DENIED,
6649ec7b004SRick Macklem 	NFSERR_EXPIRED,
6659ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
6669ec7b004SRick Macklem 	NFSERR_GRACE,
6679ec7b004SRick Macklem 	NFSERR_INVAL,
6689ec7b004SRick Macklem 	NFSERR_ISDIR,
6699ec7b004SRick Macklem 	NFSERR_LEASEMOVED,
6709ec7b004SRick Macklem 	NFSERR_LOCKNOTSUPP,
6719ec7b004SRick Macklem 	NFSERR_LOCKRANGE,
6729ec7b004SRick Macklem 	NFSERR_MOVED,
6739ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
6749ec7b004SRick Macklem 	NFSERR_NOGRACE,
6759ec7b004SRick Macklem 	NFSERR_OLDSTATEID,
6769ec7b004SRick Macklem 	NFSERR_OPENMODE,
6779ec7b004SRick Macklem 	NFSERR_RECLAIMBAD,
6789ec7b004SRick Macklem 	NFSERR_RECLAIMCONFLICT,
6799ec7b004SRick Macklem 	NFSERR_RESOURCE,
6809ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
6819ec7b004SRick Macklem 	NFSERR_STALE,
6829ec7b004SRick Macklem 	NFSERR_STALECLIENTID,
6839ec7b004SRick Macklem 	NFSERR_STALESTATEID,
6849ec7b004SRick Macklem 	0,
6859ec7b004SRick Macklem };
6869ec7b004SRick Macklem 
6879ec7b004SRick Macklem static short nfsv4err_lockt[] = {
6889ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
6899ec7b004SRick Macklem 	NFSERR_ACCES,
6909ec7b004SRick Macklem 	NFSERR_BADHANDLE,
6919ec7b004SRick Macklem 	NFSERR_BADRANGE,
6929ec7b004SRick Macklem 	NFSERR_BADXDR,
6939ec7b004SRick Macklem 	NFSERR_DELAY,
6949ec7b004SRick Macklem 	NFSERR_DENIED,
6959ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
6969ec7b004SRick Macklem 	NFSERR_GRACE,
6979ec7b004SRick Macklem 	NFSERR_INVAL,
6989ec7b004SRick Macklem 	NFSERR_ISDIR,
6999ec7b004SRick Macklem 	NFSERR_LEASEMOVED,
7009ec7b004SRick Macklem 	NFSERR_LOCKRANGE,
7019ec7b004SRick Macklem 	NFSERR_MOVED,
7029ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
7039ec7b004SRick Macklem 	NFSERR_RESOURCE,
7049ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
7059ec7b004SRick Macklem 	NFSERR_STALE,
7069ec7b004SRick Macklem 	NFSERR_STALECLIENTID,
7079ec7b004SRick Macklem 	0,
7089ec7b004SRick Macklem };
7099ec7b004SRick Macklem 
7109ec7b004SRick Macklem static short nfsv4err_locku[] = {
7119ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
7129ec7b004SRick Macklem 	NFSERR_ACCES,
7139ec7b004SRick Macklem 	NFSERR_ADMINREVOKED,
7149ec7b004SRick Macklem 	NFSERR_BADHANDLE,
7159ec7b004SRick Macklem 	NFSERR_BADRANGE,
7169ec7b004SRick Macklem 	NFSERR_BADSEQID,
7179ec7b004SRick Macklem 	NFSERR_BADSTATEID,
7189ec7b004SRick Macklem 	NFSERR_BADXDR,
7199ec7b004SRick Macklem 	NFSERR_EXPIRED,
7209ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
7219ec7b004SRick Macklem 	NFSERR_GRACE,
7229ec7b004SRick Macklem 	NFSERR_INVAL,
7239ec7b004SRick Macklem 	NFSERR_ISDIR,
7249ec7b004SRick Macklem 	NFSERR_LEASEMOVED,
7259ec7b004SRick Macklem 	NFSERR_LOCKRANGE,
7269ec7b004SRick Macklem 	NFSERR_MOVED,
7279ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
7289ec7b004SRick Macklem 	NFSERR_OLDSTATEID,
7299ec7b004SRick Macklem 	NFSERR_RESOURCE,
7309ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
7319ec7b004SRick Macklem 	NFSERR_STALE,
7329ec7b004SRick Macklem 	NFSERR_STALESTATEID,
7339ec7b004SRick Macklem 	0,
7349ec7b004SRick Macklem };
7359ec7b004SRick Macklem 
7369ec7b004SRick Macklem static short nfsv4err_lookup[] = {
7379ec7b004SRick Macklem 	NFSERR_IO,
7389ec7b004SRick Macklem 	NFSERR_ACCES,
7399ec7b004SRick Macklem 	NFSERR_BADCHAR,
7409ec7b004SRick Macklem 	NFSERR_BADHANDLE,
7419ec7b004SRick Macklem 	NFSERR_BADNAME,
7429ec7b004SRick Macklem 	NFSERR_BADXDR,
7439ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
7449ec7b004SRick Macklem 	NFSERR_INVAL,
7459ec7b004SRick Macklem 	NFSERR_IO,
7469ec7b004SRick Macklem 	NFSERR_MOVED,
7479ec7b004SRick Macklem 	NFSERR_NAMETOL,
7489ec7b004SRick Macklem 	NFSERR_NOENT,
7499ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
7509ec7b004SRick Macklem 	NFSERR_NOTDIR,
7519ec7b004SRick Macklem 	NFSERR_RESOURCE,
7529ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
7539ec7b004SRick Macklem 	NFSERR_STALE,
7549ec7b004SRick Macklem 	NFSERR_SYMLINK,
7559ec7b004SRick Macklem 	NFSERR_WRONGSEC,
7569ec7b004SRick Macklem 	0,
7579ec7b004SRick Macklem };
7589ec7b004SRick Macklem 
7599ec7b004SRick Macklem static short nfsv4err_lookupp[] = {
7609ec7b004SRick Macklem 	NFSERR_IO,
7619ec7b004SRick Macklem 	NFSERR_ACCES,
7629ec7b004SRick Macklem 	NFSERR_BADHANDLE,
7639ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
7649ec7b004SRick Macklem 	NFSERR_IO,
7659ec7b004SRick Macklem 	NFSERR_MOVED,
7669ec7b004SRick Macklem 	NFSERR_NOENT,
7679ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
7689ec7b004SRick Macklem 	NFSERR_NOTDIR,
7699ec7b004SRick Macklem 	NFSERR_RESOURCE,
7709ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
7719ec7b004SRick Macklem 	NFSERR_STALE,
7729ec7b004SRick Macklem 	0,
7739ec7b004SRick Macklem };
7749ec7b004SRick Macklem 
7759ec7b004SRick Macklem static short nfsv4err_nverify[] = {
7769ec7b004SRick Macklem 	NFSERR_IO,
7779ec7b004SRick Macklem 	NFSERR_ACCES,
7789ec7b004SRick Macklem 	NFSERR_ATTRNOTSUPP,
7799ec7b004SRick Macklem 	NFSERR_BADCHAR,
7809ec7b004SRick Macklem 	NFSERR_BADHANDLE,
7819ec7b004SRick Macklem 	NFSERR_BADXDR,
7829ec7b004SRick Macklem 	NFSERR_DELAY,
7839ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
7849ec7b004SRick Macklem 	NFSERR_INVAL,
7859ec7b004SRick Macklem 	NFSERR_IO,
7869ec7b004SRick Macklem 	NFSERR_MOVED,
7879ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
7889ec7b004SRick Macklem 	NFSERR_RESOURCE,
7899ec7b004SRick Macklem 	NFSERR_SAME,
7909ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
7919ec7b004SRick Macklem 	NFSERR_STALE,
7929ec7b004SRick Macklem 	0,
7939ec7b004SRick Macklem };
7949ec7b004SRick Macklem 
7959ec7b004SRick Macklem static short nfsv4err_open[] = {
7969ec7b004SRick Macklem 	NFSERR_IO,
7979ec7b004SRick Macklem 	NFSERR_ACCES,
7989ec7b004SRick Macklem 	NFSERR_ADMINREVOKED,
7999ec7b004SRick Macklem 	NFSERR_ATTRNOTSUPP,
8009ec7b004SRick Macklem 	NFSERR_BADCHAR,
8019ec7b004SRick Macklem 	NFSERR_BADHANDLE,
8029ec7b004SRick Macklem 	NFSERR_BADNAME,
8039ec7b004SRick Macklem 	NFSERR_BADOWNER,
8049ec7b004SRick Macklem 	NFSERR_BADSEQID,
8059ec7b004SRick Macklem 	NFSERR_BADXDR,
8069ec7b004SRick Macklem 	NFSERR_DELAY,
8079ec7b004SRick Macklem 	NFSERR_DQUOT,
8089ec7b004SRick Macklem 	NFSERR_EXIST,
8099ec7b004SRick Macklem 	NFSERR_EXPIRED,
8109ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
8119ec7b004SRick Macklem 	NFSERR_GRACE,
8129ec7b004SRick Macklem 	NFSERR_IO,
8139ec7b004SRick Macklem 	NFSERR_INVAL,
8149ec7b004SRick Macklem 	NFSERR_ISDIR,
8159ec7b004SRick Macklem 	NFSERR_LEASEMOVED,
8169ec7b004SRick Macklem 	NFSERR_MOVED,
8179ec7b004SRick Macklem 	NFSERR_NAMETOL,
8189ec7b004SRick Macklem 	NFSERR_NOENT,
8199ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
8209ec7b004SRick Macklem 	NFSERR_NOGRACE,
8219ec7b004SRick Macklem 	NFSERR_NOSPC,
8229ec7b004SRick Macklem 	NFSERR_NOTDIR,
8239ec7b004SRick Macklem 	NFSERR_NOTSUPP,
8249ec7b004SRick Macklem 	NFSERR_PERM,
8259ec7b004SRick Macklem 	NFSERR_RECLAIMBAD,
8269ec7b004SRick Macklem 	NFSERR_RECLAIMCONFLICT,
8279ec7b004SRick Macklem 	NFSERR_RESOURCE,
8289ec7b004SRick Macklem 	NFSERR_ROFS,
8299ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
8309ec7b004SRick Macklem 	NFSERR_SHAREDENIED,
8319ec7b004SRick Macklem 	NFSERR_STALE,
8329ec7b004SRick Macklem 	NFSERR_STALECLIENTID,
8339ec7b004SRick Macklem 	NFSERR_SYMLINK,
8349ec7b004SRick Macklem 	NFSERR_WRONGSEC,
8359ec7b004SRick Macklem 	0,
8369ec7b004SRick Macklem };
8379ec7b004SRick Macklem 
8389ec7b004SRick Macklem static short nfsv4err_openattr[] = {
8399ec7b004SRick Macklem 	NFSERR_IO,
8409ec7b004SRick Macklem 	NFSERR_ACCES,
8419ec7b004SRick Macklem 	NFSERR_BADHANDLE,
8429ec7b004SRick Macklem 	NFSERR_BADXDR,
8439ec7b004SRick Macklem 	NFSERR_DELAY,
8449ec7b004SRick Macklem 	NFSERR_DQUOT,
8459ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
8469ec7b004SRick Macklem 	NFSERR_IO,
8479ec7b004SRick Macklem 	NFSERR_MOVED,
8489ec7b004SRick Macklem 	NFSERR_NOENT,
8499ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
8509ec7b004SRick Macklem 	NFSERR_NOSPC,
8519ec7b004SRick Macklem 	NFSERR_NOTSUPP,
8529ec7b004SRick Macklem 	NFSERR_RESOURCE,
8539ec7b004SRick Macklem 	NFSERR_ROFS,
8549ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
8559ec7b004SRick Macklem 	NFSERR_STALE,
8569ec7b004SRick Macklem 	0,
8579ec7b004SRick Macklem };
8589ec7b004SRick Macklem 
8599ec7b004SRick Macklem static short nfsv4err_openconfirm[] = {
8609ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
8619ec7b004SRick Macklem 	NFSERR_ADMINREVOKED,
8629ec7b004SRick Macklem 	NFSERR_BADHANDLE,
8639ec7b004SRick Macklem 	NFSERR_BADSEQID,
8649ec7b004SRick Macklem 	NFSERR_BADSTATEID,
8659ec7b004SRick Macklem 	NFSERR_BADXDR,
8669ec7b004SRick Macklem 	NFSERR_EXPIRED,
8679ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
8689ec7b004SRick Macklem 	NFSERR_INVAL,
8699ec7b004SRick Macklem 	NFSERR_ISDIR,
8709ec7b004SRick Macklem 	NFSERR_MOVED,
8719ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
8729ec7b004SRick Macklem 	NFSERR_OLDSTATEID,
8739ec7b004SRick Macklem 	NFSERR_RESOURCE,
8749ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
8759ec7b004SRick Macklem 	NFSERR_STALE,
8769ec7b004SRick Macklem 	NFSERR_STALESTATEID,
8779ec7b004SRick Macklem 	0,
8789ec7b004SRick Macklem };
8799ec7b004SRick Macklem 
8809ec7b004SRick Macklem static short nfsv4err_opendowngrade[] = {
8819ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
8829ec7b004SRick Macklem 	NFSERR_ADMINREVOKED,
8839ec7b004SRick Macklem 	NFSERR_BADHANDLE,
8849ec7b004SRick Macklem 	NFSERR_BADSEQID,
8859ec7b004SRick Macklem 	NFSERR_BADSTATEID,
8869ec7b004SRick Macklem 	NFSERR_BADXDR,
8879ec7b004SRick Macklem 	NFSERR_EXPIRED,
8889ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
8899ec7b004SRick Macklem 	NFSERR_INVAL,
8909ec7b004SRick Macklem 	NFSERR_MOVED,
8919ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
8929ec7b004SRick Macklem 	NFSERR_OLDSTATEID,
8939ec7b004SRick Macklem 	NFSERR_RESOURCE,
8949ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
8959ec7b004SRick Macklem 	NFSERR_STALE,
8969ec7b004SRick Macklem 	NFSERR_STALESTATEID,
8979ec7b004SRick Macklem 	0,
8989ec7b004SRick Macklem };
8999ec7b004SRick Macklem 
9009ec7b004SRick Macklem static short nfsv4err_putfh[] = {
9019ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
9029ec7b004SRick Macklem 	NFSERR_BADHANDLE,
9039ec7b004SRick Macklem 	NFSERR_BADXDR,
9049ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
9059ec7b004SRick Macklem 	NFSERR_MOVED,
9069ec7b004SRick Macklem 	NFSERR_RESOURCE,
9079ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
9089ec7b004SRick Macklem 	NFSERR_STALE,
9099ec7b004SRick Macklem 	NFSERR_WRONGSEC,
9109ec7b004SRick Macklem 	0,
9119ec7b004SRick Macklem };
9129ec7b004SRick Macklem 
9139ec7b004SRick Macklem static short nfsv4err_putpubfh[] = {
9149ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
9159ec7b004SRick Macklem 	NFSERR_RESOURCE,
9169ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
9179ec7b004SRick Macklem 	NFSERR_WRONGSEC,
9189ec7b004SRick Macklem 	0,
9199ec7b004SRick Macklem };
9209ec7b004SRick Macklem 
9219ec7b004SRick Macklem static short nfsv4err_putrootfh[] = {
9229ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
9239ec7b004SRick Macklem 	NFSERR_RESOURCE,
9249ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
9259ec7b004SRick Macklem 	NFSERR_WRONGSEC,
9269ec7b004SRick Macklem 	0,
9279ec7b004SRick Macklem };
9289ec7b004SRick Macklem 
9299ec7b004SRick Macklem static short nfsv4err_read[] = {
9309ec7b004SRick Macklem 	NFSERR_IO,
9319ec7b004SRick Macklem 	NFSERR_ACCES,
9329ec7b004SRick Macklem 	NFSERR_ADMINREVOKED,
9339ec7b004SRick Macklem 	NFSERR_BADHANDLE,
9349ec7b004SRick Macklem 	NFSERR_BADSTATEID,
9359ec7b004SRick Macklem 	NFSERR_BADXDR,
9369ec7b004SRick Macklem 	NFSERR_DELAY,
9379ec7b004SRick Macklem 	NFSERR_EXPIRED,
9389ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
9399ec7b004SRick Macklem 	NFSERR_GRACE,
9409ec7b004SRick Macklem 	NFSERR_IO,
9419ec7b004SRick Macklem 	NFSERR_INVAL,
9429ec7b004SRick Macklem 	NFSERR_ISDIR,
9439ec7b004SRick Macklem 	NFSERR_LEASEMOVED,
9449ec7b004SRick Macklem 	NFSERR_LOCKED,
9459ec7b004SRick Macklem 	NFSERR_MOVED,
9469ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
9479ec7b004SRick Macklem 	NFSERR_NXIO,
9489ec7b004SRick Macklem 	NFSERR_OLDSTATEID,
9499ec7b004SRick Macklem 	NFSERR_OPENMODE,
9509ec7b004SRick Macklem 	NFSERR_RESOURCE,
9519ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
9529ec7b004SRick Macklem 	NFSERR_STALE,
9539ec7b004SRick Macklem 	NFSERR_STALESTATEID,
9549ec7b004SRick Macklem 	0,
9559ec7b004SRick Macklem };
9569ec7b004SRick Macklem 
9579ec7b004SRick Macklem static short nfsv4err_readdir[] = {
9589ec7b004SRick Macklem 	NFSERR_IO,
9599ec7b004SRick Macklem 	NFSERR_ACCES,
9609ec7b004SRick Macklem 	NFSERR_BADHANDLE,
9619ec7b004SRick Macklem 	NFSERR_BAD_COOKIE,
9629ec7b004SRick Macklem 	NFSERR_BADXDR,
9639ec7b004SRick Macklem 	NFSERR_DELAY,
9649ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
9659ec7b004SRick Macklem 	NFSERR_INVAL,
9669ec7b004SRick Macklem 	NFSERR_IO,
9679ec7b004SRick Macklem 	NFSERR_MOVED,
9689ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
9699ec7b004SRick Macklem 	NFSERR_NOTDIR,
9709ec7b004SRick Macklem 	NFSERR_NOTSAME,
9719ec7b004SRick Macklem 	NFSERR_RESOURCE,
9729ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
9739ec7b004SRick Macklem 	NFSERR_STALE,
9749ec7b004SRick Macklem 	NFSERR_TOOSMALL,
9759ec7b004SRick Macklem 	0,
9769ec7b004SRick Macklem };
9779ec7b004SRick Macklem 
9789ec7b004SRick Macklem static short nfsv4err_readlink[] = {
9799ec7b004SRick Macklem 	NFSERR_IO,
9809ec7b004SRick Macklem 	NFSERR_ACCES,
9819ec7b004SRick Macklem 	NFSERR_BADHANDLE,
9829ec7b004SRick Macklem 	NFSERR_DELAY,
9839ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
9849ec7b004SRick Macklem 	NFSERR_INVAL,
9859ec7b004SRick Macklem 	NFSERR_IO,
9869ec7b004SRick Macklem 	NFSERR_ISDIR,
9879ec7b004SRick Macklem 	NFSERR_MOVED,
9889ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
9899ec7b004SRick Macklem 	NFSERR_NOTSUPP,
9909ec7b004SRick Macklem 	NFSERR_RESOURCE,
9919ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
9929ec7b004SRick Macklem 	NFSERR_STALE,
9939ec7b004SRick Macklem 	0,
9949ec7b004SRick Macklem };
9959ec7b004SRick Macklem 
9969ec7b004SRick Macklem static short nfsv4err_remove[] = {
9979ec7b004SRick Macklem 	NFSERR_IO,
9989ec7b004SRick Macklem 	NFSERR_ACCES,
9999ec7b004SRick Macklem 	NFSERR_BADCHAR,
10009ec7b004SRick Macklem 	NFSERR_BADHANDLE,
10019ec7b004SRick Macklem 	NFSERR_BADNAME,
10029ec7b004SRick Macklem 	NFSERR_BADXDR,
10039ec7b004SRick Macklem 	NFSERR_DELAY,
10049ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
10059ec7b004SRick Macklem 	NFSERR_FILEOPEN,
10069ec7b004SRick Macklem 	NFSERR_INVAL,
10079ec7b004SRick Macklem 	NFSERR_IO,
10089ec7b004SRick Macklem 	NFSERR_MOVED,
10099ec7b004SRick Macklem 	NFSERR_NAMETOL,
10109ec7b004SRick Macklem 	NFSERR_NOENT,
10119ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
10129ec7b004SRick Macklem 	NFSERR_NOTDIR,
10139ec7b004SRick Macklem 	NFSERR_NOTEMPTY,
10149ec7b004SRick Macklem 	NFSERR_RESOURCE,
10159ec7b004SRick Macklem 	NFSERR_ROFS,
10169ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
10179ec7b004SRick Macklem 	NFSERR_STALE,
10189ec7b004SRick Macklem 	0,
10199ec7b004SRick Macklem };
10209ec7b004SRick Macklem 
10219ec7b004SRick Macklem static short nfsv4err_rename[] = {
10229ec7b004SRick Macklem 	NFSERR_IO,
10239ec7b004SRick Macklem 	NFSERR_ACCES,
10249ec7b004SRick Macklem 	NFSERR_BADCHAR,
10259ec7b004SRick Macklem 	NFSERR_BADHANDLE,
10269ec7b004SRick Macklem 	NFSERR_BADNAME,
10279ec7b004SRick Macklem 	NFSERR_BADXDR,
10289ec7b004SRick Macklem 	NFSERR_DELAY,
10299ec7b004SRick Macklem 	NFSERR_DQUOT,
10309ec7b004SRick Macklem 	NFSERR_EXIST,
10319ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
10329ec7b004SRick Macklem 	NFSERR_FILEOPEN,
10339ec7b004SRick Macklem 	NFSERR_INVAL,
10349ec7b004SRick Macklem 	NFSERR_IO,
10359ec7b004SRick Macklem 	NFSERR_MOVED,
10369ec7b004SRick Macklem 	NFSERR_NAMETOL,
10379ec7b004SRick Macklem 	NFSERR_NOENT,
10389ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
10399ec7b004SRick Macklem 	NFSERR_NOSPC,
10409ec7b004SRick Macklem 	NFSERR_NOTDIR,
10419ec7b004SRick Macklem 	NFSERR_NOTEMPTY,
10429ec7b004SRick Macklem 	NFSERR_RESOURCE,
10439ec7b004SRick Macklem 	NFSERR_ROFS,
10449ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
10459ec7b004SRick Macklem 	NFSERR_STALE,
10469ec7b004SRick Macklem 	NFSERR_WRONGSEC,
10479ec7b004SRick Macklem 	NFSERR_XDEV,
10489ec7b004SRick Macklem 	0,
10499ec7b004SRick Macklem };
10509ec7b004SRick Macklem 
10519ec7b004SRick Macklem static short nfsv4err_renew[] = {
10529ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
10539ec7b004SRick Macklem 	NFSERR_ACCES,
10549ec7b004SRick Macklem 	NFSERR_ADMINREVOKED,
10559ec7b004SRick Macklem 	NFSERR_BADXDR,
10569ec7b004SRick Macklem 	NFSERR_CBPATHDOWN,
10579ec7b004SRick Macklem 	NFSERR_EXPIRED,
10589ec7b004SRick Macklem 	NFSERR_LEASEMOVED,
10599ec7b004SRick Macklem 	NFSERR_RESOURCE,
10609ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
10619ec7b004SRick Macklem 	NFSERR_STALECLIENTID,
10629ec7b004SRick Macklem 	0,
10639ec7b004SRick Macklem };
10649ec7b004SRick Macklem 
10659ec7b004SRick Macklem static short nfsv4err_restorefh[] = {
10669ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
10679ec7b004SRick Macklem 	NFSERR_BADHANDLE,
10689ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
10699ec7b004SRick Macklem 	NFSERR_MOVED,
10709ec7b004SRick Macklem 	NFSERR_RESOURCE,
10719ec7b004SRick Macklem 	NFSERR_RESTOREFH,
10729ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
10739ec7b004SRick Macklem 	NFSERR_STALE,
10749ec7b004SRick Macklem 	NFSERR_WRONGSEC,
10759ec7b004SRick Macklem 	0,
10769ec7b004SRick Macklem };
10779ec7b004SRick Macklem 
10789ec7b004SRick Macklem static short nfsv4err_savefh[] = {
10799ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
10809ec7b004SRick Macklem 	NFSERR_BADHANDLE,
10819ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
10829ec7b004SRick Macklem 	NFSERR_MOVED,
10839ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
10849ec7b004SRick Macklem 	NFSERR_RESOURCE,
10859ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
10869ec7b004SRick Macklem 	NFSERR_STALE,
10879ec7b004SRick Macklem 	0,
10889ec7b004SRick Macklem };
10899ec7b004SRick Macklem 
10909ec7b004SRick Macklem static short nfsv4err_secinfo[] = {
10919ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
10929ec7b004SRick Macklem 	NFSERR_ACCES,
10939ec7b004SRick Macklem 	NFSERR_BADCHAR,
10949ec7b004SRick Macklem 	NFSERR_BADHANDLE,
10959ec7b004SRick Macklem 	NFSERR_BADNAME,
10969ec7b004SRick Macklem 	NFSERR_BADXDR,
10979ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
10989ec7b004SRick Macklem 	NFSERR_INVAL,
10999ec7b004SRick Macklem 	NFSERR_MOVED,
11009ec7b004SRick Macklem 	NFSERR_NAMETOL,
11019ec7b004SRick Macklem 	NFSERR_NOENT,
11029ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
11039ec7b004SRick Macklem 	NFSERR_NOTDIR,
11049ec7b004SRick Macklem 	NFSERR_RESOURCE,
11059ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
11069ec7b004SRick Macklem 	NFSERR_STALE,
11079ec7b004SRick Macklem 	0,
11089ec7b004SRick Macklem };
11099ec7b004SRick Macklem 
11109ec7b004SRick Macklem static short nfsv4err_setattr[] = {
11119ec7b004SRick Macklem 	NFSERR_IO,
11129ec7b004SRick Macklem 	NFSERR_ACCES,
11139ec7b004SRick Macklem 	NFSERR_ADMINREVOKED,
11149ec7b004SRick Macklem 	NFSERR_ATTRNOTSUPP,
11159ec7b004SRick Macklem 	NFSERR_BADCHAR,
11169ec7b004SRick Macklem 	NFSERR_BADHANDLE,
11179ec7b004SRick Macklem 	NFSERR_BADOWNER,
11189ec7b004SRick Macklem 	NFSERR_BADSTATEID,
11199ec7b004SRick Macklem 	NFSERR_BADXDR,
11209ec7b004SRick Macklem 	NFSERR_DELAY,
11219ec7b004SRick Macklem 	NFSERR_DQUOT,
11229ec7b004SRick Macklem 	NFSERR_EXPIRED,
11239ec7b004SRick Macklem 	NFSERR_FBIG,
11249ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
11259ec7b004SRick Macklem 	NFSERR_GRACE,
11269ec7b004SRick Macklem 	NFSERR_INVAL,
11279ec7b004SRick Macklem 	NFSERR_IO,
11289ec7b004SRick Macklem 	NFSERR_ISDIR,
11299ec7b004SRick Macklem 	NFSERR_LOCKED,
11309ec7b004SRick Macklem 	NFSERR_MOVED,
11319ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
11329ec7b004SRick Macklem 	NFSERR_NOSPC,
11339ec7b004SRick Macklem 	NFSERR_OLDSTATEID,
11349ec7b004SRick Macklem 	NFSERR_OPENMODE,
11359ec7b004SRick Macklem 	NFSERR_PERM,
11369ec7b004SRick Macklem 	NFSERR_RESOURCE,
11379ec7b004SRick Macklem 	NFSERR_ROFS,
11389ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
11399ec7b004SRick Macklem 	NFSERR_STALE,
11409ec7b004SRick Macklem 	NFSERR_STALESTATEID,
11419ec7b004SRick Macklem 	0,
11429ec7b004SRick Macklem };
11439ec7b004SRick Macklem 
11449ec7b004SRick Macklem static short nfsv4err_setclientid[] = {
11459ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
11469ec7b004SRick Macklem 	NFSERR_BADXDR,
11479ec7b004SRick Macklem 	NFSERR_CLIDINUSE,
11489ec7b004SRick Macklem 	NFSERR_INVAL,
11499ec7b004SRick Macklem 	NFSERR_RESOURCE,
11509ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
1151ae03cbd7SRick Macklem 	NFSERR_WRONGSEC,
11529ec7b004SRick Macklem 	0,
11539ec7b004SRick Macklem };
11549ec7b004SRick Macklem 
11559ec7b004SRick Macklem static short nfsv4err_setclientidconfirm[] = {
11569ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
11579ec7b004SRick Macklem 	NFSERR_BADXDR,
11589ec7b004SRick Macklem 	NFSERR_CLIDINUSE,
11599ec7b004SRick Macklem 	NFSERR_RESOURCE,
11609ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
11619ec7b004SRick Macklem 	NFSERR_STALECLIENTID,
11629ec7b004SRick Macklem 	0,
11639ec7b004SRick Macklem };
11649ec7b004SRick Macklem 
11659ec7b004SRick Macklem static short nfsv4err_verify[] = {
11669ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
11679ec7b004SRick Macklem 	NFSERR_ACCES,
11689ec7b004SRick Macklem 	NFSERR_ATTRNOTSUPP,
11699ec7b004SRick Macklem 	NFSERR_BADCHAR,
11709ec7b004SRick Macklem 	NFSERR_BADHANDLE,
11719ec7b004SRick Macklem 	NFSERR_BADXDR,
11729ec7b004SRick Macklem 	NFSERR_DELAY,
11739ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
11749ec7b004SRick Macklem 	NFSERR_INVAL,
11759ec7b004SRick Macklem 	NFSERR_MOVED,
11769ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
11779ec7b004SRick Macklem 	NFSERR_NOTSAME,
11789ec7b004SRick Macklem 	NFSERR_RESOURCE,
11799ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
11809ec7b004SRick Macklem 	NFSERR_STALE,
11819ec7b004SRick Macklem 	0,
11829ec7b004SRick Macklem };
11839ec7b004SRick Macklem 
11849ec7b004SRick Macklem static short nfsv4err_write[] = {
11859ec7b004SRick Macklem 	NFSERR_IO,
11869ec7b004SRick Macklem 	NFSERR_ACCES,
11879ec7b004SRick Macklem 	NFSERR_ADMINREVOKED,
11889ec7b004SRick Macklem 	NFSERR_BADHANDLE,
11899ec7b004SRick Macklem 	NFSERR_BADSTATEID,
11909ec7b004SRick Macklem 	NFSERR_BADXDR,
11919ec7b004SRick Macklem 	NFSERR_DELAY,
11929ec7b004SRick Macklem 	NFSERR_DQUOT,
11939ec7b004SRick Macklem 	NFSERR_EXPIRED,
11949ec7b004SRick Macklem 	NFSERR_FBIG,
11959ec7b004SRick Macklem 	NFSERR_FHEXPIRED,
11969ec7b004SRick Macklem 	NFSERR_GRACE,
11979ec7b004SRick Macklem 	NFSERR_INVAL,
11989ec7b004SRick Macklem 	NFSERR_IO,
11999ec7b004SRick Macklem 	NFSERR_ISDIR,
12009ec7b004SRick Macklem 	NFSERR_LEASEMOVED,
12019ec7b004SRick Macklem 	NFSERR_LOCKED,
12029ec7b004SRick Macklem 	NFSERR_MOVED,
12039ec7b004SRick Macklem 	NFSERR_NOFILEHANDLE,
12049ec7b004SRick Macklem 	NFSERR_NOSPC,
12059ec7b004SRick Macklem 	NFSERR_NXIO,
12069ec7b004SRick Macklem 	NFSERR_OLDSTATEID,
12079ec7b004SRick Macklem 	NFSERR_OPENMODE,
12089ec7b004SRick Macklem 	NFSERR_RESOURCE,
12099ec7b004SRick Macklem 	NFSERR_ROFS,
12109ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
12119ec7b004SRick Macklem 	NFSERR_STALE,
12129ec7b004SRick Macklem 	NFSERR_STALESTATEID,
12139ec7b004SRick Macklem 	0,
12149ec7b004SRick Macklem };
12159ec7b004SRick Macklem 
12169ec7b004SRick Macklem static short nfsv4err_releaselockowner[] = {
12179ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
12189ec7b004SRick Macklem 	NFSERR_ADMINREVOKED,
12199ec7b004SRick Macklem 	NFSERR_BADXDR,
12209ec7b004SRick Macklem 	NFSERR_EXPIRED,
12219ec7b004SRick Macklem 	NFSERR_LEASEMOVED,
12229ec7b004SRick Macklem 	NFSERR_LOCKSHELD,
12239ec7b004SRick Macklem 	NFSERR_RESOURCE,
12249ec7b004SRick Macklem 	NFSERR_SERVERFAULT,
12259ec7b004SRick Macklem 	NFSERR_STALECLIENTID,
12269ec7b004SRick Macklem 	0,
12279ec7b004SRick Macklem };
12289ec7b004SRick Macklem 
12299ec7b004SRick Macklem static short *nfsrv_v4errmap[] = {
12309ec7b004SRick Macklem 	nfsv4err_null,
12319ec7b004SRick Macklem 	nfsv4err_null,
12329ec7b004SRick Macklem 	nfsv4err_null,
12339ec7b004SRick Macklem 	nfsv4err_access,
12349ec7b004SRick Macklem 	nfsv4err_close,
12359ec7b004SRick Macklem 	nfsv4err_commit,
12369ec7b004SRick Macklem 	nfsv4err_create,
12379ec7b004SRick Macklem 	nfsv4err_delegpurge,
12389ec7b004SRick Macklem 	nfsv4err_delegreturn,
12399ec7b004SRick Macklem 	nfsv4err_getattr,
12409ec7b004SRick Macklem 	nfsv4err_getfh,
12419ec7b004SRick Macklem 	nfsv4err_link,
12429ec7b004SRick Macklem 	nfsv4err_lock,
12439ec7b004SRick Macklem 	nfsv4err_lockt,
12449ec7b004SRick Macklem 	nfsv4err_locku,
12459ec7b004SRick Macklem 	nfsv4err_lookup,
12469ec7b004SRick Macklem 	nfsv4err_lookupp,
12479ec7b004SRick Macklem 	nfsv4err_nverify,
12489ec7b004SRick Macklem 	nfsv4err_open,
12499ec7b004SRick Macklem 	nfsv4err_openattr,
12509ec7b004SRick Macklem 	nfsv4err_openconfirm,
12519ec7b004SRick Macklem 	nfsv4err_opendowngrade,
12529ec7b004SRick Macklem 	nfsv4err_putfh,
12539ec7b004SRick Macklem 	nfsv4err_putpubfh,
12549ec7b004SRick Macklem 	nfsv4err_putrootfh,
12559ec7b004SRick Macklem 	nfsv4err_read,
12569ec7b004SRick Macklem 	nfsv4err_readdir,
12579ec7b004SRick Macklem 	nfsv4err_readlink,
12589ec7b004SRick Macklem 	nfsv4err_remove,
12599ec7b004SRick Macklem 	nfsv4err_rename,
12609ec7b004SRick Macklem 	nfsv4err_renew,
12619ec7b004SRick Macklem 	nfsv4err_restorefh,
12629ec7b004SRick Macklem 	nfsv4err_savefh,
12639ec7b004SRick Macklem 	nfsv4err_secinfo,
12649ec7b004SRick Macklem 	nfsv4err_setattr,
12659ec7b004SRick Macklem 	nfsv4err_setclientid,
12669ec7b004SRick Macklem 	nfsv4err_setclientidconfirm,
12679ec7b004SRick Macklem 	nfsv4err_verify,
12689ec7b004SRick Macklem 	nfsv4err_write,
12699ec7b004SRick Macklem 	nfsv4err_releaselockowner,
12709ec7b004SRick Macklem };
12719ec7b004SRick Macklem 
12729ec7b004SRick Macklem /*
127318a48314SRick Macklem  * Trim tlen bytes off the end of the mbuf list and then ensure
127418a48314SRick Macklem  * the end of the last mbuf is nul filled to a long boundary,
127518a48314SRick Macklem  * as indicated by the value of "nul".
127618a48314SRick Macklem  * Return the last mbuf in the updated list and free and mbufs
127718a48314SRick Macklem  * that follow it in the original list.
127818a48314SRick Macklem  * This is somewhat different than the old nfsrv_adj() with
127918a48314SRick Macklem  * support for ext_pgs mbufs.  It frees the remaining mbufs
128018a48314SRick Macklem  * instead of setting them 0 length, since lists of ext_pgs
128118a48314SRick Macklem  * mbufs are all expected to be non-empty.
12829ec7b004SRick Macklem  */
128318a48314SRick Macklem struct mbuf *
1284ae070589SRick Macklem nfsrv_adj(struct mbuf *mp, int len, int nul)
12859ec7b004SRick Macklem {
128618a48314SRick Macklem 	struct mbuf *m, *m2;
128718a48314SRick Macklem 	vm_page_t pg;
128818a48314SRick Macklem 	int i, lastlen, pgno, plen, tlen, trim;
128918a48314SRick Macklem 	uint16_t off;
12909ec7b004SRick Macklem 	char *cp;
12919ec7b004SRick Macklem 
12929ec7b004SRick Macklem 	/*
129318a48314SRick Macklem 	 * Find the last mbuf after adjustment and
129418a48314SRick Macklem 	 * how much it needs to be adjusted by.
12959ec7b004SRick Macklem 	 */
129618a48314SRick Macklem 	tlen = 0;
12979ec7b004SRick Macklem 	m = mp;
12989ec7b004SRick Macklem 	for (;;) {
129918a48314SRick Macklem 		tlen += m->m_len;
130028e8046bSRick Macklem 		if (m->m_next == NULL)
13019ec7b004SRick Macklem 			break;
130228e8046bSRick Macklem 		m = m->m_next;
13039ec7b004SRick Macklem 	}
130418a48314SRick Macklem 	/* m is now the last mbuf and tlen the total length. */
130518a48314SRick Macklem 
130618a48314SRick Macklem 	if (len >= m->m_len) {
130718a48314SRick Macklem 		/* Need to trim away the last mbuf(s). */
130818a48314SRick Macklem 		i = tlen - len;
130918a48314SRick Macklem 		m = mp;
131018a48314SRick Macklem 		for (;;) {
131118a48314SRick Macklem 			if (m->m_len >= i)
13129ec7b004SRick Macklem 				break;
131318a48314SRick Macklem 			i -= m->m_len;
131418a48314SRick Macklem 			m = m->m_next;
13159ec7b004SRick Macklem 		}
131618a48314SRick Macklem 		lastlen = i;
131718a48314SRick Macklem 	} else
131818a48314SRick Macklem 		lastlen = m->m_len - len;
131918a48314SRick Macklem 
132018a48314SRick Macklem 	/*
132118a48314SRick Macklem 	 * m is now the last mbuf after trimming and its length needs to
132218a48314SRick Macklem 	 * be lastlen.
132318a48314SRick Macklem 	 * Adjust the last mbuf and set cp to point to where nuls must be
132418a48314SRick Macklem 	 * written.
132518a48314SRick Macklem 	 */
132618a48314SRick Macklem 	if ((m->m_flags & M_EXTPG) != 0) {
132718a48314SRick Macklem 		pgno = m->m_epg_npgs - 1;
132818a48314SRick Macklem 		off = (pgno == 0) ? m->m_epg_1st_off : 0;
132918a48314SRick Macklem 		plen = m_epg_pagelen(m, pgno, off);
133018a48314SRick Macklem 		if (m->m_len > lastlen) {
133118a48314SRick Macklem 			/* Trim this mbuf. */
133218a48314SRick Macklem 			trim = m->m_len - lastlen;
133318a48314SRick Macklem 			while (trim >= plen) {
133418a48314SRick Macklem 				KASSERT(pgno > 0,
133518a48314SRick Macklem 				    ("nfsrv_adj: freeing page 0"));
133618a48314SRick Macklem 				/* Free page. */
133718a48314SRick Macklem 				pg = PHYS_TO_VM_PAGE(m->m_epg_pa[pgno]);
133818a48314SRick Macklem 				vm_page_unwire_noq(pg);
133918a48314SRick Macklem 				vm_page_free(pg);
134018a48314SRick Macklem 				trim -= plen;
134118a48314SRick Macklem 				m->m_epg_npgs--;
134218a48314SRick Macklem 				pgno--;
134318a48314SRick Macklem 				off = (pgno == 0) ? m->m_epg_1st_off : 0;
134418a48314SRick Macklem 				plen = m_epg_pagelen(m, pgno, off);
13459ec7b004SRick Macklem 			}
134618a48314SRick Macklem 			plen -= trim;
134718a48314SRick Macklem 			m->m_epg_last_len = plen;
134818a48314SRick Macklem 			m->m_len = lastlen;
134918a48314SRick Macklem 		}
135018a48314SRick Macklem 		cp = (char *)(void *)PHYS_TO_DMAP(m->m_epg_pa[pgno]);
135118a48314SRick Macklem 		cp += off + plen - nul;
135218a48314SRick Macklem 	} else {
135318a48314SRick Macklem 		m->m_len = lastlen;
135418a48314SRick Macklem 		cp = mtod(m, char *) + m->m_len - nul;
135518a48314SRick Macklem 	}
135618a48314SRick Macklem 
135718a48314SRick Macklem 	/* Write the nul bytes. */
135818a48314SRick Macklem 	for (i = 0; i < nul; i++)
135918a48314SRick Macklem 		*cp++ = '\0';
136018a48314SRick Macklem 
136118a48314SRick Macklem 	/* Free up any mbufs past "m". */
136218a48314SRick Macklem 	m2 = m->m_next;
136318a48314SRick Macklem 	m->m_next = NULL;
136418a48314SRick Macklem 	if (m2 != NULL)
136518a48314SRick Macklem 		m_freem(m2);
136618a48314SRick Macklem 	return (m);
13679ec7b004SRick Macklem }
13689ec7b004SRick Macklem 
13699ec7b004SRick Macklem /*
13709ec7b004SRick Macklem  * Make these functions instead of macros, so that the kernel text size
13719ec7b004SRick Macklem  * doesn't get too big...
13729ec7b004SRick Macklem  */
1373b9cc3262SRyan Moeller void
13749ec7b004SRick Macklem nfsrv_wcc(struct nfsrv_descript *nd, int before_ret,
13759ec7b004SRick Macklem     struct nfsvattr *before_nvap, int after_ret, struct nfsvattr *after_nvap)
13769ec7b004SRick Macklem {
13779ec7b004SRick Macklem 	u_int32_t *tl;
13789ec7b004SRick Macklem 
13799ec7b004SRick Macklem 	if (before_ret) {
13809ec7b004SRick Macklem 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
13819ec7b004SRick Macklem 		*tl = newnfs_false;
13829ec7b004SRick Macklem 	} else {
13839ec7b004SRick Macklem 		NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
13849ec7b004SRick Macklem 		*tl++ = newnfs_true;
13859ec7b004SRick Macklem 		txdr_hyper(before_nvap->na_size, tl);
13869ec7b004SRick Macklem 		tl += 2;
13879ec7b004SRick Macklem 		txdr_nfsv3time(&(before_nvap->na_mtime), tl);
13889ec7b004SRick Macklem 		tl += 2;
13899ec7b004SRick Macklem 		txdr_nfsv3time(&(before_nvap->na_ctime), tl);
13909ec7b004SRick Macklem 	}
13919ec7b004SRick Macklem 	nfsrv_postopattr(nd, after_ret, after_nvap);
13929ec7b004SRick Macklem }
13939ec7b004SRick Macklem 
1394b9cc3262SRyan Moeller void
13959ec7b004SRick Macklem nfsrv_postopattr(struct nfsrv_descript *nd, int after_ret,
13969ec7b004SRick Macklem     struct nfsvattr *after_nvap)
13979ec7b004SRick Macklem {
13989ec7b004SRick Macklem 	u_int32_t *tl;
13999ec7b004SRick Macklem 
14009ec7b004SRick Macklem 	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
14019ec7b004SRick Macklem 	if (after_ret)
14029ec7b004SRick Macklem 		*tl = newnfs_false;
14039ec7b004SRick Macklem 	else {
14049ec7b004SRick Macklem 		*tl = newnfs_true;
14059ec7b004SRick Macklem 		nfsrv_fillattr(nd, after_nvap);
14069ec7b004SRick Macklem 	}
14079ec7b004SRick Macklem }
14089ec7b004SRick Macklem 
14099ec7b004SRick Macklem /*
14109ec7b004SRick Macklem  * Fill in file attributes for V2 and 3. For V4, call a separate
14119ec7b004SRick Macklem  * routine that sifts through all the attribute bits.
14129ec7b004SRick Macklem  */
1413b9cc3262SRyan Moeller void
14149ec7b004SRick Macklem nfsrv_fillattr(struct nfsrv_descript *nd, struct nfsvattr *nvap)
14159ec7b004SRick Macklem {
14169ec7b004SRick Macklem 	struct nfs_fattr *fp;
14179ec7b004SRick Macklem 	int fattr_size;
14189ec7b004SRick Macklem 
14199ec7b004SRick Macklem 	/*
14209ec7b004SRick Macklem 	 * Build space for the attribute structure.
14219ec7b004SRick Macklem 	 */
14229ec7b004SRick Macklem 	if (nd->nd_flag & ND_NFSV3)
14239ec7b004SRick Macklem 		fattr_size = NFSX_V3FATTR;
14249ec7b004SRick Macklem 	else
14259ec7b004SRick Macklem 		fattr_size = NFSX_V2FATTR;
14269ec7b004SRick Macklem 	NFSM_BUILD(fp, struct nfs_fattr *, fattr_size);
14279ec7b004SRick Macklem 
14289ec7b004SRick Macklem 	/*
14299ec7b004SRick Macklem 	 * Now just fill it all in.
14309ec7b004SRick Macklem 	 */
14319ec7b004SRick Macklem 	fp->fa_nlink = txdr_unsigned(nvap->na_nlink);
14329ec7b004SRick Macklem 	fp->fa_uid = txdr_unsigned(nvap->na_uid);
14339ec7b004SRick Macklem 	fp->fa_gid = txdr_unsigned(nvap->na_gid);
14349ec7b004SRick Macklem 	if (nd->nd_flag & ND_NFSV3) {
14359ec7b004SRick Macklem 		fp->fa_type = vtonfsv34_type(nvap->na_type);
14369ec7b004SRick Macklem 		fp->fa_mode = vtonfsv34_mode(nvap->na_mode);
143732fbc5d8SAlan Somers 		txdr_hyper(nvap->na_size, (uint32_t*)&fp->fa3_size);
143832fbc5d8SAlan Somers 		txdr_hyper(nvap->na_bytes, (uint32_t*)&fp->fa3_used);
14399ec7b004SRick Macklem 		fp->fa3_rdev.specdata1 = txdr_unsigned(NFSMAJOR(nvap->na_rdev));
14409ec7b004SRick Macklem 		fp->fa3_rdev.specdata2 = txdr_unsigned(NFSMINOR(nvap->na_rdev));
14419ec7b004SRick Macklem 		fp->fa3_fsid.nfsuquad[0] = 0;
14429ec7b004SRick Macklem 		fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(nvap->na_fsid);
144332fbc5d8SAlan Somers 		txdr_hyper(nvap->na_fileid, (uint32_t*)&fp->fa3_fileid);
14449ec7b004SRick Macklem 		txdr_nfsv3time(&nvap->na_atime, &fp->fa3_atime);
14459ec7b004SRick Macklem 		txdr_nfsv3time(&nvap->na_mtime, &fp->fa3_mtime);
14469ec7b004SRick Macklem 		txdr_nfsv3time(&nvap->na_ctime, &fp->fa3_ctime);
14479ec7b004SRick Macklem 	} else {
14489ec7b004SRick Macklem 		fp->fa_type = vtonfsv2_type(nvap->na_type);
14499ec7b004SRick Macklem 		fp->fa_mode = vtonfsv2_mode(nvap->na_type, nvap->na_mode);
14509ec7b004SRick Macklem 		fp->fa2_size = txdr_unsigned(nvap->na_size);
14519ec7b004SRick Macklem 		fp->fa2_blocksize = txdr_unsigned(nvap->na_blocksize);
14529ec7b004SRick Macklem 		if (nvap->na_type == VFIFO)
14539ec7b004SRick Macklem 			fp->fa2_rdev = 0xffffffff;
14549ec7b004SRick Macklem 		else
14559ec7b004SRick Macklem 			fp->fa2_rdev = txdr_unsigned(nvap->na_rdev);
14569ec7b004SRick Macklem 		fp->fa2_blocks = txdr_unsigned(nvap->na_bytes / NFS_FABLKSIZE);
14579ec7b004SRick Macklem 		fp->fa2_fsid = txdr_unsigned(nvap->na_fsid);
14589ec7b004SRick Macklem 		fp->fa2_fileid = txdr_unsigned(nvap->na_fileid);
14599ec7b004SRick Macklem 		txdr_nfsv2time(&nvap->na_atime, &fp->fa2_atime);
14609ec7b004SRick Macklem 		txdr_nfsv2time(&nvap->na_mtime, &fp->fa2_mtime);
14619ec7b004SRick Macklem 		txdr_nfsv2time(&nvap->na_ctime, &fp->fa2_ctime);
14629ec7b004SRick Macklem 	}
14639ec7b004SRick Macklem }
14649ec7b004SRick Macklem 
14659ec7b004SRick Macklem /*
14669ec7b004SRick Macklem  * This function gets a file handle out of an mbuf list.
14679ec7b004SRick Macklem  * It returns 0 for success, EBADRPC otherwise.
14689ec7b004SRick Macklem  * If sets the third flagp argument to 1 if the file handle is
14699ec7b004SRick Macklem  * the public file handle.
14709ec7b004SRick Macklem  * For NFSv4, if the length is incorrect, set nd_repstat == NFSERR_BADHANDLE
14719ec7b004SRick Macklem  */
1472b9cc3262SRyan Moeller int
14739ec7b004SRick Macklem nfsrv_mtofh(struct nfsrv_descript *nd, struct nfsrvfh *fhp)
14749ec7b004SRick Macklem {
14759ec7b004SRick Macklem 	u_int32_t *tl;
14769ec7b004SRick Macklem 	int error = 0, len, copylen;
14779ec7b004SRick Macklem 
14789ec7b004SRick Macklem 	if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
14799ec7b004SRick Macklem 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
14809ec7b004SRick Macklem 		len = fxdr_unsigned(int, *tl);
14819ec7b004SRick Macklem 		if (len == 0 && nfs_pubfhset && (nd->nd_flag & ND_NFSV3) &&
14829ec7b004SRick Macklem 		    nd->nd_procnum == NFSPROC_LOOKUP) {
14839ec7b004SRick Macklem 			nd->nd_flag |= ND_PUBLOOKUP;
1484a9285ae5SZack Kirsch 			goto nfsmout;
14859ec7b004SRick Macklem 		}
148690d2dfabSRick Macklem 		copylen = len;
148790d2dfabSRick Macklem 
148890d2dfabSRick Macklem 		/* If len == NFSX_V4PNFSFH the RPC is a pNFS DS one. */
148990d2dfabSRick Macklem 		if (len == NFSX_V4PNFSFH && (nd->nd_flag & ND_NFSV41) != 0) {
149090d2dfabSRick Macklem 			copylen = NFSX_MYFH;
149190d2dfabSRick Macklem 			len = NFSM_RNDUP(len);
149290d2dfabSRick Macklem 			nd->nd_flag |= ND_DSSERVER;
149390d2dfabSRick Macklem 		} else if (len < NFSRV_MINFH || len > NFSRV_MAXFH) {
14949ec7b004SRick Macklem 			if (nd->nd_flag & ND_NFSV4) {
14959ec7b004SRick Macklem 			    if (len > 0 && len <= NFSX_V4FHMAX) {
14969ec7b004SRick Macklem 				error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
14979ec7b004SRick Macklem 				if (error)
1498a9285ae5SZack Kirsch 					goto nfsmout;
14999ec7b004SRick Macklem 				nd->nd_repstat = NFSERR_BADHANDLE;
1500a9285ae5SZack Kirsch 				goto nfsmout;
15019ec7b004SRick Macklem 			    } else {
1502a9285ae5SZack Kirsch 				    error = EBADRPC;
1503a9285ae5SZack Kirsch 				    goto nfsmout;
15049ec7b004SRick Macklem 			    }
15059ec7b004SRick Macklem 			} else {
1506a9285ae5SZack Kirsch 				error = EBADRPC;
1507a9285ae5SZack Kirsch 				goto nfsmout;
15089ec7b004SRick Macklem 			}
15099ec7b004SRick Macklem 		}
15109ec7b004SRick Macklem 	} else {
15119ec7b004SRick Macklem 		/*
15129ec7b004SRick Macklem 		 * For NFSv2, the file handle is always 32 bytes on the
15139ec7b004SRick Macklem 		 * wire, but this server only cares about the first
15149ec7b004SRick Macklem 		 * NFSRV_MAXFH bytes.
15159ec7b004SRick Macklem 		 */
15169ec7b004SRick Macklem 		len = NFSX_V2FH;
15179ec7b004SRick Macklem 		copylen = NFSRV_MAXFH;
15189ec7b004SRick Macklem 	}
15199ec7b004SRick Macklem 	NFSM_DISSECT(tl, u_int32_t *, len);
15209ec7b004SRick Macklem 	if ((nd->nd_flag & ND_NFSV2) && nfs_pubfhset &&
15219ec7b004SRick Macklem 	    nd->nd_procnum == NFSPROC_LOOKUP &&
15229ec7b004SRick Macklem 	    !NFSBCMP((caddr_t)tl, nfs_v2pubfh, NFSX_V2FH)) {
15239ec7b004SRick Macklem 		nd->nd_flag |= ND_PUBLOOKUP;
1524a9285ae5SZack Kirsch 		goto nfsmout;
15259ec7b004SRick Macklem 	}
15269ec7b004SRick Macklem 	NFSBCOPY(tl, (caddr_t)fhp->nfsrvfh_data, copylen);
15279ec7b004SRick Macklem 	fhp->nfsrvfh_len = copylen;
15289ec7b004SRick Macklem nfsmout:
1529a9285ae5SZack Kirsch 	NFSEXITCODE2(error, nd);
15309ec7b004SRick Macklem 	return (error);
15319ec7b004SRick Macklem }
15329ec7b004SRick Macklem 
15339ec7b004SRick Macklem /*
15349ec7b004SRick Macklem  * Map errnos to NFS error numbers. For Version 3 and 4 also filter out error
15359ec7b004SRick Macklem  * numbers not specified for the associated procedure.
15369ec7b004SRick Macklem  * NFSPROC_NOOP is a special case, where the high order bits of nd_repstat
15379ec7b004SRick Macklem  * should be cleared. NFSPROC_NOOP is used to return errors when a valid
15389ec7b004SRick Macklem  * RPC procedure is not involved.
15399ec7b004SRick Macklem  * Returns the error number in XDR.
15409ec7b004SRick Macklem  */
1541b9cc3262SRyan Moeller int
15429ec7b004SRick Macklem nfsd_errmap(struct nfsrv_descript *nd)
15439ec7b004SRick Macklem {
15449ec7b004SRick Macklem 	short *defaulterrp, *errp;
15459ec7b004SRick Macklem 
15469ec7b004SRick Macklem 	if (!nd->nd_repstat)
15479ec7b004SRick Macklem 		return (0);
1548984c71f9SRick Macklem 	if ((nd->nd_repstat & NFSERR_AUTHERR) != 0)
1549984c71f9SRick Macklem 		return (txdr_unsigned(NFSERR_ACCES));
15509ec7b004SRick Macklem 	if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
15519ec7b004SRick Macklem 		if (nd->nd_procnum == NFSPROC_NOOP)
15529ec7b004SRick Macklem 			return (txdr_unsigned(nd->nd_repstat & 0xffff));
15539ec7b004SRick Macklem 		if (nd->nd_flag & ND_NFSV3)
15549ec7b004SRick Macklem 		    errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
15559ec7b004SRick Macklem 		else if (nd->nd_repstat == EBADRPC)
15569ec7b004SRick Macklem 			return (txdr_unsigned(NFSERR_BADXDR));
15579ec7b004SRick Macklem 		else if (nd->nd_repstat == NFSERR_MINORVERMISMATCH ||
15589ec7b004SRick Macklem 			 nd->nd_repstat == NFSERR_OPILLEGAL)
15599ec7b004SRick Macklem 			return (txdr_unsigned(nd->nd_repstat));
156005a39c2cSRick Macklem 		else if (nd->nd_repstat == NFSERR_REPLYFROMCACHE)
156105a39c2cSRick Macklem 			return (txdr_unsigned(NFSERR_IO));
1562c59e4cc3SRick Macklem 		else if ((nd->nd_flag & ND_NFSV41) != 0) {
1563c59e4cc3SRick Macklem 			if (nd->nd_repstat == EOPNOTSUPP)
1564c59e4cc3SRick Macklem 				nd->nd_repstat = NFSERR_NOTSUPP;
1565c59e4cc3SRick Macklem 			nd->nd_repstat = nfsrv_isannfserr(nd->nd_repstat);
1566c59e4cc3SRick Macklem 			return (txdr_unsigned(nd->nd_repstat));
1567c59e4cc3SRick Macklem 		} else
15689ec7b004SRick Macklem 		    errp = defaulterrp = nfsrv_v4errmap[nd->nd_procnum];
15699ec7b004SRick Macklem 		while (*++errp)
15709ec7b004SRick Macklem 			if (*errp == nd->nd_repstat)
15719ec7b004SRick Macklem 				return (txdr_unsigned(nd->nd_repstat));
15729ec7b004SRick Macklem 		return (txdr_unsigned(*defaulterrp));
15739ec7b004SRick Macklem 	}
1574c59e4cc3SRick Macklem 	if (nd->nd_repstat <= NFSERR_REMOTE)
15759ec7b004SRick Macklem 		return (txdr_unsigned(nfsrv_v2errmap[nd->nd_repstat - 1]));
15769ec7b004SRick Macklem 	return (txdr_unsigned(NFSERR_IO));
15779ec7b004SRick Macklem }
15789ec7b004SRick Macklem 
15799ec7b004SRick Macklem /*
1580c59e4cc3SRick Macklem  * Check to see if the error is a valid NFS one. If not, replace it with
1581c59e4cc3SRick Macklem  * NFSERR_IO.
1582c59e4cc3SRick Macklem  */
1583c59e4cc3SRick Macklem static u_int32_t
1584c59e4cc3SRick Macklem nfsrv_isannfserr(u_int32_t errval)
1585c59e4cc3SRick Macklem {
1586c59e4cc3SRick Macklem 
1587c59e4cc3SRick Macklem 	if (errval == NFSERR_OK)
1588c59e4cc3SRick Macklem 		return (errval);
1589c057a378SRick Macklem 	if (errval >= NFSERR_BADHANDLE && errval <= NFSERR_MAXERRVAL)
1590c59e4cc3SRick Macklem 		return (errval);
1591c59e4cc3SRick Macklem 	if (errval > 0 && errval <= NFSERR_REMOTE)
1592c59e4cc3SRick Macklem 		return (nfsrv_v2errmap[errval - 1]);
1593c59e4cc3SRick Macklem 	return (NFSERR_IO);
1594c59e4cc3SRick Macklem }
1595c59e4cc3SRick Macklem 
1596c59e4cc3SRick Macklem /*
15979ec7b004SRick Macklem  * Check to see if setting a uid/gid is permitted when creating a new
15989ec7b004SRick Macklem  * file object. (Called when uid and/or gid is specified in the
15999ec7b004SRick Macklem  * settable attributes for V4.
16009ec7b004SRick Macklem  */
1601b9cc3262SRyan Moeller int
16029ec7b004SRick Macklem nfsrv_checkuidgid(struct nfsrv_descript *nd, struct nfsvattr *nvap)
16039ec7b004SRick Macklem {
1604a9285ae5SZack Kirsch 	int error = 0;
16059ec7b004SRick Macklem 
16069ec7b004SRick Macklem 	/*
16079ec7b004SRick Macklem 	 * If not setting either uid nor gid, it's OK.
16089ec7b004SRick Macklem 	 */
16099ec7b004SRick Macklem 	if (NFSVNO_NOTSETUID(nvap) && NFSVNO_NOTSETGID(nvap))
1610a9285ae5SZack Kirsch 		goto out;
16117e44856eSRick Macklem 	if ((NFSVNO_ISSETUID(nvap) &&
16127e44856eSRick Macklem 	     nvap->na_uid == NFSD_VNET(nfsrv_defaultuid) &&
16137e44856eSRick Macklem              enable_nobodycheck == 1) ||
16147e44856eSRick Macklem 	    (NFSVNO_ISSETGID(nvap) &&
16157e44856eSRick Macklem 	     nvap->na_gid == NFSD_VNET(nfsrv_defaultgid) &&
16163dd6b7ffSMarcelo Araujo              enable_nogroupcheck == 1)) {
1617a9285ae5SZack Kirsch 		error = NFSERR_BADOWNER;
1618a9285ae5SZack Kirsch 		goto out;
1619a9285ae5SZack Kirsch 	}
16209ec7b004SRick Macklem 	if (nd->nd_cred->cr_uid == 0)
1621a9285ae5SZack Kirsch 		goto out;
16229ec7b004SRick Macklem 	if ((NFSVNO_ISSETUID(nvap) && nvap->na_uid != nd->nd_cred->cr_uid) ||
1623*caa309c8SRick Macklem 	    (NFSVNO_ISSETGID(nvap) &&
16249ec7b004SRick Macklem 	    !groupmember(nvap->na_gid, nd->nd_cred)))
1625a9285ae5SZack Kirsch 		error = NFSERR_PERM;
1626a9285ae5SZack Kirsch 
1627a9285ae5SZack Kirsch out:
1628a9285ae5SZack Kirsch 	NFSEXITCODE2(error, nd);
1629a9285ae5SZack Kirsch 	return (error);
16309ec7b004SRick Macklem }
16319ec7b004SRick Macklem 
16329ec7b004SRick Macklem /*
16339ec7b004SRick Macklem  * and this routine fixes up the settable attributes for V4 if allowed
16349ec7b004SRick Macklem  * by nfsrv_checkuidgid().
16359ec7b004SRick Macklem  */
1636b9cc3262SRyan Moeller void
16379ec7b004SRick Macklem nfsrv_fixattr(struct nfsrv_descript *nd, vnode_t vp,
16389ec7b004SRick Macklem     struct nfsvattr *nvap, NFSACL_T *aclp, NFSPROC_T *p, nfsattrbit_t *attrbitp,
16399ec7b004SRick Macklem     struct nfsexstuff *exp)
16409ec7b004SRick Macklem {
16419ec7b004SRick Macklem 	int change = 0;
16429ec7b004SRick Macklem 	struct nfsvattr nva;
16439ec7b004SRick Macklem 	uid_t tuid;
16449ec7b004SRick Macklem 	int error;
16459ec7b004SRick Macklem 	nfsattrbit_t nattrbits;
16469ec7b004SRick Macklem 
16479ec7b004SRick Macklem 	/*
16489ec7b004SRick Macklem 	 * Maybe this should be done for V2 and 3 but it never has been
16499ec7b004SRick Macklem 	 * and nobody seems to be upset, so I think it's best not to change
16509ec7b004SRick Macklem 	 * the V2 and 3 semantics.
16519ec7b004SRick Macklem 	 */
16529ec7b004SRick Macklem 	if ((nd->nd_flag & ND_NFSV4) == 0)
1653a9285ae5SZack Kirsch 		goto out;
16549ec7b004SRick Macklem 	NFSVNO_ATTRINIT(&nva);
16559ec7b004SRick Macklem 	NFSZERO_ATTRBIT(&nattrbits);
16569ec7b004SRick Macklem 	tuid = nd->nd_cred->cr_uid;
16579ec7b004SRick Macklem 	if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNER) &&
16589ec7b004SRick Macklem 	    NFSVNO_ISSETUID(nvap) &&
16599ec7b004SRick Macklem 	    nvap->na_uid != nd->nd_cred->cr_uid) {
16609ec7b004SRick Macklem 		if (nd->nd_cred->cr_uid == 0) {
16619ec7b004SRick Macklem 			nva.na_uid = nvap->na_uid;
16629ec7b004SRick Macklem 			change++;
16639ec7b004SRick Macklem 			NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_OWNER);
16649ec7b004SRick Macklem 		} else {
16659ec7b004SRick Macklem 			NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_OWNER);
16669ec7b004SRick Macklem 		}
16679ec7b004SRick Macklem 	}
16689ec7b004SRick Macklem 	if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_TIMEACCESSSET) &&
16699ec7b004SRick Macklem 	    NFSVNO_ISSETATIME(nvap)) {
16709ec7b004SRick Macklem 		nva.na_atime = nvap->na_atime;
16719ec7b004SRick Macklem 		change++;
16729ec7b004SRick Macklem 		NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_TIMEACCESSSET);
16739ec7b004SRick Macklem 	}
16749ec7b004SRick Macklem 	if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_TIMEMODIFYSET) &&
16759ec7b004SRick Macklem 	    NFSVNO_ISSETMTIME(nvap)) {
16769ec7b004SRick Macklem 		nva.na_mtime = nvap->na_mtime;
16779ec7b004SRick Macklem 		change++;
16789ec7b004SRick Macklem 		NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_TIMEMODIFYSET);
16799ec7b004SRick Macklem 	}
16809ec7b004SRick Macklem 	if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP) &&
16819ec7b004SRick Macklem 	    NFSVNO_ISSETGID(nvap)) {
1682*caa309c8SRick Macklem 		if (groupmember(nvap->na_gid, nd->nd_cred)) {
16839ec7b004SRick Macklem 			nd->nd_cred->cr_uid = 0;
16849ec7b004SRick Macklem 			nva.na_gid = nvap->na_gid;
16859ec7b004SRick Macklem 			change++;
16869ec7b004SRick Macklem 			NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_OWNERGROUP);
16879ec7b004SRick Macklem 		} else {
16889ec7b004SRick Macklem 			NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP);
16899ec7b004SRick Macklem 		}
16909ec7b004SRick Macklem 	}
16919ec7b004SRick Macklem 	if (change) {
16929ec7b004SRick Macklem 		error = nfsvno_setattr(vp, &nva, nd->nd_cred, p, exp);
16939ec7b004SRick Macklem 		if (error) {
16949ec7b004SRick Macklem 			NFSCLRALL_ATTRBIT(attrbitp, &nattrbits);
16959ec7b004SRick Macklem 		}
16969ec7b004SRick Macklem 	}
16979ec7b004SRick Macklem 	if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SIZE) &&
16989ec7b004SRick Macklem 	    NFSVNO_ISSETSIZE(nvap) && nvap->na_size != (u_quad_t)0) {
16999ec7b004SRick Macklem 		NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_SIZE);
17009ec7b004SRick Macklem 	}
17019ec7b004SRick Macklem #ifdef NFS4_ACL_EXTATTR_NAME
17029ec7b004SRick Macklem 	if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ACL) &&
17039ec7b004SRick Macklem 	    nfsrv_useacl != 0 && aclp != NULL) {
17049ec7b004SRick Macklem 		if (aclp->acl_cnt > 0) {
17059ec7b004SRick Macklem 			error = nfsrv_setacl(vp, aclp, nd->nd_cred, p);
17069ec7b004SRick Macklem 			if (error) {
17079ec7b004SRick Macklem 				NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_ACL);
17089ec7b004SRick Macklem 			}
17099ec7b004SRick Macklem 		}
17109ec7b004SRick Macklem 	} else
17119ec7b004SRick Macklem #endif
17129ec7b004SRick Macklem 	NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_ACL);
17139ec7b004SRick Macklem 	nd->nd_cred->cr_uid = tuid;
1714a9285ae5SZack Kirsch 
1715a9285ae5SZack Kirsch out:
1716a9285ae5SZack Kirsch 	NFSEXITCODE2(0, nd);
17179ec7b004SRick Macklem }
17189ec7b004SRick Macklem 
17199ec7b004SRick Macklem /*
17209ec7b004SRick Macklem  * Translate an ASCII hex digit to it's binary value. Return -1 if the
17219ec7b004SRick Macklem  * char isn't a hex digit.
17229ec7b004SRick Macklem  */
17239ec7b004SRick Macklem static char
17249ec7b004SRick Macklem nfsrv_hexdigit(char c, int *err)
17259ec7b004SRick Macklem {
17269ec7b004SRick Macklem 
17279ec7b004SRick Macklem 	*err = 0;
17289ec7b004SRick Macklem 	if (c >= '0' && c <= '9')
17299ec7b004SRick Macklem 		return (c - '0');
17309ec7b004SRick Macklem 	if (c >= 'a' && c <= 'f')
17319ec7b004SRick Macklem 		return (c - 'a' + ((char)10));
17329ec7b004SRick Macklem 	if (c >= 'A' && c <= 'F')
17339ec7b004SRick Macklem 		return (c - 'A' + ((char)10));
17349ec7b004SRick Macklem 	/* Not valid ! */
17359ec7b004SRick Macklem 	*err = 1;
17369ec7b004SRick Macklem 	return (1);	/* BOGUS */
17379ec7b004SRick Macklem }
17389ec7b004SRick Macklem 
17399ec7b004SRick Macklem /*
17409ec7b004SRick Macklem  * Check to see if NFSERR_MOVED can be returned for this op. Return 1 iff
17419ec7b004SRick Macklem  * it can be.
17429ec7b004SRick Macklem  */
1743b9cc3262SRyan Moeller int
17449ec7b004SRick Macklem nfsrv_errmoved(int op)
17459ec7b004SRick Macklem {
17469ec7b004SRick Macklem 	short *errp;
17479ec7b004SRick Macklem 
17489ec7b004SRick Macklem 	errp = nfsrv_v4errmap[op];
17499ec7b004SRick Macklem 	while (*errp != 0) {
17509ec7b004SRick Macklem 		if (*errp == NFSERR_MOVED)
17519ec7b004SRick Macklem 			return (1);
17529ec7b004SRick Macklem 		errp++;
17539ec7b004SRick Macklem 	}
17549ec7b004SRick Macklem 	return (0);
17559ec7b004SRick Macklem }
17569ec7b004SRick Macklem 
17579ec7b004SRick Macklem /*
17589ec7b004SRick Macklem  * Fill in attributes for a Referral.
17599ec7b004SRick Macklem  * (Return the number of bytes of XDR created.)
17609ec7b004SRick Macklem  */
1761b9cc3262SRyan Moeller int
17629ec7b004SRick Macklem nfsrv_putreferralattr(struct nfsrv_descript *nd, nfsattrbit_t *retbitp,
17639ec7b004SRick Macklem     struct nfsreferral *refp, int getattr, int *reterrp)
17649ec7b004SRick Macklem {
17659ec7b004SRick Macklem 	u_int32_t *tl, *retnump;
17669ec7b004SRick Macklem 	u_char *cp, *cp2;
17679ec7b004SRick Macklem 	int prefixnum, retnum = 0, i, len, bitpos, rderrbit = 0, nonrefbit = 0;
17689ec7b004SRick Macklem 	int fslocationsbit = 0;
17699ec7b004SRick Macklem 	nfsattrbit_t tmpbits, refbits;
17709ec7b004SRick Macklem 
17719ec7b004SRick Macklem 	NFSREFERRAL_ATTRBIT(&refbits);
17729ec7b004SRick Macklem 	if (getattr)
17739ec7b004SRick Macklem 		NFSCLRBIT_ATTRBIT(&refbits, NFSATTRBIT_RDATTRERROR);
17749ec7b004SRick Macklem 	else if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_RDATTRERROR))
17759ec7b004SRick Macklem 		rderrbit = 1;
17769ec7b004SRick Macklem 	if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_FSLOCATIONS))
17779ec7b004SRick Macklem 		fslocationsbit = 1;
17789ec7b004SRick Macklem 
17799ec7b004SRick Macklem 	/*
17809ec7b004SRick Macklem 	 * Check for the case where unsupported referral attributes are
17819ec7b004SRick Macklem 	 * requested.
17829ec7b004SRick Macklem 	 */
17839ec7b004SRick Macklem 	NFSSET_ATTRBIT(&tmpbits, retbitp);
17849ec7b004SRick Macklem 	NFSCLRALL_ATTRBIT(&tmpbits, &refbits);
17859ec7b004SRick Macklem 	if (NFSNONZERO_ATTRBIT(&tmpbits))
17869ec7b004SRick Macklem 		nonrefbit = 1;
17879ec7b004SRick Macklem 
17889ec7b004SRick Macklem 	if (nonrefbit && !fslocationsbit && (getattr || !rderrbit)) {
17899ec7b004SRick Macklem 		*reterrp = NFSERR_MOVED;
17909ec7b004SRick Macklem 		return (0);
17919ec7b004SRick Macklem 	}
17929ec7b004SRick Macklem 
17939ec7b004SRick Macklem 	/*
17949ec7b004SRick Macklem 	 * Now we can fill in the attributes.
17959ec7b004SRick Macklem 	 */
17969ec7b004SRick Macklem 	NFSSET_ATTRBIT(&tmpbits, retbitp);
17979ec7b004SRick Macklem 	NFSCLRNOT_ATTRBIT(&tmpbits, &refbits);
17989ec7b004SRick Macklem 
17999ec7b004SRick Macklem 	/*
18009ec7b004SRick Macklem 	 * Put out the attribute bitmap for the ones being filled in
18019ec7b004SRick Macklem 	 * and get the field for the number of attributes returned.
18029ec7b004SRick Macklem 	 */
18039ec7b004SRick Macklem 	prefixnum = nfsrv_putattrbit(nd, &tmpbits);
18049ec7b004SRick Macklem 	NFSM_BUILD(retnump, u_int32_t *, NFSX_UNSIGNED);
18059ec7b004SRick Macklem 	prefixnum += NFSX_UNSIGNED;
18069ec7b004SRick Macklem 
18079ec7b004SRick Macklem 	/*
18089ec7b004SRick Macklem 	 * Now, loop around filling in the attributes for each bit set.
18099ec7b004SRick Macklem 	 */
18109ec7b004SRick Macklem 	for (bitpos = 0; bitpos < NFSATTRBIT_MAX; bitpos++) {
18119ec7b004SRick Macklem 	    if (NFSISSET_ATTRBIT(&tmpbits, bitpos)) {
18129ec7b004SRick Macklem 		switch (bitpos) {
18139ec7b004SRick Macklem 		case NFSATTRBIT_TYPE:
18149ec7b004SRick Macklem 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
18159ec7b004SRick Macklem 			*tl = txdr_unsigned(NFDIR);
18169ec7b004SRick Macklem 			retnum += NFSX_UNSIGNED;
18179ec7b004SRick Macklem 			break;
18189ec7b004SRick Macklem 		case NFSATTRBIT_FSID:
18199ec7b004SRick Macklem 			NFSM_BUILD(tl, u_int32_t *, NFSX_V4FSID);
18209ec7b004SRick Macklem 			*tl++ = 0;
18219ec7b004SRick Macklem 			*tl++ = txdr_unsigned(NFSV4ROOT_FSID0);
18229ec7b004SRick Macklem 			*tl++ = 0;
18239ec7b004SRick Macklem 			*tl = txdr_unsigned(NFSV4ROOT_REFERRAL);
18249ec7b004SRick Macklem 			retnum += NFSX_V4FSID;
18259ec7b004SRick Macklem 			break;
18269ec7b004SRick Macklem 		case NFSATTRBIT_RDATTRERROR:
18279ec7b004SRick Macklem 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
18289ec7b004SRick Macklem 			if (nonrefbit)
18299ec7b004SRick Macklem 				*tl = txdr_unsigned(NFSERR_MOVED);
18309ec7b004SRick Macklem 			else
18319ec7b004SRick Macklem 				*tl = 0;
18329ec7b004SRick Macklem 			retnum += NFSX_UNSIGNED;
18339ec7b004SRick Macklem 			break;
18349ec7b004SRick Macklem 		case NFSATTRBIT_FSLOCATIONS:
18359ec7b004SRick Macklem 			retnum += nfsm_strtom(nd, "/", 1);
18369ec7b004SRick Macklem 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
18379ec7b004SRick Macklem 			*tl = txdr_unsigned(refp->nfr_srvcnt);
18389ec7b004SRick Macklem 			retnum += NFSX_UNSIGNED;
18399ec7b004SRick Macklem 			cp = refp->nfr_srvlist;
18409ec7b004SRick Macklem 			for (i = 0; i < refp->nfr_srvcnt; i++) {
18419ec7b004SRick Macklem 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
18429ec7b004SRick Macklem 				*tl = txdr_unsigned(1);
18439ec7b004SRick Macklem 				retnum += NFSX_UNSIGNED;
18449ec7b004SRick Macklem 				cp2 = STRCHR(cp, ':');
18459ec7b004SRick Macklem 				if (cp2 != NULL)
18469ec7b004SRick Macklem 					len = cp2 - cp;
18479ec7b004SRick Macklem 				else
18489ec7b004SRick Macklem 					len = 1;
18499ec7b004SRick Macklem 				retnum += nfsm_strtom(nd, cp, len);
18509ec7b004SRick Macklem 				if (cp2 != NULL)
18519ec7b004SRick Macklem 					cp = cp2 + 1;
18529ec7b004SRick Macklem 				cp2 = STRCHR(cp, ',');
18539ec7b004SRick Macklem 				if (cp2 != NULL)
18549ec7b004SRick Macklem 					len = cp2 - cp;
18559ec7b004SRick Macklem 				else
18569ec7b004SRick Macklem 					len = strlen(cp);
18579ec7b004SRick Macklem 				retnum += nfsm_strtom(nd, cp, len);
18589ec7b004SRick Macklem 				if (cp2 != NULL)
18599ec7b004SRick Macklem 					cp = cp2 + 1;
18609ec7b004SRick Macklem 			}
18619ec7b004SRick Macklem 			break;
18629ec7b004SRick Macklem 		case NFSATTRBIT_MOUNTEDONFILEID:
18639ec7b004SRick Macklem 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
186495ac7f1aSRick Macklem 			txdr_hyper(refp->nfr_dfileno, tl);
18659ec7b004SRick Macklem 			retnum += NFSX_HYPER;
18669ec7b004SRick Macklem 			break;
18679ec7b004SRick Macklem 		default:
18689ec7b004SRick Macklem 			printf("EEK! Bad V4 refattr bitpos=%d\n", bitpos);
186974b8d63dSPedro F. Giffuni 		}
18709ec7b004SRick Macklem 	    }
18719ec7b004SRick Macklem 	}
18729ec7b004SRick Macklem 	*retnump = txdr_unsigned(retnum);
18739ec7b004SRick Macklem 	return (retnum + prefixnum);
18749ec7b004SRick Macklem }
18759ec7b004SRick Macklem 
18769ec7b004SRick Macklem /*
18779ec7b004SRick Macklem  * Parse a file name out of a request.
18789ec7b004SRick Macklem  */
1879b9cc3262SRyan Moeller int
18809ec7b004SRick Macklem nfsrv_parsename(struct nfsrv_descript *nd, char *bufp, u_long *hashp,
18819ec7b004SRick Macklem     NFSPATHLEN_T *outlenp)
18829ec7b004SRick Macklem {
18839ec7b004SRick Macklem 	char *fromcp, *tocp, val = '\0';
1884ae070589SRick Macklem 	struct mbuf *md;
18859ec7b004SRick Macklem 	int i;
18869ec7b004SRick Macklem 	int rem, len, error = 0, pubtype = 0, outlen = 0, percent = 0;
18879ec7b004SRick Macklem 	char digit;
18889ec7b004SRick Macklem 	u_int32_t *tl;
18899ec7b004SRick Macklem 	u_long hash = 0;
18909ec7b004SRick Macklem 
18919ec7b004SRick Macklem 	if (hashp != NULL)
18929ec7b004SRick Macklem 		*hashp = 0;
18939ec7b004SRick Macklem 	tocp = bufp;
18949ec7b004SRick Macklem 	/*
18959ec7b004SRick Macklem 	 * For V4, check for lookup parent.
18969ec7b004SRick Macklem 	 * Otherwise, get the component name.
18979ec7b004SRick Macklem 	 */
1898947bd247SRick Macklem 	if ((nd->nd_flag & ND_NFSV4) && (nd->nd_procnum == NFSV4OP_LOOKUPP ||
1899947bd247SRick Macklem 	    nd->nd_procnum == NFSV4OP_SECINFONONAME)) {
19009ec7b004SRick Macklem 	    *tocp++ = '.';
19019ec7b004SRick Macklem 	    hash += ((u_char)'.');
19029ec7b004SRick Macklem 	    *tocp++ = '.';
19039ec7b004SRick Macklem 	    hash += ((u_char)'.');
19049ec7b004SRick Macklem 	    outlen = 2;
19059ec7b004SRick Macklem 	} else {
19069ec7b004SRick Macklem 	    /*
19079ec7b004SRick Macklem 	     * First, get the name length.
19089ec7b004SRick Macklem 	     */
19099ec7b004SRick Macklem 	    NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
19109ec7b004SRick Macklem 	    len = fxdr_unsigned(int, *tl);
19119ec7b004SRick Macklem 	    if (len > NFS_MAXNAMLEN) {
19129ec7b004SRick Macklem 		nd->nd_repstat = NFSERR_NAMETOL;
1913a9285ae5SZack Kirsch 		error = 0;
1914a9285ae5SZack Kirsch 		goto nfsmout;
19159ec7b004SRick Macklem 	    } else if (len <= 0) {
19169ec7b004SRick Macklem 		nd->nd_repstat = NFSERR_INVAL;
1917a9285ae5SZack Kirsch 		error = 0;
1918a9285ae5SZack Kirsch 		goto nfsmout;
19199ec7b004SRick Macklem 	    }
19209ec7b004SRick Macklem 
19219ec7b004SRick Macklem 	    /*
19229ec7b004SRick Macklem 	     * Now, copy the component name into the buffer.
19239ec7b004SRick Macklem 	     */
19249ec7b004SRick Macklem 	    fromcp = nd->nd_dpos;
19259ec7b004SRick Macklem 	    md = nd->nd_md;
192628e8046bSRick Macklem 	    rem = mtod(md, caddr_t) + md->m_len - fromcp;
19279ec7b004SRick Macklem 	    for (i = 0; i < len; i++) {
19289ec7b004SRick Macklem 		while (rem == 0) {
192928e8046bSRick Macklem 			md = md->m_next;
1930a9285ae5SZack Kirsch 			if (md == NULL) {
1931a9285ae5SZack Kirsch 				error = EBADRPC;
1932a9285ae5SZack Kirsch 				goto nfsmout;
1933a9285ae5SZack Kirsch 			}
193428e8046bSRick Macklem 			fromcp = mtod(md, caddr_t);
193528e8046bSRick Macklem 			rem = md->m_len;
19369ec7b004SRick Macklem 		}
19379ec7b004SRick Macklem 		if (*fromcp == '\0') {
19389ec7b004SRick Macklem 			nd->nd_repstat = EACCES;
1939a9285ae5SZack Kirsch 			error = 0;
1940a9285ae5SZack Kirsch 			goto nfsmout;
19419ec7b004SRick Macklem 		}
19429ec7b004SRick Macklem 		/*
19439ec7b004SRick Macklem 		 * For lookups on the public filehandle, do some special
19449ec7b004SRick Macklem 		 * processing on the name. (The public file handle is the
19459ec7b004SRick Macklem 		 * root of the public file system for this server.)
19469ec7b004SRick Macklem 		 */
19479ec7b004SRick Macklem 		if (nd->nd_flag & ND_PUBLOOKUP) {
19489ec7b004SRick Macklem 			/*
19499ec7b004SRick Macklem 			 * If the first char is ASCII, it is a canonical
19509ec7b004SRick Macklem 			 * path, otherwise it is a native path. (RFC2054
19519ec7b004SRick Macklem 			 * doesn't actually state what it is if the first
19529ec7b004SRick Macklem 			 * char isn't ASCII or 0x80, so I assume native.)
19539ec7b004SRick Macklem 			 * pubtype == 1 -> native path
19549ec7b004SRick Macklem 			 * pubtype == 2 -> canonical path
19559ec7b004SRick Macklem 			 */
19569ec7b004SRick Macklem 			if (i == 0) {
19579ec7b004SRick Macklem 				if (*fromcp & 0x80) {
19589ec7b004SRick Macklem 					/*
19599ec7b004SRick Macklem 					 * Since RFC2054 doesn't indicate
19609ec7b004SRick Macklem 					 * that a native path of just 0x80
19619ec7b004SRick Macklem 					 * isn't allowed, I'll replace the
19629ec7b004SRick Macklem 					 * 0x80 with '/' instead of just
19639ec7b004SRick Macklem 					 * throwing it away.
19649ec7b004SRick Macklem 					 */
19659ec7b004SRick Macklem 					*fromcp = '/';
19669ec7b004SRick Macklem 					pubtype = 1;
19679ec7b004SRick Macklem 				} else {
19689ec7b004SRick Macklem 					pubtype = 2;
19699ec7b004SRick Macklem 				}
19709ec7b004SRick Macklem 			}
19719ec7b004SRick Macklem 			/*
19729ec7b004SRick Macklem 			 * '/' only allowed in a native path
19739ec7b004SRick Macklem 			 */
19749ec7b004SRick Macklem 			if (*fromcp == '/' && pubtype != 1) {
19759ec7b004SRick Macklem 				nd->nd_repstat = EACCES;
1976a9285ae5SZack Kirsch 				error = 0;
1977a9285ae5SZack Kirsch 				goto nfsmout;
19789ec7b004SRick Macklem 			}
19799ec7b004SRick Macklem 
19809ec7b004SRick Macklem 			/*
19819ec7b004SRick Macklem 			 * For the special case of 2 hex digits after a
19829ec7b004SRick Macklem 			 * '%' in an absolute path, calculate the value.
19839ec7b004SRick Macklem 			 * percent == 1 -> indicates "get first hex digit"
19849ec7b004SRick Macklem 			 * percent == 2 -> indicates "get second hex digit"
19859ec7b004SRick Macklem 			 */
19869ec7b004SRick Macklem 			if (percent > 0) {
19879ec7b004SRick Macklem 				digit = nfsrv_hexdigit(*fromcp, &error);
19889ec7b004SRick Macklem 				if (error) {
19899ec7b004SRick Macklem 					nd->nd_repstat = EACCES;
1990a9285ae5SZack Kirsch 					error = 0;
1991a9285ae5SZack Kirsch 					goto nfsmout;
19929ec7b004SRick Macklem 				}
19939ec7b004SRick Macklem 				if (percent == 1) {
19949ec7b004SRick Macklem 					val = (digit << 4);
19959ec7b004SRick Macklem 					percent = 2;
19969ec7b004SRick Macklem 				} else {
19979ec7b004SRick Macklem 					val += digit;
19989ec7b004SRick Macklem 					percent = 0;
19999ec7b004SRick Macklem 					*tocp++ = val;
20009ec7b004SRick Macklem 					hash += ((u_char)val);
20019ec7b004SRick Macklem 					outlen++;
20029ec7b004SRick Macklem 				}
20039ec7b004SRick Macklem 			} else {
20049ec7b004SRick Macklem 				if (*fromcp == '%' && pubtype == 2) {
20059ec7b004SRick Macklem 					/*
20069ec7b004SRick Macklem 					 * Must be followed by 2 hex digits
20079ec7b004SRick Macklem 					 */
20089ec7b004SRick Macklem 					if ((len - i) < 3) {
20099ec7b004SRick Macklem 						nd->nd_repstat = EACCES;
2010a9285ae5SZack Kirsch 						error = 0;
2011a9285ae5SZack Kirsch 						goto nfsmout;
20129ec7b004SRick Macklem 					}
20139ec7b004SRick Macklem 					percent = 1;
20149ec7b004SRick Macklem 				} else {
20159ec7b004SRick Macklem 					*tocp++ = *fromcp;
20169ec7b004SRick Macklem 					hash += ((u_char)*fromcp);
20179ec7b004SRick Macklem 					outlen++;
20189ec7b004SRick Macklem 				}
20199ec7b004SRick Macklem 			}
20209ec7b004SRick Macklem 		} else {
20219ec7b004SRick Macklem 			/*
20229ec7b004SRick Macklem 			 * Normal, non lookup on public, name.
20239ec7b004SRick Macklem 			 */
20249ec7b004SRick Macklem 			if (*fromcp == '/') {
20259ec7b004SRick Macklem 				if (nd->nd_flag & ND_NFSV4)
20269ec7b004SRick Macklem 					nd->nd_repstat = NFSERR_BADNAME;
20279ec7b004SRick Macklem 				else
20289ec7b004SRick Macklem 					nd->nd_repstat = EACCES;
2029a9285ae5SZack Kirsch 				error = 0;
2030a9285ae5SZack Kirsch 				goto nfsmout;
20319ec7b004SRick Macklem 			}
20329ec7b004SRick Macklem 			hash += ((u_char)*fromcp);
20339ec7b004SRick Macklem 			*tocp++ = *fromcp;
20349ec7b004SRick Macklem 			outlen++;
20359ec7b004SRick Macklem 		}
20369ec7b004SRick Macklem 		fromcp++;
20379ec7b004SRick Macklem 		rem--;
20389ec7b004SRick Macklem 	    }
20399ec7b004SRick Macklem 	    nd->nd_md = md;
20409ec7b004SRick Macklem 	    nd->nd_dpos = fromcp;
20419ec7b004SRick Macklem 	    i = NFSM_RNDUP(len) - len;
20429ec7b004SRick Macklem 	    if (i > 0) {
20439ec7b004SRick Macklem 		if (rem >= i) {
20449ec7b004SRick Macklem 			nd->nd_dpos += i;
20459ec7b004SRick Macklem 		} else {
20469ec7b004SRick Macklem 			error = nfsm_advance(nd, i, rem);
20479ec7b004SRick Macklem 			if (error)
2048a9285ae5SZack Kirsch 				goto nfsmout;
20499ec7b004SRick Macklem 		}
20509ec7b004SRick Macklem 	    }
20519ec7b004SRick Macklem 
20529ec7b004SRick Macklem 	    /*
20539ec7b004SRick Macklem 	     * For v4, don't allow lookups of '.' or '..' and
20549ec7b004SRick Macklem 	     * also check for non-utf8 strings.
20559ec7b004SRick Macklem 	     */
20569ec7b004SRick Macklem 	    if (nd->nd_flag & ND_NFSV4) {
20579ec7b004SRick Macklem 		if ((outlen == 1 && bufp[0] == '.') ||
20589ec7b004SRick Macklem 		    (outlen == 2 && bufp[0] == '.' &&
20599ec7b004SRick Macklem 		     bufp[1] == '.')) {
20609ec7b004SRick Macklem 		    nd->nd_repstat = NFSERR_BADNAME;
2061a9285ae5SZack Kirsch 		    error = 0;
2062a9285ae5SZack Kirsch 		    goto nfsmout;
20639ec7b004SRick Macklem 		}
2064f9246664SMarcelo Araujo 		if (enable_checkutf8 == 1 &&
206534f2e649SRick Macklem 		    nfsrv_checkutf8((u_int8_t *)bufp, outlen)) {
20669ec7b004SRick Macklem 		    nd->nd_repstat = NFSERR_INVAL;
2067a9285ae5SZack Kirsch 		    error = 0;
2068a9285ae5SZack Kirsch 		    goto nfsmout;
20699ec7b004SRick Macklem 		}
20709ec7b004SRick Macklem 	    }
20719ec7b004SRick Macklem 	}
20729ec7b004SRick Macklem 	*tocp = '\0';
207368c25442SMateusz Guzik 	*outlenp = (size_t)outlen + 1;
20749ec7b004SRick Macklem 	if (hashp != NULL)
20759ec7b004SRick Macklem 		*hashp = hash;
20769ec7b004SRick Macklem nfsmout:
2077a9285ae5SZack Kirsch 	NFSEXITCODE2(error, nd);
20789ec7b004SRick Macklem 	return (error);
20799ec7b004SRick Macklem }
20809ec7b004SRick Macklem 
20819ec7b004SRick Macklem void
20829ec7b004SRick Macklem nfsd_init(void)
20839ec7b004SRick Macklem {
20849ec7b004SRick Macklem 	int i;
20859ec7b004SRick Macklem 
20869ec7b004SRick Macklem 
20879ec7b004SRick Macklem 	/*
20889ec7b004SRick Macklem 	 * Initialize client queues. Don't free/reinitialize
20899ec7b004SRick Macklem 	 * them when nfsds are restarted.
20909ec7b004SRick Macklem 	 */
20917e44856eSRick Macklem 	NFSD_VNET(nfsclienthash) = malloc(sizeof(struct nfsclienthashhead) *
20921f54e596SRick Macklem 	    nfsrv_clienthashsize, M_NFSDCLIENT, M_WAITOK | M_ZERO);
20931f54e596SRick Macklem 	for (i = 0; i < nfsrv_clienthashsize; i++)
20947e44856eSRick Macklem 		LIST_INIT(&NFSD_VNET(nfsclienthash)[i]);
20957e44856eSRick Macklem 	NFSD_VNET(nfslockhash) = malloc(sizeof(struct nfslockhashhead) *
20961f54e596SRick Macklem 	    nfsrv_lockhashsize, M_NFSDLOCKFILE, M_WAITOK | M_ZERO);
20971f54e596SRick Macklem 	for (i = 0; i < nfsrv_lockhashsize; i++)
20987e44856eSRick Macklem 		LIST_INIT(&NFSD_VNET(nfslockhash)[i]);
20997e44856eSRick Macklem 	NFSD_VNET(nfssessionhash) = malloc(sizeof(struct nfssessionhash) *
21001f54e596SRick Macklem 	    nfsrv_sessionhashsize, M_NFSDSESSION, M_WAITOK | M_ZERO);
21011f54e596SRick Macklem 	for (i = 0; i < nfsrv_sessionhashsize; i++) {
21027e44856eSRick Macklem 		mtx_init(&NFSD_VNET(nfssessionhash)[i].mtx, "nfssm", NULL,
21037e44856eSRick Macklem 		    MTX_DEF);
21047e44856eSRick Macklem 		LIST_INIT(&NFSD_VNET(nfssessionhash)[i].list);
21051f54e596SRick Macklem 	}
210690d2dfabSRick Macklem 	LIST_INIT(&nfsrv_dontlisthead);
210790d2dfabSRick Macklem 	TAILQ_INIT(&nfsrv_recalllisthead);
21089ec7b004SRick Macklem 
21099ec7b004SRick Macklem 	/* and the v2 pubfh should be all zeros */
21109ec7b004SRick Macklem 	NFSBZERO(nfs_v2pubfh, NFSX_V2FH);
21119ec7b004SRick Macklem }
21129ec7b004SRick Macklem 
211398ad4453SRick Macklem /*
211498ad4453SRick Macklem  * Check the v4 root exports.
211598ad4453SRick Macklem  * Return 0 if ok, 1 otherwise.
211698ad4453SRick Macklem  */
211798ad4453SRick Macklem int
211898ad4453SRick Macklem nfsd_checkrootexp(struct nfsrv_descript *nd)
211998ad4453SRick Macklem {
212098ad4453SRick Macklem 
21217e44856eSRick Macklem 	if (NFSD_VNET(nfs_rootfhset) == 0)
2122984c71f9SRick Macklem 		return (NFSERR_AUTHERR | AUTH_FAILED);
21235a0050e6SRick Macklem 	/*
21245a0050e6SRick Macklem 	 * For NFSv4.1/4.2, if the client specifies SP4_NONE, then these
21255a0050e6SRick Macklem 	 * operations are allowed regardless of the value of the "sec=XXX"
21265a0050e6SRick Macklem 	 * field in the V4: exports line.
21275a0050e6SRick Macklem 	 * As such, these Kerberos checks only apply to NFSv4.0 mounts.
21285a0050e6SRick Macklem 	 */
21295a0050e6SRick Macklem 	if ((nd->nd_flag & ND_NFSV41) != 0)
21305a0050e6SRick Macklem 		goto checktls;
213198ad4453SRick Macklem 	if ((nd->nd_flag & (ND_GSS | ND_EXAUTHSYS)) == ND_EXAUTHSYS)
21326e4b6ff8SRick Macklem 		goto checktls;
213398ad4453SRick Macklem 	if ((nd->nd_flag & (ND_GSSINTEGRITY | ND_EXGSSINTEGRITY)) ==
213498ad4453SRick Macklem 	    (ND_GSSINTEGRITY | ND_EXGSSINTEGRITY))
21356e4b6ff8SRick Macklem 		goto checktls;
213698ad4453SRick Macklem 	if ((nd->nd_flag & (ND_GSSPRIVACY | ND_EXGSSPRIVACY)) ==
213798ad4453SRick Macklem 	    (ND_GSSPRIVACY | ND_EXGSSPRIVACY))
21386e4b6ff8SRick Macklem 		goto checktls;
213998ad4453SRick Macklem 	if ((nd->nd_flag & (ND_GSS | ND_GSSINTEGRITY | ND_GSSPRIVACY |
214098ad4453SRick Macklem 	     ND_EXGSS)) == (ND_GSS | ND_EXGSS))
21416e4b6ff8SRick Macklem 		goto checktls;
2142984c71f9SRick Macklem 	return (NFSERR_AUTHERR | AUTH_TOOWEAK);
21436e4b6ff8SRick Macklem checktls:
21446e4b6ff8SRick Macklem 	if ((nd->nd_flag & ND_EXTLS) == 0)
21456e4b6ff8SRick Macklem 		return (0);
21466e4b6ff8SRick Macklem 	if ((nd->nd_flag & (ND_TLSCERTUSER | ND_EXTLSCERTUSER)) ==
21476e4b6ff8SRick Macklem 	    (ND_TLSCERTUSER | ND_EXTLSCERTUSER))
21486e4b6ff8SRick Macklem 		return (0);
21496e4b6ff8SRick Macklem 	if ((nd->nd_flag & (ND_TLSCERT | ND_EXTLSCERT | ND_EXTLSCERTUSER)) ==
21506e4b6ff8SRick Macklem 	    (ND_TLSCERT | ND_EXTLSCERT))
21516e4b6ff8SRick Macklem 		return (0);
21526e4b6ff8SRick Macklem 	if ((nd->nd_flag & (ND_TLS | ND_EXTLSCERTUSER | ND_EXTLSCERT)) ==
21536e4b6ff8SRick Macklem 	    ND_TLS)
215498ad4453SRick Macklem 		return (0);
2155744c2dc7SRick Macklem #ifdef notnow
2156744c2dc7SRick Macklem 	/* There is currently no auth_stat for this. */
2157984c71f9SRick Macklem 	if ((nd->nd_flag & ND_TLS) == 0)
2158984c71f9SRick Macklem 		return (NFSERR_AUTHERR | AUTH_NEEDS_TLS);
2159984c71f9SRick Macklem 	return (NFSERR_AUTHERR | AUTH_NEEDS_TLS_MUTUAL_HOST);
2160744c2dc7SRick Macklem #endif
2161744c2dc7SRick Macklem 	return (NFSERR_AUTHERR | AUTH_TOOWEAK);
216298ad4453SRick Macklem }
216398ad4453SRick Macklem 
2164c59e4cc3SRick Macklem /*
2165c59e4cc3SRick Macklem  * Parse the first part of an NFSv4 compound to find out what the minor
2166c59e4cc3SRick Macklem  * version# is.
2167c59e4cc3SRick Macklem  */
2168c59e4cc3SRick Macklem void
2169c59e4cc3SRick Macklem nfsd_getminorvers(struct nfsrv_descript *nd, u_char *tag, u_char **tagstrp,
2170c59e4cc3SRick Macklem     int *taglenp, u_int32_t *minversp)
2171c59e4cc3SRick Macklem {
2172c59e4cc3SRick Macklem 	uint32_t *tl;
2173c59e4cc3SRick Macklem 	int error = 0, taglen = -1;
2174c59e4cc3SRick Macklem 	u_char *tagstr = NULL;
2175c59e4cc3SRick Macklem 
2176c59e4cc3SRick Macklem 	NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
2177c59e4cc3SRick Macklem 	taglen = fxdr_unsigned(int, *tl);
2178c59e4cc3SRick Macklem 	if (taglen < 0 || taglen > NFSV4_OPAQUELIMIT) {
2179c59e4cc3SRick Macklem 		error = EBADRPC;
2180c59e4cc3SRick Macklem 		goto nfsmout;
2181c59e4cc3SRick Macklem 	}
2182c59e4cc3SRick Macklem 	if (taglen <= NFSV4_SMALLSTR)
2183c59e4cc3SRick Macklem 		tagstr = tag;
2184c59e4cc3SRick Macklem 	else
2185c59e4cc3SRick Macklem 		tagstr = malloc(taglen + 1, M_TEMP, M_WAITOK);
2186c59e4cc3SRick Macklem 	error = nfsrv_mtostr(nd, tagstr, taglen);
2187c59e4cc3SRick Macklem 	if (error != 0)
2188c59e4cc3SRick Macklem 		goto nfsmout;
2189c59e4cc3SRick Macklem 	NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
2190c59e4cc3SRick Macklem 	*minversp = fxdr_unsigned(u_int32_t, *tl);
2191c59e4cc3SRick Macklem 	*tagstrp = tagstr;
2192c59e4cc3SRick Macklem 	if (*minversp == NFSV41_MINORVERSION)
2193c59e4cc3SRick Macklem 		nd->nd_flag |= ND_NFSV41;
2194c057a378SRick Macklem 	else if (*minversp == NFSV42_MINORVERSION)
2195c057a378SRick Macklem 		nd->nd_flag |= (ND_NFSV41 | ND_NFSV42);
2196c59e4cc3SRick Macklem nfsmout:
2197c59e4cc3SRick Macklem 	if (error != 0) {
2198c59e4cc3SRick Macklem 		if (tagstr != NULL && taglen > NFSV4_SMALLSTR)
2199c59e4cc3SRick Macklem 			free(tagstr, M_TEMP);
2200c59e4cc3SRick Macklem 		taglen = -1;
2201c59e4cc3SRick Macklem 	}
2202c59e4cc3SRick Macklem 	*taglenp = taglen;
2203c59e4cc3SRick Macklem }
2204