Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 1 Apr 2023 21:25:03 GMT
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: f4179ad46fa4 - main - nfscommon: Add support for an NFSv4 operation bitmap
Message-ID:  <202304012125.331LP3OO094168@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by rmacklem:

URL: https://cgit.FreeBSD.org/src/commit/?id=f4179ad46fa4ff717557e5485072c004e6054416

commit f4179ad46fa4ff717557e5485072c004e6054416
Author:     Rick Macklem <rmacklem@FreeBSD.org>
AuthorDate: 2023-04-01 21:22:26 +0000
Commit:     Rick Macklem <rmacklem@FreeBSD.org>
CommitDate: 2023-04-01 21:22:26 +0000

    nfscommon: Add support for an NFSv4 operation bitmap
    
    NFSv4.1/4.2 uses operation bitmaps for various operations,
    such as the SP4_MACH_CRED case for ExchangeID.
    This patch adds support for operation bitmaps so that
    support for SP4_MACH_CRED can be added to the NFSv4.1/4.2
    server in a future commit.
    
    This commit should not change any NFSv4.1/4.2 semantics.
    
    MFC after:      3 months
---
 sys/fs/nfs/nfs.h            |  31 ++++++++++++
 sys/fs/nfs/nfs_commonsubs.c |  62 +++++++++++++++++++++++
 sys/fs/nfs/nfs_var.h        |   2 +
 sys/fs/nfs/nfsproto.h       | 120 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 215 insertions(+)

diff --git a/sys/fs/nfs/nfs.h b/sys/fs/nfs/nfs.h
index eac318512a35..9d0a2d8191b2 100644
--- a/sys/fs/nfs/nfs.h
+++ b/sys/fs/nfs/nfs.h
@@ -344,6 +344,7 @@ struct nfsreferral {
 #define	LCL_RECLAIMONEFS	0x00080000
 #define	LCL_NFSV42		0x00100000
 #define	LCL_TLSCB		0x00200000
+#define	LCL_MACHCRED		0x00400000
 
 #define	LCL_GSS		LCL_KERBV	/* Or of all mechs */
 
@@ -552,6 +553,34 @@ typedef struct {
 	(b)->bits[2] = NFSATTRBIT_REFERRAL2;				\
 } while (0)
 
+/*
+ * Here is the definition of the operation bits array and macros that
+ * manipulate it.
+ * THE MACROS MUST BE MANUALLY MODIFIED IF NFSOPBIT_MAXWORDS CHANGES!!
+ * It is (NFSV42_NOPS + 31) / 32.
+ */
+#define	NFSOPBIT_MAXWORDS	3
+
+typedef struct {
+	uint32_t bits[NFSOPBIT_MAXWORDS];
+} nfsopbit_t;
+
+#define	NFSZERO_OPBIT(b) do {						\
+	(b)->bits[0] = 0;						\
+	(b)->bits[1] = 0;						\
+	(b)->bits[2] = 0;						\
+} while (0)
+
+#define	NFSSET_OPBIT(t, f) do {						\
+	(t)->bits[0] = (f)->bits[0];			 		\
+	(t)->bits[1] = (f)->bits[1];					\
+	(t)->bits[2] = (f)->bits[2];					\
+} while (0)
+
+#define	NFSISSET_OPBIT(b, p)	((b)->bits[(p) / 32] & (1 << ((p) % 32)))
+#define	NFSSETBIT_OPBIT(b, p)	((b)->bits[(p) / 32] |= (1 << ((p) % 32)))
+#define	NFSCLRBIT_OPBIT(b, p)	((b)->bits[(p) / 32] &= ~(1 << ((p) % 32)))
+
 /*
  * Store uid, gid creds that were used when the stateid was acquired.
  * The RPC layer allows NFS_MAXGRPS + 1 groups to go out on the wire,
@@ -687,6 +716,7 @@ struct nfsrv_descript {
 	int			nd_bextpg;	/* Current ext_pgs page */
 	int			nd_bextpgsiz;	/* Bytes left in page */
 	int			nd_maxextsiz;	/* Max ext_pgs mbuf size */
+	nfsopbit_t		nd_allowops;	/* Allowed ops ND_MACHCRED */
 };
 
 #define	nd_princlen	nd_gssnamelen
@@ -736,6 +766,7 @@ struct nfsrv_descript {
 #define	ND_EXTLSCERT		0x10000000000
 #define	ND_EXTLSCERTUSER	0x20000000000
 #define	ND_ERELOOKUP		0x40000000000
+#define	ND_MACHCRED		0x80000000000
 
 /*
  * ND_GSS should be the "or" of all GSS type authentications.
diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c
index 48798087b177..81bd2beba749 100644
--- a/sys/fs/nfs/nfs_commonsubs.c
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -1222,6 +1222,47 @@ nfsmout:
 	return (error);
 }
 
+/*
+ * Get operation bits from an mbuf list.
+ * Returns EBADRPC for a parsing error, 0 otherwise.
+ */
+int
+nfsrv_getopbits(struct nfsrv_descript *nd, nfsopbit_t *opbitp, int *cntp)
+{
+	uint32_t *tl;
+	int cnt, i, outcnt;
+	int error = 0;
+
+	NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+	cnt = fxdr_unsigned(int, *tl);
+	if (cnt < 0) {
+		error = NFSERR_BADXDR;
+		goto nfsmout;
+	}
+	if (cnt > NFSOPBIT_MAXWORDS)
+		outcnt = NFSOPBIT_MAXWORDS;
+	else
+		outcnt = cnt;
+	NFSZERO_OPBIT(opbitp);
+	if (outcnt > 0) {
+		NFSM_DISSECT(tl, uint32_t *, outcnt * NFSX_UNSIGNED);
+		for (i = 0; i < outcnt; i++)
+			opbitp->bits[i] = fxdr_unsigned(uint32_t, *tl++);
+	}
+	for (i = 0; i < (cnt - outcnt); i++) {
+		NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+		if (*tl != 0) {
+			error = NFSERR_BADXDR;
+			goto nfsmout;
+		}
+	}
+	if (cntp != NULL)
+		*cntp = NFSX_UNSIGNED + (cnt * NFSX_UNSIGNED);
+nfsmout:
+	NFSEXITCODE2(error, nd);
+	return (error);
+}
+
 /*
  * Get the attributes for V4.
  * If the compare flag is true, test for any attribute changes,
@@ -3142,6 +3183,27 @@ nfsrv_putattrbit(struct nfsrv_descript *nd, nfsattrbit_t *attrbitp)
 	return (bytesize);
 }
 
+/*
+ * Put the operation bits onto an mbuf list.
+ * Return the number of bytes of output generated.
+ */
+int
+nfsrv_putopbit(struct nfsrv_descript *nd, nfsopbit_t *opbitp)
+{
+	uint32_t *tl;
+	int cnt, i, bytesize;
+
+	for (cnt = NFSOPBIT_MAXWORDS; cnt > 0; cnt--)
+		if (opbitp->bits[cnt - 1])
+			break;
+	bytesize = (cnt + 1) * NFSX_UNSIGNED;
+	NFSM_BUILD(tl, uint32_t *, bytesize);
+	*tl++ = txdr_unsigned(cnt);
+	for (i = 0; i < cnt; i++)
+		*tl++ = txdr_unsigned(opbitp->bits[i]);
+	return (bytesize);
+}
+
 /*
  * Convert a uid to a string.
  * If the lookup fails, just output the digits.
diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h
index 55396bfb0902..ad1eb73b1090 100644
--- a/sys/fs/nfs/nfs_var.h
+++ b/sys/fs/nfs/nfs_var.h
@@ -337,6 +337,7 @@ int nfsrv_dissectacl(struct nfsrv_descript *, NFSACL_T *, bool, int *,
     int *, NFSPROC_T *);
 int nfsrv_getattrbits(struct nfsrv_descript *, nfsattrbit_t *, int *,
     int *);
+int nfsrv_getopbits(struct nfsrv_descript *, nfsopbit_t *, int *);
 int nfsv4_loadattr(struct nfsrv_descript *, vnode_t,
     struct nfsvattr *, struct nfsfh **, fhandle_t *, int,
     struct nfsv3_pathconf *, struct statfs *, struct nfsstatfs *,
@@ -391,6 +392,7 @@ int nfsd_excred(struct nfsrv_descript *, struct nfsexstuff *, struct ucred *,
     bool);
 int nfsrv_mtofh(struct nfsrv_descript *, struct nfsrvfh *);
 int nfsrv_putattrbit(struct nfsrv_descript *, nfsattrbit_t *);
+int nfsrv_putopbit(struct nfsrv_descript *, nfsopbit_t *);
 void nfsrv_wcc(struct nfsrv_descript *, int, struct nfsvattr *, int,
     struct nfsvattr *);
 int nfsv4_fillattr(struct nfsrv_descript *, struct mount *, vnode_t, NFSACL_T *,
diff --git a/sys/fs/nfs/nfsproto.h b/sys/fs/nfs/nfsproto.h
index ceecc63a7732..0d36ee84642a 100644
--- a/sys/fs/nfs/nfsproto.h
+++ b/sys/fs/nfs/nfsproto.h
@@ -1427,6 +1427,126 @@ struct nfsv3_sattr {
 #define	NFSATTRBIT_REFERRAL1	NFSATTRBM_MOUNTEDONFILEID
 #define	NFSATTRBIT_REFERRAL2		0
 
+/* Bits for the operations bitmaps. */
+#define	NFSV4OPBM_ACCESS		0x00000008
+#define	NFSV4OPBM_CLOSE			0x00000010
+#define	NFSV4OPBM_COMMIT		0x00000020
+#define	NFSV4OPBM_CREATE		0x00000040
+#define	NFSV4OPBM_DELEGPURGE		0x00000080
+#define	NFSV4OPBM_DELEGRETURN		0x00000100
+#define	NFSV4OPBM_GETATTR		0x00000200
+#define	NFSV4OPBM_GETFH			0x00000400
+#define	NFSV4OPBM_LINK			0x00000800
+#define	NFSV4OPBM_LOCK			0x00001000
+#define	NFSV4OPBM_LOCKT			0x00002000
+#define	NFSV4OPBM_LOCKU			0x00004000
+#define	NFSV4OPBM_LOOKUP		0x00008000
+#define	NFSV4OPBM_LOOKUPP		0x00010000
+#define	NFSV4OPBM_NVERIFY		0x00020000
+#define	NFSV4OPBM_OPEN			0x00040000
+#define	NFSV4OPBM_OPENATTR		0x00080000
+#define	NFSV4OPBM_OPENCONFIRM		0x00100000
+#define	NFSV4OPBM_OPENDOWNGRADE		0x00200000
+#define	NFSV4OPBM_PUTFH			0x00400000
+#define	NFSV4OPBM_PUTPUBFH		0x00800000
+#define	NFSV4OPBM_PUTROOTFH		0x01000000
+#define	NFSV4OPBM_READ			0x02000000
+#define	NFSV4OPBM_READDIR		0x04000000
+#define	NFSV4OPBM_READLINK		0x08000000
+#define	NFSV4OPBM_REMOVE		0x10000000
+#define	NFSV4OPBM_RENAME		0x20000000
+#define	NFSV4OPBM_RENEW			0x40000000
+#define	NFSV4OPBM_RESTOREFH		0x80000000
+#define	NFSV4OPBM_SAVEFH		0x00000001
+#define	NFSV4OPBM_SECINFO		0x00000002
+#define	NFSV4OPBM_SETATTR		0x00000004
+#define	NFSV4OPBM_SETCLIENTID		0x00000008
+#define	NFSV4OPBM_SETCLIENTIDCFRM	0x00000010
+#define	NFSV4OPBM_VERIFY		0x00000020
+#define	NFSV4OPBM_WRITE			0x00000040
+#define	NFSV4OPBM_RELEASELCKOWN		0x00000080
+#define	NFSV4OPBM_BACKCHANNELCTL	0x00000100
+#define	NFSV4OPBM_BINDCONNTOSESS	0x00000200
+#define	NFSV4OPBM_EXCHANGEID		0x00000400
+#define	NFSV4OPBM_CREATESESSION		0x00000800
+#define	NFSV4OPBM_DESTROYSESSION	0x00001000
+#define	NFSV4OPBM_FREESTATEID		0x00002000
+#define	NFSV4OPBM_GETDIRDELEG		0x00004000
+#define	NFSV4OPBM_GETDEVINFO		0x00008000
+#define	NFSV4OPBM_GETDEVLIST		0x00010000
+#define	NFSV4OPBM_LAYOUTCOMMIT		0x00020000
+#define	NFSV4OPBM_LAYOUTGET		0x00040000
+#define	NFSV4OPBM_LAYOUTRETURN		0x00080000
+#define	NFSV4OPBM_SECINFONONAME		0x00100000
+#define	NFSV4OPBM_SEQUENCE		0x00200000
+#define	NFSV4OPBM_SETSSV		0x00400000
+#define	NFSV4OPBM_TESTSTATEID		0x00800000
+#define	NFSV4OPBM_WANTDELEG		0x01000000
+#define	NFSV4OPBM_DESTROYCLIENTID	0x02000000
+#define	NFSV4OPBM_RECLAIMCOMPL		0x04000000
+#define	NFSV4OPBM_ALLOCATE		0x08000000
+#define	NFSV4OPBM_COPY			0x10000000
+#define	NFSV4OPBM_COPYNOTIFY		0x20000000
+#define	NFSV4OPBM_DEALLOCATE		0x40000000
+#define	NFSV4OPBM_IOADVISE		0x80000000
+#define	NFSV4OPBM_LAYOUTERROR		0x00000001
+#define	NFSV4OPBM_LAYOUTSTATS		0x00000002
+#define	NFSV4OPBM_OFFLOADCANCEL		0x00000004
+#define	NFSV4OPBM_OFFLOADSTATUS		0x00000008
+#define	NFSV4OPBM_READPLUS		0x00000010
+#define	NFSV4OPBM_SEEK			0x00000020
+#define	NFSV4OPBM_WRITESAME		0x00000040
+#define	NFSV4OPBM_CLONE			0x00000080
+#define	NFSV4OPBM_GETXATTR		0x00000100
+#define	NFSV4OPBM_SETXATTR		0x00000200
+#define	NFSV4OPBM_LISTXATTRS		0x00000400
+#define	NFSV4OPBM_REMOVEXATTR		0x00000800
+
+/*
+ * The set of must and allow operations for SP4_MACH_CRED.  These are
+ * the operations requested by the Linux NFSv4.1/4.2 client.
+ * The must list is also the same ones listed in the RFC.
+ */
+#define	NFSOPBIT_MUST0	NFSV4OP_DELEGPURGE
+
+#define	NFSOPBIT_MUST1							\
+	(NFSV4OPBM_BINDCONNTOSESS |					\
+	NFSV4OPBM_EXCHANGEID |						\
+	NFSV4OPBM_CREATESESSION |					\
+	NFSV4OPBM_DESTROYSESSION |					\
+	NFSV4OPBM_DESTROYCLIENTID)
+
+#define	NFSOPBIT_MUST2		0x0
+
+#define	NFSOPBIT_CLRNOTMUST(b) do {					\
+	(b)->bits[0] &= NFSOPBIT_MUST0;					\
+	(b)->bits[1] &= NFSOPBIT_MUST1;					\
+	(b)->bits[2] &= NFSOPBIT_MUST2;					\
+    } while (0)
+
+#define	NFSOPBIT_ALLOWED0						\
+	(NFSV4OPBM_CLOSE |						\
+	NFSV4OPBM_COMMIT |						\
+	NFSV4OPBM_DELEGRETURN |						\
+	NFSV4OPBM_LOCKU |						\
+	NFSV4OPBM_OPENDOWNGRADE)
+
+#define	NFSOPBIT_ALLOWED1						\
+	(NFSV4OPBM_SECINFO |						\
+	NFSV4OPBM_WRITE |						\
+	NFSV4OPBM_FREESTATEID |						\
+	NFSV4OPBM_LAYOUTRETURN |					\
+	NFSV4OPBM_SECINFONONAME |					\
+	NFSV4OPBM_TESTSTATEID)
+
+#define	NFSOPBIT_ALLOWED2	0x0
+
+#define	NFSOPBIT_CLRNOTALLOWED(b) do {					\
+	(b)->bits[0] &= NFSOPBIT_ALLOWED0;				\
+	(b)->bits[1] &= NFSOPBIT_ALLOWED1;				\
+	(b)->bits[2] &= NFSOPBIT_ALLOWED2;				\
+    } while (0)
+
 /*
  * Structure for data handled by the statfs rpc. Since some fields are
  * u_int64_t, this cannot be used for copying data on/off the wire, due



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202304012125.331LP3OO094168>