summaryrefslogtreecommitdiff
path: root/sys/nfs/nfs_subs.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/nfs/nfs_subs.c')
-rw-r--r--sys/nfs/nfs_subs.c1070
1 files changed, 916 insertions, 154 deletions
diff --git a/sys/nfs/nfs_subs.c b/sys/nfs/nfs_subs.c
index 305f23df96e..edc395c5bd7 100644
--- a/sys/nfs/nfs_subs.c
+++ b/sys/nfs/nfs_subs.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: nfs_subs.c,v 1.4 1996/02/29 09:24:56 niklas Exp $ */
-/* $NetBSD: nfs_subs.c,v 1.24 1996/02/09 21:48:34 christos Exp $ */
+/* $OpenBSD: nfs_subs.c,v 1.5 1996/03/31 13:15:53 mickey Exp $ */
+/* $NetBSD: nfs_subs.c,v 1.26 1996/03/13 00:44:17 fvdl Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -36,9 +36,10 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs_subs.c 8.3 (Berkeley) 1/4/94
+ * @(#)nfs_subs.c 8.8 (Berkeley) 5/22/95
*/
+
/*
* These functions support the macros and help fiddle mbuf chains for
* the nfs op functions. They do things like create the rpc header and
@@ -54,9 +55,12 @@
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/stat.h>
+#include <sys/malloc.h>
+
+#include <vm/vm.h>
#include <nfs/rpcv2.h>
-#include <nfs/nfsv2.h>
+#include <nfs/nfsproto.h>
#include <nfs/nfsnode.h>
#include <nfs/nfs.h>
#include <nfs/xdr_subs.h>
@@ -75,34 +79,461 @@
#include <netiso/iso.h>
#endif
-#define TRUE 1
-#define FALSE 0
-
/*
* Data items converted to xdr at startup, since they are constant
* This is kinda hokey, but may save a little time doing byte swaps
*/
-u_long nfs_procids[NFS_NPROCS];
u_int32_t nfs_xdrneg1;
u_int32_t rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, rpc_autherr,
- rpc_mismatch, rpc_auth_unix, rpc_msgaccepted, rpc_rejectedcred,
+ rpc_mismatch, rpc_auth_unix, rpc_msgaccepted,
rpc_auth_kerb;
-u_int32_t nfs_vers, nfs_prog, nfs_true, nfs_false;
+u_int32_t nfs_prog, nqnfs_prog, nfs_true, nfs_false;
/* And other global data */
static u_int32_t nfs_xid = 0;
-enum vtype ntov_type[7] = { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON };
+nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON,
+ NFCHR, NFNON };
+nfstype nfsv3_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK,
+ NFFIFO, NFNON };
+enum vtype nv2tov_type[8] = { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON, VNON };
+enum vtype nv3tov_type[8]={ VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO };
+int nfs_ticks;
+
+/*
+ * Mapping of old NFS Version 2 RPC numbers to generic numbers.
+ */
+int nfsv3_procid[NFS_NPROCS] = {
+ NFSPROC_NULL,
+ NFSPROC_GETATTR,
+ NFSPROC_SETATTR,
+ NFSPROC_NOOP,
+ NFSPROC_LOOKUP,
+ NFSPROC_READLINK,
+ NFSPROC_READ,
+ NFSPROC_NOOP,
+ NFSPROC_WRITE,
+ NFSPROC_CREATE,
+ NFSPROC_REMOVE,
+ NFSPROC_RENAME,
+ NFSPROC_LINK,
+ NFSPROC_SYMLINK,
+ NFSPROC_MKDIR,
+ NFSPROC_RMDIR,
+ NFSPROC_READDIR,
+ NFSPROC_FSSTAT,
+ NFSPROC_NOOP,
+ NFSPROC_NOOP,
+ NFSPROC_NOOP,
+ NFSPROC_NOOP,
+ NFSPROC_NOOP,
+ NFSPROC_NOOP,
+ NFSPROC_NOOP,
+ NFSPROC_NOOP
+};
+
+/*
+ * and the reverse mapping from generic to Version 2 procedure numbers
+ */
+int nfsv2_procid[NFS_NPROCS] = {
+ NFSV2PROC_NULL,
+ NFSV2PROC_GETATTR,
+ NFSV2PROC_SETATTR,
+ NFSV2PROC_LOOKUP,
+ NFSV2PROC_NOOP,
+ NFSV2PROC_READLINK,
+ NFSV2PROC_READ,
+ NFSV2PROC_WRITE,
+ NFSV2PROC_CREATE,
+ NFSV2PROC_MKDIR,
+ NFSV2PROC_SYMLINK,
+ NFSV2PROC_CREATE,
+ NFSV2PROC_REMOVE,
+ NFSV2PROC_RMDIR,
+ NFSV2PROC_RENAME,
+ NFSV2PROC_LINK,
+ NFSV2PROC_READDIR,
+ NFSV2PROC_NOOP,
+ NFSV2PROC_STATFS,
+ NFSV2PROC_NOOP,
+ NFSV2PROC_NOOP,
+ NFSV2PROC_NOOP,
+ NFSV2PROC_NOOP,
+ NFSV2PROC_NOOP,
+ NFSV2PROC_NOOP,
+ NFSV2PROC_NOOP,
+};
+
+/*
+ * Maps errno values to nfs error numbers.
+ * Use NFSERR_IO as the catch all for ones not specifically defined in
+ * RFC 1094.
+ */
+static u_char nfsrv_v2errmap[ELAST] = {
+ NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO,
+ NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
+ NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO,
+ NFSERR_IO, NFSERR_EXIST, NFSERR_IO, NFSERR_NODEV, NFSERR_NOTDIR,
+ NFSERR_ISDIR, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
+ NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS,
+ NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
+ NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
+ NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
+ NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
+ NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
+ NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
+ NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO,
+ NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE,
+ NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
+ NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
+ NFSERR_IO,
+};
+
+/*
+ * Maps errno values to nfs error numbers.
+ * Although it is not obvious whether or not NFS clients really care if
+ * a returned error value is in the specified list for the procedure, the
+ * safest thing to do is filter them appropriately. For Version 2, the
+ * X/Open XNFS document is the only specification that defines error values
+ * for each RPC (The RFC simply lists all possible error values for all RPCs),
+ * so I have decided to not do this for Version 2.
+ * The first entry is the default error return and the rest are the valid
+ * errors for that RPC in increasing numeric order.
+ */
+static short nfsv3err_null[] = {
+ 0,
+ 0,
+};
+
+static short nfsv3err_getattr[] = {
+ NFSERR_IO,
+ NFSERR_IO,
+ NFSERR_STALE,
+ NFSERR_BADHANDLE,
+ NFSERR_SERVERFAULT,
+ 0,
+};
+
+static short nfsv3err_setattr[] = {
+ NFSERR_IO,
+ NFSERR_PERM,
+ NFSERR_IO,
+ NFSERR_ACCES,
+ NFSERR_INVAL,
+ NFSERR_NOSPC,
+ NFSERR_ROFS,
+ NFSERR_DQUOT,
+ NFSERR_STALE,
+ NFSERR_BADHANDLE,
+ NFSERR_NOT_SYNC,
+ NFSERR_SERVERFAULT,
+ 0,
+};
+
+static short nfsv3err_lookup[] = {
+ NFSERR_IO,
+ NFSERR_NOENT,
+ NFSERR_IO,
+ NFSERR_ACCES,
+ NFSERR_NOTDIR,
+ NFSERR_NAMETOL,
+ NFSERR_STALE,
+ NFSERR_BADHANDLE,
+ NFSERR_SERVERFAULT,
+ 0,
+};
+
+static short nfsv3err_access[] = {
+ NFSERR_IO,
+ NFSERR_IO,
+ NFSERR_STALE,
+ NFSERR_BADHANDLE,
+ NFSERR_SERVERFAULT,
+ 0,
+};
+
+static short nfsv3err_readlink[] = {
+ NFSERR_IO,
+ NFSERR_IO,
+ NFSERR_ACCES,
+ NFSERR_INVAL,
+ NFSERR_STALE,
+ NFSERR_BADHANDLE,
+ NFSERR_NOTSUPP,
+ NFSERR_SERVERFAULT,
+ 0,
+};
+
+static short nfsv3err_read[] = {
+ NFSERR_IO,
+ NFSERR_IO,
+ NFSERR_NXIO,
+ NFSERR_ACCES,
+ NFSERR_INVAL,
+ NFSERR_STALE,
+ NFSERR_BADHANDLE,
+ NFSERR_SERVERFAULT,
+ 0,
+};
+
+static short nfsv3err_write[] = {
+ NFSERR_IO,
+ NFSERR_IO,
+ NFSERR_ACCES,
+ NFSERR_INVAL,
+ NFSERR_FBIG,
+ NFSERR_NOSPC,
+ NFSERR_ROFS,
+ NFSERR_DQUOT,
+ NFSERR_STALE,
+ NFSERR_BADHANDLE,
+ NFSERR_SERVERFAULT,
+ 0,
+};
+
+static short nfsv3err_create[] = {
+ NFSERR_IO,
+ NFSERR_IO,
+ NFSERR_ACCES,
+ NFSERR_EXIST,
+ NFSERR_NOTDIR,
+ NFSERR_NOSPC,
+ NFSERR_ROFS,
+ NFSERR_NAMETOL,
+ NFSERR_DQUOT,
+ NFSERR_STALE,
+ NFSERR_BADHANDLE,
+ NFSERR_NOTSUPP,
+ NFSERR_SERVERFAULT,
+ 0,
+};
+
+static short nfsv3err_mkdir[] = {
+ NFSERR_IO,
+ NFSERR_IO,
+ NFSERR_ACCES,
+ NFSERR_EXIST,
+ NFSERR_NOTDIR,
+ NFSERR_NOSPC,
+ NFSERR_ROFS,
+ NFSERR_NAMETOL,
+ NFSERR_DQUOT,
+ NFSERR_STALE,
+ NFSERR_BADHANDLE,
+ NFSERR_NOTSUPP,
+ NFSERR_SERVERFAULT,
+ 0,
+};
+
+static short nfsv3err_symlink[] = {
+ NFSERR_IO,
+ NFSERR_IO,
+ NFSERR_ACCES,
+ NFSERR_EXIST,
+ NFSERR_NOTDIR,
+ NFSERR_NOSPC,
+ NFSERR_ROFS,
+ NFSERR_NAMETOL,
+ NFSERR_DQUOT,
+ NFSERR_STALE,
+ NFSERR_BADHANDLE,
+ NFSERR_NOTSUPP,
+ NFSERR_SERVERFAULT,
+ 0,
+};
+
+static short nfsv3err_mknod[] = {
+ NFSERR_IO,
+ NFSERR_IO,
+ NFSERR_ACCES,
+ NFSERR_EXIST,
+ NFSERR_NOTDIR,
+ NFSERR_NOSPC,
+ NFSERR_ROFS,
+ NFSERR_NAMETOL,
+ NFSERR_DQUOT,
+ NFSERR_STALE,
+ NFSERR_BADHANDLE,
+ NFSERR_NOTSUPP,
+ NFSERR_SERVERFAULT,
+ NFSERR_BADTYPE,
+ 0,
+};
+
+static short nfsv3err_remove[] = {
+ NFSERR_IO,
+ NFSERR_NOENT,
+ NFSERR_IO,
+ NFSERR_ACCES,
+ NFSERR_NOTDIR,
+ NFSERR_ROFS,
+ NFSERR_NAMETOL,
+ NFSERR_STALE,
+ NFSERR_BADHANDLE,
+ NFSERR_SERVERFAULT,
+ 0,
+};
+
+static short nfsv3err_rmdir[] = {
+ NFSERR_IO,
+ NFSERR_NOENT,
+ NFSERR_IO,
+ NFSERR_ACCES,
+ NFSERR_EXIST,
+ NFSERR_NOTDIR,
+ NFSERR_INVAL,
+ NFSERR_ROFS,
+ NFSERR_NAMETOL,
+ NFSERR_NOTEMPTY,
+ NFSERR_STALE,
+ NFSERR_BADHANDLE,
+ NFSERR_NOTSUPP,
+ NFSERR_SERVERFAULT,
+ 0,
+};
+
+static short nfsv3err_rename[] = {
+ NFSERR_IO,
+ NFSERR_NOENT,
+ NFSERR_IO,
+ NFSERR_ACCES,
+ NFSERR_EXIST,
+ NFSERR_XDEV,
+ NFSERR_NOTDIR,
+ NFSERR_ISDIR,
+ NFSERR_INVAL,
+ NFSERR_NOSPC,
+ NFSERR_ROFS,
+ NFSERR_MLINK,
+ NFSERR_NAMETOL,
+ NFSERR_NOTEMPTY,
+ NFSERR_DQUOT,
+ NFSERR_STALE,
+ NFSERR_BADHANDLE,
+ NFSERR_NOTSUPP,
+ NFSERR_SERVERFAULT,
+ 0,
+};
+
+static short nfsv3err_link[] = {
+ NFSERR_IO,
+ NFSERR_IO,
+ NFSERR_ACCES,
+ NFSERR_EXIST,
+ NFSERR_XDEV,
+ NFSERR_NOTDIR,
+ NFSERR_INVAL,
+ NFSERR_NOSPC,
+ NFSERR_ROFS,
+ NFSERR_MLINK,
+ NFSERR_NAMETOL,
+ NFSERR_DQUOT,
+ NFSERR_STALE,
+ NFSERR_BADHANDLE,
+ NFSERR_NOTSUPP,
+ NFSERR_SERVERFAULT,
+ 0,
+};
+
+static short nfsv3err_readdir[] = {
+ NFSERR_IO,
+ NFSERR_IO,
+ NFSERR_ACCES,
+ NFSERR_NOTDIR,
+ NFSERR_STALE,
+ NFSERR_BADHANDLE,
+ NFSERR_BAD_COOKIE,
+ NFSERR_TOOSMALL,
+ NFSERR_SERVERFAULT,
+ 0,
+};
+
+static short nfsv3err_readdirplus[] = {
+ NFSERR_IO,
+ NFSERR_IO,
+ NFSERR_ACCES,
+ NFSERR_NOTDIR,
+ NFSERR_STALE,
+ NFSERR_BADHANDLE,
+ NFSERR_BAD_COOKIE,
+ NFSERR_NOTSUPP,
+ NFSERR_TOOSMALL,
+ NFSERR_SERVERFAULT,
+ 0,
+};
+
+static short nfsv3err_fsstat[] = {
+ NFSERR_IO,
+ NFSERR_IO,
+ NFSERR_STALE,
+ NFSERR_BADHANDLE,
+ NFSERR_SERVERFAULT,
+ 0,
+};
+
+static short nfsv3err_fsinfo[] = {
+ NFSERR_STALE,
+ NFSERR_STALE,
+ NFSERR_BADHANDLE,
+ NFSERR_SERVERFAULT,
+ 0,
+};
+
+static short nfsv3err_pathconf[] = {
+ NFSERR_STALE,
+ NFSERR_STALE,
+ NFSERR_BADHANDLE,
+ NFSERR_SERVERFAULT,
+ 0,
+};
+
+static short nfsv3err_commit[] = {
+ NFSERR_IO,
+ NFSERR_IO,
+ NFSERR_STALE,
+ NFSERR_BADHANDLE,
+ NFSERR_SERVERFAULT,
+ 0,
+};
+
+static short *nfsrv_v3errmap[] = {
+ nfsv3err_null,
+ nfsv3err_getattr,
+ nfsv3err_setattr,
+ nfsv3err_lookup,
+ nfsv3err_access,
+ nfsv3err_readlink,
+ nfsv3err_read,
+ nfsv3err_write,
+ nfsv3err_create,
+ nfsv3err_mkdir,
+ nfsv3err_symlink,
+ nfsv3err_mknod,
+ nfsv3err_remove,
+ nfsv3err_rmdir,
+ nfsv3err_rename,
+ nfsv3err_link,
+ nfsv3err_readdir,
+ nfsv3err_readdirplus,
+ nfsv3err_fsstat,
+ nfsv3err_fsinfo,
+ nfsv3err_pathconf,
+ nfsv3err_commit,
+};
+
extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
-extern int nqnfs_piggy[NFS_NPROCS];
extern struct nfsrtt nfsrtt;
extern time_t nqnfsstarttime;
-extern u_int32_t nqnfs_prog, nqnfs_vers;
extern int nqsrv_clockskew;
extern int nqsrv_writeslack;
extern int nqsrv_maxlease;
+extern struct nfsstats nfsstats;
+extern int nqnfs_piggy[NFS_NPROCS];
+extern nfstype nfsv2_type[9];
+extern nfstype nfsv3_type[9];
+extern struct nfsnodehashhead *nfsnodehashtbl;
+extern u_long nfsnodehash;
LIST_HEAD(nfsnodehashhead, nfsnode);
-extern struct nfsnodehashhead *nfs_hash __P((nfsv2fh_t *));
/*
* Create the header for an rpc request packet
@@ -158,14 +589,16 @@ nfsm_reqh(vp, procid, hsiz, bposp)
* Returns the head of the mbuf list.
*/
struct mbuf *
-nfsm_rpchead(cr, nqnfs, procid, auth_type, auth_len, auth_str, mrest,
- mrest_len, mbp, xidp)
+nfsm_rpchead(cr, nmflag, procid, auth_type, auth_len, auth_str, verf_len,
+ verf_str, mrest, mrest_len, mbp, xidp)
register struct ucred *cr;
- int nqnfs;
+ int nmflag;
int procid;
int auth_type;
int auth_len;
char *auth_str;
+ int verf_len;
+ char *verf_str;
struct mbuf *mrest;
int mrest_len;
struct mbuf **mbp;
@@ -179,15 +612,13 @@ nfsm_rpchead(cr, nqnfs, procid, auth_type, auth_len, auth_str, mrest,
int siz, grpsiz, authsiz;
authsiz = nfsm_rndup(auth_len);
- if (auth_type == RPCAUTH_NQNFS)
- authsiz += 2 * NFSX_UNSIGNED;
MGETHDR(mb, M_WAIT, MT_DATA);
- if ((authsiz + 10*NFSX_UNSIGNED) >= MINCLSIZE) {
+ if ((authsiz + 10 * NFSX_UNSIGNED) >= MINCLSIZE) {
MCLGET(mb, M_WAIT);
- } else if ((authsiz + 10*NFSX_UNSIGNED) < MHLEN) {
- MH_ALIGN(mb, authsiz + 10*NFSX_UNSIGNED);
+ } else if ((authsiz + 10 * NFSX_UNSIGNED) < MHLEN) {
+ MH_ALIGN(mb, authsiz + 10 * NFSX_UNSIGNED);
} else {
- MH_ALIGN(mb, 8*NFSX_UNSIGNED);
+ MH_ALIGN(mb, 8 * NFSX_UNSIGNED);
}
mb->m_len = 0;
mreq = mb;
@@ -196,20 +627,26 @@ nfsm_rpchead(cr, nqnfs, procid, auth_type, auth_len, auth_str, mrest,
/*
* First the RPC header.
*/
- nfsm_build(tl, u_int32_t *, 8*NFSX_UNSIGNED);
+ nfsm_build(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
if (++nfs_xid == 0)
nfs_xid++;
*tl++ = *xidp = txdr_unsigned(nfs_xid);
*tl++ = rpc_call;
*tl++ = rpc_vers;
- if (nqnfs) {
+ if (nmflag & NFSMNT_NQNFS) {
*tl++ = txdr_unsigned(NQNFS_PROG);
- *tl++ = txdr_unsigned(NQNFS_VER1);
+ *tl++ = txdr_unsigned(NQNFS_VER3);
} else {
*tl++ = txdr_unsigned(NFS_PROG);
- *tl++ = txdr_unsigned(NFS_VER2);
+ if (nmflag & NFSMNT_NFSV3)
+ *tl++ = txdr_unsigned(NFS_VER3);
+ else
+ *tl++ = txdr_unsigned(NFS_VER2);
}
- *tl++ = txdr_unsigned(procid);
+ if (nmflag & NFSMNT_NFSV3)
+ *tl++ = txdr_unsigned(procid);
+ else
+ *tl++ = txdr_unsigned(nfsv2_procid[procid]);
/*
* And then the authorization cred.
@@ -228,10 +665,7 @@ nfsm_rpchead(cr, nqnfs, procid, auth_type, auth_len, auth_str, mrest,
for (i = 0; i < grpsiz; i++)
*tl++ = txdr_unsigned(cr->cr_groups[i]);
break;
- case RPCAUTH_NQNFS:
- nfsm_build(tl, u_int32_t *, 2*NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(cr->cr_uid);
- *tl = txdr_unsigned(auth_len);
+ case RPCAUTH_KERB4:
siz = auth_len;
while (siz > 0) {
if (M_TRAILINGSPACE(mb) == 0) {
@@ -257,11 +691,43 @@ nfsm_rpchead(cr, nqnfs, procid, auth_type, auth_len, auth_str, mrest,
}
break;
};
- nfsm_build(tl, u_int32_t *, 2*NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(RPCAUTH_NULL);
- *tl = 0;
+
+ /*
+ * And the verifier...
+ */
+ nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
+ if (verf_str) {
+ *tl++ = txdr_unsigned(RPCAUTH_KERB4);
+ *tl = txdr_unsigned(verf_len);
+ siz = verf_len;
+ while (siz > 0) {
+ if (M_TRAILINGSPACE(mb) == 0) {
+ MGET(mb2, M_WAIT, MT_DATA);
+ if (siz >= MINCLSIZE)
+ MCLGET(mb2, M_WAIT);
+ mb->m_next = mb2;
+ mb = mb2;
+ mb->m_len = 0;
+ bpos = mtod(mb, caddr_t);
+ }
+ i = min(siz, M_TRAILINGSPACE(mb));
+ bcopy(verf_str, bpos, i);
+ mb->m_len += i;
+ verf_str += i;
+ bpos += i;
+ siz -= i;
+ }
+ if ((siz = (nfsm_rndup(verf_len) - verf_len)) > 0) {
+ for (i = 0; i < siz; i++)
+ *bpos++ = '\0';
+ mb->m_len += siz;
+ }
+ } else {
+ *tl++ = txdr_unsigned(RPCAUTH_NULL);
+ *tl = 0;
+ }
mb->m_next = mrest;
- mreq->m_pkthdr.len = authsiz + 10*NFSX_UNSIGNED + mrest_len;
+ mreq->m_pkthdr.len = authsiz + 10 * NFSX_UNSIGNED + mrest_len;
mreq->m_pkthdr.rcvif = (struct ifnet *)0;
*mbp = mb;
return (mreq);
@@ -594,6 +1060,28 @@ nfs_init()
{
register int i;
+#if !defined(alpha) && defined(DIAGNOSTIC)
+ /*
+ * Check to see if major data structures haven't bloated.
+ */
+ if (sizeof (struct nfsnode) > NFS_NODEALLOC) {
+ printf("struct nfsnode bloated (> %dbytes)\n", NFS_NODEALLOC);
+ printf("Try reducing NFS_SMALLFH\n");
+ }
+ if (sizeof (struct nfsmount) > NFS_MNTALLOC) {
+ printf("struct nfsmount bloated (> %dbytes)\n", NFS_MNTALLOC);
+ printf("Try reducing NFS_MUIDHASHSIZ\n");
+ }
+ if (sizeof (struct nfssvc_sock) > NFS_SVCALLOC) {
+ printf("struct nfssvc_sock bloated (> %dbytes)\n",NFS_SVCALLOC);
+ printf("Try reducing NFS_UIDHASHSIZ\n");
+ }
+ if (sizeof (struct nfsuid) > NFS_UIDALLOC) {
+ printf("struct nfsuid bloated (> %dbytes)\n",NFS_UIDALLOC);
+ printf("Try unionizing the nu_nickname and nu_flag fields\n");
+ }
+#endif
+
nfsrtt.pos = 0;
rpc_vers = txdr_unsigned(RPC_VER2);
rpc_call = txdr_unsigned(RPC_CALL);
@@ -602,17 +1090,16 @@ nfs_init()
rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);
rpc_mismatch = txdr_unsigned(RPC_MISMATCH);
rpc_autherr = txdr_unsigned(RPC_AUTHERR);
- rpc_rejectedcred = txdr_unsigned(AUTH_REJECTCRED);
rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);
- rpc_auth_kerb = txdr_unsigned(RPCAUTH_NQNFS);
- nfs_vers = txdr_unsigned(NFS_VER2);
+ rpc_auth_kerb = txdr_unsigned(RPCAUTH_KERB4);
nfs_prog = txdr_unsigned(NFS_PROG);
+ nqnfs_prog = txdr_unsigned(NQNFS_PROG);
nfs_true = txdr_unsigned(TRUE);
nfs_false = txdr_unsigned(FALSE);
nfs_xdrneg1 = txdr_unsigned(-1);
- /* Loop thru nfs procids */
- for (i = 0; i < NFS_NPROCS; i++)
- nfs_procids[i] = txdr_unsigned(i);
+ nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
+ if (nfs_ticks < 1)
+ nfs_ticks = 1;
#ifdef NFSCLIENT
/* Ensure async daemons disabled */
for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
@@ -632,8 +1119,6 @@ nfs_init()
nqnfsstarttime = boottime.tv_sec + nqsrv_maxlease
+ nqsrv_clockskew + nqsrv_writeslack;
NQLOADNOVRAM(nqnfsstarttime);
- nqnfs_prog = txdr_unsigned(NQNFS_PROG);
- nqnfs_vers = txdr_unsigned(NQNFS_VER1);
CIRCLEQ_INIT(&nqtimerhead);
nqfhhashtbl = hashinit(NQLCHSZ, M_NQLEASE, &nqfhhash);
}
@@ -669,39 +1154,47 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
{
register struct vnode *vp = *vpp;
register struct vattr *vap;
- register struct nfsv2_fattr *fp;
+ register struct nfs_fattr *fp;
extern int (**spec_nfsv2nodeop_p) __P((void *));
register struct nfsnode *np;
- register struct nfsnodehashhead *nhpp;
register int32_t t1;
- caddr_t dpos, cp2;
- int error = 0, isnq;
+ caddr_t cp2;
+ int error = 0;
+ int32_t rdev;
struct mbuf *md;
enum vtype vtyp;
u_short vmode;
- long rdev;
struct timespec mtime;
struct vnode *nvp;
+ int v3 = NFS_ISV3(vp);
md = *mdp;
- dpos = *dposp;
- t1 = (mtod(md, caddr_t) + md->m_len) - dpos;
- isnq = (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS);
- error = nfsm_disct(&md, &dpos, NFSX_FATTR(isnq), t1, &cp2);
+ t1 = (mtod(md, caddr_t) + md->m_len) - *dposp;
+ error = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, &cp2);
if (error)
return (error);
- fp = (struct nfsv2_fattr *)cp2;
- vtyp = nfstov_type(fp->fa_type);
- vmode = fxdr_unsigned(u_short, fp->fa_mode);
- if (vtyp == VNON || vtyp == VREG)
- vtyp = IFTOVT(vmode);
- if (isnq) {
- rdev = fxdr_unsigned(int32_t, fp->fa_nqrdev);
- fxdr_nqtime(&fp->fa_nqmtime, &mtime);
+ fp = (struct nfs_fattr *)cp2;
+ if (v3) {
+ vtyp = nfsv3tov_type(fp->fa_type);
+ vmode = fxdr_unsigned(u_short, fp->fa_mode);
+ rdev = makedev(fxdr_unsigned(u_char, fp->fa3_rdev.specdata1),
+ fxdr_unsigned(u_char, fp->fa3_rdev.specdata2));
+ fxdr_nfsv3time(&fp->fa3_mtime, &mtime);
} else {
- rdev = fxdr_unsigned(int32_t, fp->fa_nfsrdev);
- fxdr_nfstime(&fp->fa_nfsmtime, &mtime);
+ vtyp = nfsv2tov_type(fp->fa_type);
+ vmode = fxdr_unsigned(u_short, fp->fa_mode);
+ if (vtyp == VNON || vtyp == VREG)
+ vtyp = IFTOVT(vmode);
+ rdev = fxdr_unsigned(int32_t, fp->fa2_rdev);
+ fxdr_nfsv2time(&fp->fa2_mtime, &mtime);
+
+ /*
+ * Really ugly NFSv2 kludge.
+ */
+ if (vtyp == VCHR && rdev == 0xffffffff)
+ vtyp = VFIFO;
}
+
/*
* If v_type == VNON it is a new node, so fill in the v_type,
* n_mtime fields. Check to see if it represents a special
@@ -711,17 +1204,10 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
*/
np = VTONFS(vp);
if (vp->v_type != vtyp) {
- if (vtyp == VCHR && rdev == 0xffffffff)
- vp->v_type = vtyp = VFIFO;
- else
- vp->v_type = vtyp;
+ vp->v_type = vtyp;
if (vp->v_type == VFIFO) {
-#ifdef FIFO
extern int (**fifo_nfsv2nodeop_p) __P((void *));
vp->v_op = fifo_nfsv2nodeop_p;
-#else
- return (EOPNOTSUPP);
-#endif /* FIFO */
}
if (vp->v_type == VCHR || vp->v_type == VBLK) {
vp->v_op = spec_nfsv2nodeop_p;
@@ -729,8 +1215,13 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
if (nvp) {
/*
* Discard unneeded vnode, but save its nfsnode.
+ * Since the nfsnode does not have a lock, its
+ * vnode lock has to be carried over.
*/
- LIST_REMOVE(np, n_hash);
+#ifdef Lite2_integrated
+ nvp->v_vnlock = vp->v_vnlock;
+ vp->v_vnlock = NULL;
+#endif
nvp->v_data = vp->v_data;
vp->v_data = NULL;
vp->v_op = spec_vnodeop_p;
@@ -740,8 +1231,6 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
* Reinitialize aliased node.
*/
np->n_vnode = nvp;
- nhpp = nfs_hash(&np->n_fh);
- LIST_INSERT_HEAD(nhpp, np, n_hash);
*vpp = vp = nvp;
}
}
@@ -750,31 +1239,37 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
vap = &np->n_vattr;
vap->va_type = vtyp;
vap->va_mode = (vmode & 07777);
- vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
- vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
- vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
vap->va_rdev = (dev_t)rdev;
vap->va_mtime = mtime;
vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
- if (isnq) {
- fxdr_hyper(&fp->fa_nqsize, &vap->va_size);
- vap->va_blocksize = fxdr_unsigned(int32_t, fp->fa_nqblocksize);
- fxdr_hyper(&fp->fa_nqbytes, &vap->va_bytes);
- vap->va_fileid = fxdr_unsigned(int32_t, fp->fa_nqfileid);
- fxdr_nqtime(&fp->fa_nqatime, &vap->va_atime);
- vap->va_flags = fxdr_unsigned(u_int32_t, fp->fa_nqflags);
- fxdr_nqtime(&fp->fa_nqctime, &vap->va_ctime);
- vap->va_gen = fxdr_unsigned(u_int32_t, fp->fa_nqgen);
- fxdr_hyper(&fp->fa_nqfilerev, &vap->va_filerev);
+ if (v3) {
+ vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
+ vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
+ vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
+ fxdr_hyper(&fp->fa3_size, &vap->va_size);
+ vap->va_blocksize = NFS_FABLKSIZE;
+ fxdr_hyper(&fp->fa3_used, &vap->va_bytes);
+ vap->va_fileid = fxdr_unsigned(int32_t,
+ fp->fa3_fileid.nfsuquad[1]);
+ fxdr_nfsv3time(&fp->fa3_atime, &vap->va_atime);
+ fxdr_nfsv3time(&fp->fa3_ctime, &vap->va_ctime);
+ vap->va_flags = 0;
+ vap->va_filerev = 0;
} else {
- vap->va_size = fxdr_unsigned(u_int32_t, fp->fa_nfssize);
- vap->va_blocksize = fxdr_unsigned(int32_t, fp->fa_nfsblocksize);
- vap->va_bytes = fxdr_unsigned(int32_t, fp->fa_nfsblocks) * NFS_FABLKSIZE;
- vap->va_fileid = fxdr_unsigned(int32_t, fp->fa_nfsfileid);
- fxdr_nfstime(&fp->fa_nfsatime, &vap->va_atime);
+ vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
+ vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
+ vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
+ vap->va_size = fxdr_unsigned(u_int32_t, fp->fa2_size);
+ vap->va_blocksize = fxdr_unsigned(int32_t, fp->fa2_blocksize);
+ vap->va_bytes = fxdr_unsigned(int32_t, fp->fa2_blocks)
+ * NFS_FABLKSIZE;
+ vap->va_fileid = fxdr_unsigned(int32_t, fp->fa2_fileid);
+ fxdr_nfsv2time(&fp->fa2_atime, &vap->va_atime);
vap->va_flags = 0;
- fxdr_nfstime(&fp->fa_nfsctime, &vap->va_ctime);
- vap->va_gen = 0;
+ vap->va_ctime.tv_sec = fxdr_unsigned(u_int32_t,
+ fp->fa2_ctime.nfsv2_sec);
+ vap->va_ctime.tv_nsec = 0;
+ vap->va_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec);
vap->va_filerev = 0;
}
if (vap->va_size != np->n_size) {
@@ -791,26 +1286,13 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
np->n_size = vap->va_size;
}
np->n_attrstamp = time.tv_sec;
- *dposp = dpos;
- *mdp = md;
if (vaper != NULL) {
bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap));
-#ifdef notdef
- if ((np->n_flag & NMODIFIED) && np->n_size > vap->va_size)
- if (np->n_size > vap->va_size)
- vaper->va_size = np->n_size;
-#endif
if (np->n_flag & NCHG) {
- if (np->n_flag & NACC) {
- vaper->va_atime.tv_sec = np->n_atim.tv_sec;
- vaper->va_atime.tv_nsec =
- np->n_atim.tv_usec * 1000;
- }
- if (np->n_flag & NUPD) {
- vaper->va_mtime.tv_sec = np->n_mtim.tv_sec;
- vaper->va_mtime.tv_nsec =
- np->n_mtim.tv_usec * 1000;
- }
+ if (np->n_flag & NACC)
+ vaper->va_atime = np->n_atim;
+ if (np->n_flag & NUPD)
+ vaper->va_mtime = np->n_mtim;
}
}
return (0);
@@ -829,12 +1311,7 @@ nfs_getattrcache(vp, vaper)
register struct nfsnode *np = VTONFS(vp);
register struct vattr *vap;
- if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQLOOKLEASE) {
- if (!NQNFS_CKCACHABLE(vp, NQL_READ) || np->n_attrstamp == 0) {
- nfsstats.attrcache_misses++;
- return (ENOENT);
- }
- } else if ((time.tv_sec - np->n_attrstamp) >= NFS_ATTRTIMEO(np)) {
+ if ((time.tv_sec - np->n_attrstamp) >= NFS_ATTRTIMEO(np)) {
nfsstats.attrcache_misses++;
return (ENOENT);
}
@@ -854,33 +1331,21 @@ nfs_getattrcache(vp, vaper)
np->n_size = vap->va_size;
}
bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(struct vattr));
-#ifdef notdef
- if ((np->n_flag & NMODIFIED) == 0) {
- np->n_size = vaper->va_size;
- vnode_pager_setsize(vp, (u_long)np->n_size);
- } else if (np->n_size > vaper->va_size)
- if (np->n_size > vaper->va_size)
- vaper->va_size = np->n_size;
-#endif
if (np->n_flag & NCHG) {
- if (np->n_flag & NACC) {
- vaper->va_atime.tv_sec = np->n_atim.tv_sec;
- vaper->va_atime.tv_nsec = np->n_atim.tv_usec * 1000;
- }
- if (np->n_flag & NUPD) {
- vaper->va_mtime.tv_sec = np->n_mtim.tv_sec;
- vaper->va_mtime.tv_nsec = np->n_mtim.tv_usec * 1000;
- }
+ if (np->n_flag & NACC)
+ vaper->va_atime = np->n_atim;
+ if (np->n_flag & NUPD)
+ vaper->va_mtime = np->n_mtim;
}
return (0);
}
-#endif
+#endif /* NFSCLIENT */
/*
* Set up nameidata for a lookup() call and do it
*/
int
-nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, p)
+nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
register struct nameidata *ndp;
fhandle_t *fhp;
int len;
@@ -888,7 +1353,9 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, p)
struct mbuf *nam;
struct mbuf **mdp;
caddr_t *dposp;
+ struct vnode **retdirp;
struct proc *p;
+ int kerbflag;
{
register int i, rem;
register struct mbuf *md;
@@ -897,6 +1364,7 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, p)
int error, rdonly;
struct componentname *cnp = &ndp->ni_cnd;
+ *retdirp = (struct vnode *)0;
MALLOC(cnp->cn_pnbuf, char *, len + 1, M_NAMEI, M_WAITOK);
/*
* Copy the name from the mbuf list to ndp->ni_pnbuf
@@ -917,7 +1385,7 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, p)
rem = md->m_len;
}
if (*fromcp == '\0' || *fromcp == '/') {
- error = EINVAL;
+ error = EACCES;
goto out;
}
*tocp++ = *fromcp++;
@@ -939,7 +1407,7 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, p)
* Extract and set starting directory.
*/
error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
- nam, &rdonly);
+ nam, &rdonly, kerbflag);
if (error)
goto out;
if (dp->v_type != VDIR) {
@@ -947,6 +1415,8 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, p)
error = ENOTDIR;
goto out;
}
+ VREF(dp);
+ *retdirp = dp;
ndp->ni_startdir = dp;
if (rdonly)
cnp->cn_flags |= (NOCROSSMOUNT | RDONLY);
@@ -956,7 +1426,8 @@ nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, p)
* And call lookup() to do the real work
*/
cnp->cn_proc = p;
- if ((error = lookup(ndp)) != 0)
+ error = lookup(ndp);
+ if (error)
goto out;
/*
* Check for encountering a symbolic link
@@ -1041,11 +1512,114 @@ nfsm_adj(mp, len, nul)
}
count -= m->m_len;
}
- while ((m = m->m_next) != NULL)
+ for (m = m->m_next;m;m = m->m_next)
m->m_len = 0;
}
/*
+ * Make these functions instead of macros, so that the kernel text size
+ * doesn't get too big...
+ */
+void
+nfsm_srvwcc(nfsd, before_ret, before_vap, after_ret, after_vap, mbp, bposp)
+ struct nfsrv_descript *nfsd;
+ int before_ret;
+ register struct vattr *before_vap;
+ int after_ret;
+ struct vattr *after_vap;
+ struct mbuf **mbp;
+ char **bposp;
+{
+ register struct mbuf *mb = *mbp, *mb2;
+ register char *bpos = *bposp;
+ register u_int32_t *tl;
+
+ if (before_ret) {
+ nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
+ *tl = nfs_false;
+ } else {
+ nfsm_build(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
+ *tl++ = nfs_true;
+ txdr_hyper(&(before_vap->va_size), tl);
+ tl += 2;
+ txdr_nfsv3time(&(before_vap->va_mtime), tl);
+ tl += 2;
+ txdr_nfsv3time(&(before_vap->va_ctime), tl);
+ }
+ *bposp = bpos;
+ *mbp = mb;
+ nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp);
+}
+
+void
+nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp)
+ struct nfsrv_descript *nfsd;
+ int after_ret;
+ struct vattr *after_vap;
+ struct mbuf **mbp;
+ char **bposp;
+{
+ register struct mbuf *mb = *mbp, *mb2;
+ register char *bpos = *bposp;
+ register u_int32_t *tl;
+ register struct nfs_fattr *fp;
+
+ if (after_ret) {
+ nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
+ *tl = nfs_false;
+ } else {
+ nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_V3FATTR);
+ *tl++ = nfs_true;
+ fp = (struct nfs_fattr *)tl;
+ nfsm_srvfattr(nfsd, after_vap, fp);
+ }
+ *mbp = mb;
+ *bposp = bpos;
+}
+
+void
+nfsm_srvfattr(nfsd, vap, fp)
+ register struct nfsrv_descript *nfsd;
+ register struct vattr *vap;
+ register struct nfs_fattr *fp;
+{
+
+ fp->fa_nlink = txdr_unsigned(vap->va_nlink);
+ fp->fa_uid = txdr_unsigned(vap->va_uid);
+ fp->fa_gid = txdr_unsigned(vap->va_gid);
+ if (nfsd->nd_flag & ND_NFSV3) {
+ fp->fa_type = vtonfsv3_type(vap->va_type);
+ fp->fa_mode = vtonfsv3_mode(vap->va_mode);
+ txdr_hyper(&vap->va_size, &fp->fa3_size);
+ txdr_hyper(&vap->va_bytes, &fp->fa3_used);
+ fp->fa3_rdev.specdata1 = txdr_unsigned(major(vap->va_rdev));
+ fp->fa3_rdev.specdata2 = txdr_unsigned(minor(vap->va_rdev));
+ fp->fa3_fsid.nfsuquad[0] = 0;
+ fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid);
+ fp->fa3_fileid.nfsuquad[0] = 0;
+ fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(vap->va_fileid);
+ txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime);
+ txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime);
+ txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime);
+ } else {
+ fp->fa_type = vtonfsv2_type(vap->va_type);
+ fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
+ fp->fa2_size = txdr_unsigned(vap->va_size);
+ fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize);
+ if (vap->va_type == VFIFO)
+ fp->fa2_rdev = 0xffffffff;
+ else
+ fp->fa2_rdev = txdr_unsigned(vap->va_rdev);
+ fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE);
+ fp->fa2_fsid = txdr_unsigned(vap->va_fsid);
+ fp->fa2_fileid = txdr_unsigned(vap->va_fileid);
+ txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime);
+ txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime);
+ txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime);
+ }
+}
+
+/*
* nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
* - look up fsid in mount list (if not found ret error)
* - get vp and export rights by calling VFS_FHTOVP()
@@ -1053,7 +1627,7 @@ nfsm_adj(mp, len, nul)
* - if not lockflag unlock it with VOP_UNLOCK()
*/
int
-nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp)
+nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
fhandle_t *fhp;
int lockflag;
struct vnode **vpp;
@@ -1061,15 +1635,23 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp)
struct nfssvc_sock *slp;
struct mbuf *nam;
int *rdonlyp;
+ int kerbflag;
{
+#ifdef Lite2_integrated
+ struct proc *p = curproc; /* XXX */
+#endif
register struct mount *mp;
- register struct nfsuid *uidp;
register int i;
struct ucred *credanon;
int error, exflags;
*vpp = (struct vnode *)0;
- if ((mp = getvfs(&fhp->fh_fsid)) == NULL)
+#ifdef Lite2_integrated
+ mp = vfs_getvfs(&fhp->fh_fsid);
+#else
+ mp = getvfs(&fhp->fh_fsid);
+#endif
+ if (!mp)
return (ESTALE);
error = VFS_FHTOVP(mp, &fhp->fh_fid, nam, vpp, &exflags, &credanon);
if (error)
@@ -1078,20 +1660,13 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp)
* Check/setup credentials.
*/
if (exflags & MNT_EXKERB) {
- for (uidp = NUIDHASH(slp, cred->cr_uid)->lh_first; uidp != 0;
- uidp = uidp->nu_hash.le_next) {
- if (uidp->nu_uid == cred->cr_uid)
- break;
- }
- if (uidp == 0) {
+ if (!kerbflag) {
vput(*vpp);
- return (NQNFS_AUTHERR);
+ return (NFSERR_AUTHERR | AUTH_TOOWEAK);
}
- cred->cr_uid = uidp->nu_cr.cr_uid;
- cred->cr_gid = uidp->nu_cr.cr_gid;
- for (i = 0; i < uidp->nu_cr.cr_ngroups; i++)
- cred->cr_groups[i] = uidp->nu_cr.cr_groups[i];
- cred->cr_ngroups = i;
+ } else if (kerbflag) {
+ vput(*vpp);
+ return (NFSERR_AUTHERR | AUTH_TOOWEAK);
} else if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
cred->cr_uid = credanon->cr_uid;
cred->cr_gid = credanon->cr_gid;
@@ -1104,7 +1679,11 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp)
else
*rdonlyp = 0;
if (!lockflag)
+#ifdef Lite2_integrated
+ VOP_UNLOCK(*vpp, 0, p);
+#else
VOP_UNLOCK(*vpp);
+#endif
return (0);
}
@@ -1150,3 +1729,186 @@ netaddr_match(family, haddr, nam)
};
return (0);
}
+
+static nfsuint64 nfs_nullcookie = {{ 0, 0 }};
+/*
+ * This function finds the directory cookie that corresponds to the
+ * logical byte offset given.
+ */
+nfsuint64 *
+nfs_getcookie(np, off, add)
+ register struct nfsnode *np;
+ off_t off;
+ int add;
+{
+ register struct nfsdmap *dp, *dp2;
+ register int pos;
+
+ pos = off / NFS_DIRBLKSIZ;
+ if (pos == 0) {
+#ifdef DIAGNOSTIC
+ if (add)
+ panic("nfs getcookie add at 0");
+#endif
+ return (&nfs_nullcookie);
+ }
+ pos--;
+ dp = np->n_cookies.lh_first;
+ if (!dp) {
+ if (add) {
+ MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap),
+ M_NFSDIROFF, M_WAITOK);
+ dp->ndm_eocookie = 0;
+ LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list);
+ } else
+ return ((nfsuint64 *)0);
+ }
+ while (pos >= NFSNUMCOOKIES) {
+ pos -= NFSNUMCOOKIES;
+ if (dp->ndm_list.le_next) {
+ if (!add && dp->ndm_eocookie < NFSNUMCOOKIES &&
+ pos >= dp->ndm_eocookie)
+ return ((nfsuint64 *)0);
+ dp = dp->ndm_list.le_next;
+ } else if (add) {
+ MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap),
+ M_NFSDIROFF, M_WAITOK);
+ dp2->ndm_eocookie = 0;
+ LIST_INSERT_AFTER(dp, dp2, ndm_list);
+ dp = dp2;
+ } else
+ return ((nfsuint64 *)0);
+ }
+ if (pos >= dp->ndm_eocookie) {
+ if (add)
+ dp->ndm_eocookie = pos + 1;
+ else
+ return ((nfsuint64 *)0);
+ }
+ return (&dp->ndm_cookies[pos]);
+}
+
+/*
+ * Invalidate cached directory information, except for the actual directory
+ * blocks (which are invalidated separately).
+ * Done mainly to avoid the use of stale offset cookies.
+ */
+void
+nfs_invaldir(vp)
+ register struct vnode *vp;
+{
+#ifdef notdef /* XXX */
+ register struct nfsnode *np = VTONFS(vp);
+
+#ifdef DIAGNOSTIC
+ if (vp->v_type != VDIR)
+ panic("nfs: invaldir not dir");
+#endif
+ np->n_direofoffset = 0;
+ np->n_cookieverf.nfsuquad[0] = 0;
+ np->n_cookieverf.nfsuquad[1] = 0;
+ if (np->n_cookies.lh_first)
+ np->n_cookies.lh_first->ndm_eocookie = 0;
+#endif
+}
+
+/*
+ * The write verifier has changed (probably due to a server reboot), so all
+ * B_NEEDCOMMIT blocks will have to be written again. Since they are on the
+ * dirty block list as B_DELWRI, all this takes is clearing the B_NEEDCOMMIT
+ * flag. Once done the new write verifier can be set for the mount point.
+ */
+void
+nfs_clearcommit(mp)
+ struct mount *mp;
+{
+ register struct vnode *vp, *nvp;
+ register struct buf *bp, *nbp;
+ int s;
+
+ s = splbio();
+loop:
+ for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) {
+ if (vp->v_mount != mp) /* Paranoia */
+ goto loop;
+ nvp = vp->v_mntvnodes.le_next;
+ for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
+ nbp = bp->b_vnbufs.le_next;
+ if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
+ == (B_DELWRI | B_NEEDCOMMIT))
+ bp->b_flags &= ~B_NEEDCOMMIT;
+ }
+ }
+ splx(s);
+}
+
+/*
+ * Map errnos to NFS error numbers. For Version 3 also filter out error
+ * numbers not specified for the associated procedure.
+ */
+int
+nfsrv_errmap(nd, err)
+ struct nfsrv_descript *nd;
+ register int err;
+{
+ register short *defaulterrp, *errp;
+
+ if (nd->nd_flag & ND_NFSV3) {
+ if (nd->nd_procnum <= NFSPROC_COMMIT) {
+ errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
+ while (*++errp) {
+ if (*errp == err)
+ return (err);
+ else if (*errp > err)
+ break;
+ }
+ return ((int)*defaulterrp);
+ } else
+ return (err & 0xffff);
+ }
+ if (err <= ELAST)
+ return ((int)nfsrv_v2errmap[err - 1]);
+ return (NFSERR_IO);
+}
+
+/*
+ * Sort the group list in increasing numerical order.
+ * (Insertion sort by Chris Torek, who was grossed out by the bubble sort
+ * that used to be here.)
+ */
+void
+nfsrvw_sort(list, num)
+ register gid_t *list;
+ register int num;
+{
+ register int i, j;
+ gid_t v;
+
+ /* Insertion sort. */
+ for (i = 1; i < num; i++) {
+ v = list[i];
+ /* find correct slot for value v, moving others up */
+ for (j = i; --j >= 0 && v < list[j];)
+ list[j + 1] = list[j];
+ list[j + 1] = v;
+ }
+}
+
+/*
+ * copy credentials making sure that the result can be compared with bcmp().
+ */
+void
+nfsrv_setcred(incred, outcred)
+ register struct ucred *incred, *outcred;
+{
+ register int i;
+
+ bzero((caddr_t)outcred, sizeof (struct ucred));
+ outcred->cr_ref = 1;
+ outcred->cr_uid = incred->cr_uid;
+ outcred->cr_gid = incred->cr_gid;
+ outcred->cr_ngroups = incred->cr_ngroups;
+ for (i = 0; i < incred->cr_ngroups; i++)
+ outcred->cr_groups[i] = incred->cr_groups[i];
+ nfsrvw_sort(outcred->cr_groups, outcred->cr_ngroups);
+}