The branch main has been updated by rmacklem:

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

commit f4179ad46fa4ff717557e5485072c004e6054416
Author:     Rick Macklem <[email protected]>
AuthorDate: 2023-04-01 21:22:26 +0000
Commit:     Rick Macklem <[email protected]>
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

Reply via email to