git: f4179ad46fa4 - main - nfscommon: Add support for an NFSv4 operation bitmap
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 01 Apr 2023 21:25:03 UTC
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