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
This commit is contained in:
Rick Macklem 2023-04-01 14:22:26 -07:00
parent d9af4219d6
commit f4179ad46f
4 changed files with 215 additions and 0 deletions

View File

@ -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.

View File

@ -1222,6 +1222,47 @@ nfsrv_getattrbits(struct nfsrv_descript *nd, nfsattrbit_t *attrbitp, int *cntp,
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.

View File

@ -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 *,

View File

@ -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