aboutsummaryrefslogtreecommitdiff
path: root/sys/fs/nfs/nfs_commonsubs.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs/nfs/nfs_commonsubs.c')
-rw-r--r--sys/fs/nfs/nfs_commonsubs.c337
1 files changed, 247 insertions, 90 deletions
diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c
index 3c9af40253ad..a957315aaa12 100644
--- a/sys/fs/nfs/nfs_commonsubs.c
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -135,7 +135,7 @@ struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS] = {
{ 1, 2, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Lookupp */
{ 0, 1, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* NVerify */
{ 1, 1, 0, 1, LK_EXCLUSIVE, 1, 0 }, /* Open */
- { 1, 1, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* OpenAttr */
+ { 1, 1, 1, 1, LK_EXCLUSIVE, 1, 1 }, /* OpenAttr */
{ 0, 1, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* OpenConfirm */
{ 0, 1, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* OpenDowngrade */
{ 1, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* PutFH */
@@ -219,18 +219,19 @@ NFSD_VNET_DEFINE_STATIC(u_char *, nfsrv_dnsname) = NULL;
static int nfs_bigreply[NFSV42_NPROCS] = { 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 0, 0, 1, 0, 0, 0, 0, 0 };
+ 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 };
/* local functions */
static int nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep);
static void nfsv4_wanted(struct nfsv4lock *lp);
static uint32_t nfsv4_filesavail(struct statfs *, struct mount *);
-static int nfsrv_cmpmixedcase(u_char *cp, u_char *cp2, int len);
static int nfsrv_getuser(int procnum, uid_t uid, gid_t gid, char *name);
static void nfsrv_removeuser(struct nfsusrgrp *usrp, int isuser);
static int nfsrv_getrefstr(struct nfsrv_descript *, u_char **, u_char **,
int *, int *);
static void nfsrv_refstrbigenough(int, u_char **, u_char **, int *);
+static uint32_t vtonfsv4_type(struct vattr *);
+static __enum_uint8(vtype) nfsv4tov_type(uint32_t, uint16_t *);
static struct {
int op;
@@ -250,10 +251,10 @@ static struct {
{ NFSV4OP_CREATE, 5, "Create", 6, },
{ NFSV4OP_CREATE, 1, "Create", 6, },
{ NFSV4OP_CREATE, 3, "Create", 6, },
+ { NFSV4OP_REMOVE, 3, "Remove", 6, },
{ NFSV4OP_REMOVE, 1, "Remove", 6, },
- { NFSV4OP_REMOVE, 1, "Remove", 6, },
- { NFSV4OP_SAVEFH, 5, "Rename", 6, },
- { NFSV4OP_SAVEFH, 4, "Link", 4, },
+ { NFSV4OP_SAVEFH, 7, "Rename", 6, },
+ { NFSV4OP_SAVEFH, 6, "Link", 4, },
{ NFSV4OP_READDIR, 2, "Readdir", 7, },
{ NFSV4OP_READDIR, 2, "Readdir", 7, },
{ NFSV4OP_GETATTR, 1, "Getattr", 7, },
@@ -308,6 +309,7 @@ static struct {
{ NFSV4OP_DEALLOCATE, 2, "Deallocate", 10, },
{ NFSV4OP_LAYOUTERROR, 1, "LayoutError", 11, },
{ NFSV4OP_VERIFY, 3, "AppendWrite", 11, },
+ { NFSV4OP_OPENATTR, 3, "OpenAttr", 8, },
};
/*
@@ -317,7 +319,7 @@ static int nfs_bigrequest[NFSV42_NPROCS] = {
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
- 0, 1
+ 0, 1, 0
};
/*
@@ -610,32 +612,43 @@ nfscl_fillsattr(struct nfsrv_descript *nd, struct vattr *vap,
break;
case ND_NFSV4:
NFSZERO_ATTRBIT(&attrbits);
- if (vap->va_mode != (mode_t)VNOVAL)
- NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_MODE);
+ np = NULL;
+ if (strcmp(vp->v_mount->mnt_vfc->vfc_name, "nfs") == 0)
+ np = VTONFS(vp);
+ if (vap->va_mode != (mode_t)VNOVAL) {
+ if ((flags & NFSSATTR_NEWFILE) != 0 && np != NULL &&
+ NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr,
+ NFSATTRBIT_MODEUMASK))
+ NFSSETBIT_ATTRBIT(&attrbits,
+ NFSATTRBIT_MODEUMASK);
+ else
+ NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_MODE);
+ }
if ((flags & NFSSATTR_FULL) && vap->va_uid != (uid_t)VNOVAL)
NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNER);
if ((flags & NFSSATTR_FULL) && vap->va_gid != (gid_t)VNOVAL)
NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNERGROUP);
if ((flags & NFSSATTR_FULL) && vap->va_size != VNOVAL)
NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SIZE);
+ if ((flags & NFSSATTR_FULL) && vap->va_flags != VNOVAL) {
+ NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_HIDDEN);
+ NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SYSTEM);
+ }
if (vap->va_atime.tv_sec != VNOVAL)
NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESSSET);
if (vap->va_mtime.tv_sec != VNOVAL)
NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFYSET);
- if (vap->va_birthtime.tv_sec != VNOVAL &&
- strcmp(vp->v_mount->mnt_vfc->vfc_name, "nfs") == 0) {
- /*
- * We can only test for support of TimeCreate if
- * the "vp" argument is for an NFS vnode.
- */
- np = VTONFS(vp);
- if (NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr,
- NFSATTRBIT_TIMECREATE))
- NFSSETBIT_ATTRBIT(&attrbits,
- NFSATTRBIT_TIMECREATE);
- }
+ /*
+ * We can only test for support of TimeCreate if
+ * the "vp" argument is for an NFS vnode.
+ */
+ if (vap->va_birthtime.tv_sec != VNOVAL && np != NULL &&
+ NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr,
+ NFSATTRBIT_TIMECREATE))
+ NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMECREATE);
(void) nfsv4_fillattr(nd, vp->v_mount, vp, NULL, vap, NULL, 0,
- &attrbits, NULL, NULL, 0, 0, 0, 0, (uint64_t)0, NULL);
+ &attrbits, NULL, NULL, 0, 0, 0, 0, (uint64_t)0, NULL,
+ false, false, false);
break;
}
}
@@ -980,6 +993,17 @@ nfsm_fhtom(struct nfsmount *nmp, struct nfsrv_descript *nd, u_int8_t *fhp,
(nmp->nm_privflag & NFSMNTP_FAKEROOTFH) != 0) {
fhp = nmp->nm_fh;
size = nmp->nm_fhsize;
+ } else if (size >= NFSX_FHMAX + NFSX_V4NAMEDDIRFH &&
+ size <= NFSX_FHMAX + NFSX_V4NAMEDATTRFH) {
+ size -= (NFSX_FHMAX - NFSX_MYFH);
+ NFSM_BUILD(tl, uint32_t *, NFSX_MYFH +
+ 2 * NFSX_UNSIGNED);
+ *tl++ = txdr_unsigned(size);
+ NFSBCOPY(fhp, tl, NFSX_MYFH);
+ tl += (NFSX_MYFH / NFSX_UNSIGNED);
+ *tl = 0;
+ bytesize = NFSX_MYFH + 2 * NFSX_UNSIGNED;
+ break;
}
fullsiz = NFSM_RNDUP(size);
if (set_true) {
@@ -1277,7 +1301,8 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
struct nfsvattr *nap, struct nfsfh **nfhpp, fhandle_t *fhp, int fhsize,
struct nfsv3_pathconf *pc, struct statfs *sbp, struct nfsstatfs *sfp,
struct nfsfsinfo *fsp, NFSACL_T *aclp, int compare, int *retcmpp,
- u_int32_t *leasep, u_int32_t *rderrp, NFSPROC_T *p, struct ucred *cred)
+ u_int32_t *leasep, u_int32_t *rderrp, bool *has_namedattrp,
+ NFSPROC_T *p, struct ucred *cred)
{
u_int32_t *tl;
int i = 0, j, k, l = 0, m, bitpos, attrsum = 0;
@@ -1293,6 +1318,8 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
gid_t gid;
u_int32_t freenum = 0, tuint;
u_int64_t uquad = 0, thyp, thyp2;
+ uint16_t tui16;
+ long has_pathconf;
#ifdef QUOTA
struct dqblk dqb;
uid_t savuid;
@@ -1316,6 +1343,7 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
* Just set default values to some of the important ones.
*/
if (nap != NULL) {
+ VATTR_NULL(&nap->na_vattr);
nap->na_type = VREG;
nap->na_mode = 0;
nap->na_rdev = (NFSDEV_T)0;
@@ -1365,6 +1393,8 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
sfp->sf_tbytes = UINT64_MAX;
sfp->sf_abytes = UINT64_MAX;
}
+ if (has_namedattrp != NULL)
+ *has_namedattrp = false;
}
/*
@@ -1397,6 +1427,16 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
NFSCLRBIT_ATTRBIT(&checkattrbits, NFSATTRBIT_ACL);
NFSCLRBIT_ATTRBIT(&checkattrbits, NFSATTRBIT_ACLSUPPORT);
}
+ /* Some filesystems do not support uf_hidden */
+ if (vp == NULL || VOP_PATHCONF(vp,
+ _PC_HAS_HIDDENSYSTEM, &has_pathconf) != 0)
+ has_pathconf = 0;
+ if (has_pathconf == 0) {
+ NFSCLRBIT_ATTRBIT(&checkattrbits,
+ NFSATTRBIT_HIDDEN);
+ NFSCLRBIT_ATTRBIT(&checkattrbits,
+ NFSATTRBIT_SYSTEM);
+ }
if (!NFSEQUAL_ATTRBIT(&retattrbits, &checkattrbits)
|| retnotsup)
*retcmpp = NFSERR_NOTSAME;
@@ -1407,11 +1447,16 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
if (compare) {
if (!(*retcmpp)) {
- if (nap->na_type != nfsv34tov_type(*tl))
+ tui16 = 0;
+ if (nap->na_type != nfsv4tov_type(*tl,
+ &tui16) ||
+ ((nap->na_bsdflags & SFBSD_NAMEDATTR) ^
+ tui16) != 0)
*retcmpp = NFSERR_NOTSAME;
}
} else if (nap != NULL) {
- nap->na_type = nfsv34tov_type(*tl);
+ nap->na_type = nfsv4tov_type(*tl,
+ &nap->na_bsdflags);
}
attrsum += NFSX_UNSIGNED;
break;
@@ -1490,9 +1535,23 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
break;
case NFSATTRBIT_NAMEDATTR:
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
- if (compare && !(*retcmpp)) {
- if (*tl != newnfs_false)
- *retcmpp = NFSERR_NOTSAME;
+ if (compare) {
+ if (!(*retcmpp)) {
+ if (vp == NULL || VOP_PATHCONF(vp,
+ _PC_HAS_NAMEDATTR, &has_pathconf)
+ != 0)
+ has_pathconf = 0;
+ if ((has_pathconf != 0 &&
+ *tl != newnfs_true) ||
+ (has_pathconf == 0 &&
+ *tl != newnfs_false))
+ *retcmpp = NFSERR_NOTSAME;
+ }
+ } else if (has_namedattrp != NULL) {
+ if (*tl == newnfs_true)
+ *has_namedattrp = true;
+ else
+ *has_namedattrp = false;
}
attrsum += NFSX_UNSIGNED;
break;
@@ -1666,6 +1725,8 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
goto nfsmout;
tfhsize = tnfhp->nfh_len;
if (compare) {
+ if (tfhsize > NFSX_MYFH)
+ tfhsize = NFSX_MYFH;
if (!(*retcmpp) &&
!NFSRV_CMPFH(tnfhp->nfh_fh, tfhsize,
fhp, fhsize))
@@ -1745,9 +1806,17 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
free(cp2, M_NFSSTRING);
break;
case NFSATTRBIT_HIDDEN:
- NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
- if (compare && !(*retcmpp))
- *retcmpp = NFSERR_ATTRNOTSUPP;
+ NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+ if (compare) {
+ if (!(*retcmpp) && ((*tl == newnfs_true &&
+ (nap->na_flags & UF_HIDDEN) == 0) ||
+ (*tl == newnfs_false &&
+ (nap->na_flags & UF_HIDDEN) != 0)))
+ *retcmpp = NFSERR_NOTSAME;
+ } else if (nap != NULL) {
+ if (*tl == newnfs_true)
+ nap->na_flags |= UF_HIDDEN;
+ }
attrsum += NFSX_UNSIGNED;
break;
case NFSATTRBIT_HOMOGENEOUS:
@@ -2119,9 +2188,17 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
attrsum += NFSX_HYPER;
break;
case NFSATTRBIT_SYSTEM:
- NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
- if (compare && !(*retcmpp))
- *retcmpp = NFSERR_ATTRNOTSUPP;
+ NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+ if (compare) {
+ if (!(*retcmpp) && ((*tl == newnfs_true &&
+ (nap->na_flags & UF_SYSTEM) == 0) ||
+ (*tl == newnfs_false &&
+ (nap->na_flags & UF_SYSTEM) != 0)))
+ *retcmpp = NFSERR_NOTSAME;
+ } else if (nap != NULL) {
+ if (*tl == newnfs_true)
+ nap->na_flags |= UF_SYSTEM;
+ }
attrsum += NFSX_UNSIGNED;
break;
case NFSATTRBIT_TIMEACCESS:
@@ -2297,6 +2374,23 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
if (compare && !(*retcmpp) && i != nfs_srvmaxio)
*retcmpp = NFSERR_NOTSAME;
break;
+ case NFSATTRBIT_CHANGEATTRTYPE:
+ NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+ if (compare) {
+ if (!(*retcmpp)) {
+ tuint = NFSV4CHANGETYPE_UNDEFINED;
+ if ((vp->v_mount->mnt_vfc->vfc_flags &
+ VFCF_FILEREVINC) != 0)
+ tuint = NFSV4CHANGETYPE_VERS_COUNTER_NOPNFS;
+ else if ((vp->v_mount->mnt_vfc->vfc_flags &
+ VFCF_FILEREVCT) != 0)
+ tuint = NFSV4CHANGETYPE_TIME_METADATA;
+ if (fxdr_unsigned(uint32_t, *tl) != tuint)
+ *retcmpp = NFSERR_NOTSAME;
+ }
+ }
+ attrsum += NFSX_UNSIGNED;
+ break;
default:
printf("EEK! nfsv4_loadattr unknown attr=%d\n",
bitpos);
@@ -2553,7 +2647,8 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
NFSACL_T *saclp, struct vattr *vap, fhandle_t *fhp, int rderror,
nfsattrbit_t *attrbitp, struct ucred *cred, NFSPROC_T *p, int isdgram,
int reterr, int supports_nfsv4acls, int at_root, uint64_t mounted_on_fileno,
- struct statfs *pnfssf)
+ struct statfs *pnfssf, bool xattrsupp, bool has_hiddensystem,
+ bool has_namedattr)
{
int bitpos, retnum = 0;
u_int32_t *tl;
@@ -2567,8 +2662,7 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
struct nfsfsinfo fsinf;
struct timespec temptime;
NFSACL_T *aclp, *naclp = NULL;
- size_t atsiz;
- bool xattrsupp;
+ short irflag;
#ifdef QUOTA
struct dqblk dqb;
uid_t savuid;
@@ -2652,18 +2746,6 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
}
}
- /* Check to see if Extended Attributes are supported. */
- xattrsupp = false;
- if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_XATTRSUPPORT)) {
- if (NFSVOPLOCK(vp, LK_SHARED) == 0) {
- error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER,
- "xxx", NULL, &atsiz, cred, p);
- NFSVOPUNLOCK(vp);
- if (error != EOPNOTSUPP)
- xattrsupp = true;
- }
- }
-
/*
* Put out the attribute bitmap for the ones being filled in
* and get the field for the number of attributes returned.
@@ -2685,11 +2767,15 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
NFSCLRBIT_ATTRBIT(&attrbits,NFSATTRBIT_ACLSUPPORT);
NFSCLRBIT_ATTRBIT(&attrbits,NFSATTRBIT_ACL);
}
+ if (!has_hiddensystem) {
+ NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_HIDDEN);
+ NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_SYSTEM);
+ }
retnum += nfsrv_putattrbit(nd, &attrbits);
break;
case NFSATTRBIT_TYPE:
NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = vtonfsv34_type(vap->va_type);
+ *tl = vtonfsv4_type(vap);
retnum += NFSX_UNSIGNED;
break;
case NFSATTRBIT_FHEXPIRETYPE:
@@ -2725,7 +2811,10 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
break;
case NFSATTRBIT_NAMEDATTR:
NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = newnfs_false;
+ if (has_namedattr)
+ *tl = newnfs_true;
+ else
+ *tl = newnfs_false;
retnum += NFSX_UNSIGNED;
break;
case NFSATTRBIT_FSID:
@@ -2786,7 +2875,15 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
retnum += NFSX_UNSIGNED;
break;
case NFSATTRBIT_FILEHANDLE:
- retnum += nfsm_fhtom(NULL, nd, (u_int8_t *)fhp, 0, 0);
+ siz = 0;
+ if (vp != NULL) {
+ irflag = vn_irflag_read(vp);
+ if ((irflag & VIRF_NAMEDDIR) != 0)
+ siz = NFSX_FHMAX + 2;
+ else if ((irflag & VIRF_NAMEDATTR) != 0)
+ siz = NFSX_FHMAX + 3;
+ }
+ retnum += nfsm_fhtom(NULL, nd, (u_int8_t *)fhp, siz, 0);
break;
case NFSATTRBIT_FILEID:
NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
@@ -2819,6 +2916,14 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
*tl = 0;
retnum += 2 * NFSX_UNSIGNED;
break;
+ case NFSATTRBIT_HIDDEN:
+ NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
+ if ((vap->va_flags & UF_HIDDEN) != 0)
+ *tl = newnfs_true;
+ else
+ *tl = newnfs_false;
+ retnum += NFSX_UNSIGNED;
+ break;
case NFSATTRBIT_HOMOGENEOUS:
NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
if (fsinf.fs_properties & NFSV3FSINFO_HOMOGENEOUS)
@@ -3008,6 +3113,14 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
txdr_hyper(vap->va_bytes, tl);
retnum += NFSX_HYPER;
break;
+ case NFSATTRBIT_SYSTEM:
+ NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
+ if ((vap->va_flags & UF_SYSTEM) != 0)
+ *tl = newnfs_true;
+ else
+ *tl = newnfs_false;
+ retnum += NFSX_UNSIGNED;
+ break;
case NFSATTRBIT_TIMEACCESS:
NFSM_BUILD(tl, u_int32_t *, NFSX_V4TIME);
txdr_nfsv4time(&vap->va_atime, tl);
@@ -3109,6 +3222,33 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
*tl = newnfs_false;
retnum += NFSX_UNSIGNED;
break;
+ case NFSATTRBIT_MODEUMASK:
+ NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
+ /*
+ * Since FreeBSD applies the umask above the VFS/VOP,
+ * there is no umask to handle here. If FreeBSD
+ * moves handling of umask to below the VFS/VOP,
+ * this could change.
+ */
+ *tl++ = vtonfsv34_mode(vap->va_mode);
+ *tl = 0;
+ retnum += 2 * NFSX_UNSIGNED;
+ break;
+ case NFSATTRBIT_CHANGEATTRTYPE:
+ NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
+ *tl = txdr_unsigned(NFSV4CHANGETYPE_UNDEFINED);
+ if (mp != NULL) {
+ if ((mp->mnt_vfc->vfc_flags &
+ VFCF_FILEREVINC) != 0)
+ *tl = txdr_unsigned(
+ NFSV4CHANGETYPE_VERS_COUNTER_NOPNFS);
+ else if ((mp->mnt_vfc->vfc_flags &
+ VFCF_FILEREVCT) != 0)
+ *tl = txdr_unsigned(
+ NFSV4CHANGETYPE_TIME_METADATA);
+ }
+ retnum += NFSX_UNSIGNED;
+ break;
default:
printf("EEK! Bad V4 attribute bitpos=%d\n", bitpos);
}
@@ -3419,13 +3559,13 @@ tryagain:
/*
* If an '@' is found and the domain name matches, search for
* the name with dns stripped off.
- * Mixed case alpahbetics will match for the domain name, but
- * all upper case will not.
+ * The match for alphabetics in now case insensitive,
+ * since RFC8881 defines this string as a DNS domain name.
*/
if (cnt == 0 && i < len && i > 0 &&
(len - 1 - i) == NFSD_VNET(nfsrv_dnsnamelen) &&
- !nfsrv_cmpmixedcase(cp,
- NFSD_VNET(nfsrv_dnsname), NFSD_VNET(nfsrv_dnsnamelen))) {
+ strncasecmp(cp, NFSD_VNET(nfsrv_dnsname),
+ NFSD_VNET(nfsrv_dnsnamelen)) == 0) {
len -= (NFSD_VNET(nfsrv_dnsnamelen) + 1);
*(cp - 1) = '\0';
}
@@ -3646,8 +3786,8 @@ tryagain:
*/
if (cnt == 0 && i < len && i > 0 &&
(len - 1 - i) == NFSD_VNET(nfsrv_dnsnamelen) &&
- !nfsrv_cmpmixedcase(cp,
- NFSD_VNET(nfsrv_dnsname), NFSD_VNET(nfsrv_dnsnamelen))) {
+ strncasecmp(cp, NFSD_VNET(nfsrv_dnsname),
+ NFSD_VNET(nfsrv_dnsnamelen)) == 0) {
len -= (NFSD_VNET(nfsrv_dnsnamelen) + 1);
*(cp - 1) = '\0';
}
@@ -3696,35 +3836,6 @@ out:
}
/*
- * Cmp len chars, allowing mixed case in the first argument to match lower
- * case in the second, but not if the first argument is all upper case.
- * Return 0 for a match, 1 otherwise.
- */
-static int
-nfsrv_cmpmixedcase(u_char *cp, u_char *cp2, int len)
-{
- int i;
- u_char tmp;
- int fndlower = 0;
-
- for (i = 0; i < len; i++) {
- if (*cp >= 'A' && *cp <= 'Z') {
- tmp = *cp++ + ('a' - 'A');
- } else {
- tmp = *cp++;
- if (tmp >= 'a' && tmp <= 'z')
- fndlower = 1;
- }
- if (tmp != *cp2++)
- return (1);
- }
- if (fndlower)
- return (0);
- else
- return (1);
-}
-
-/*
* Set the port for the nfsuserd.
*/
int
@@ -4032,8 +4143,9 @@ nfssvc_idname(struct nfsd_idargs *nidp)
*/
cr = crget();
cr->cr_uid = cr->cr_ruid = cr->cr_svuid = nidp->nid_uid;
- crsetgroups(cr, nidp->nid_ngroup, grps);
- cr->cr_rgid = cr->cr_svgid = cr->cr_groups[0];
+ crsetgroups_fallback(cr, nidp->nid_ngroup, grps,
+ GID_NOGROUP);
+ cr->cr_rgid = cr->cr_svgid = cr->cr_gid;
cr->cr_prison = curthread->td_ucred->cr_prison;
prison_hold(cr->cr_prison);
#ifdef MAC
@@ -4644,7 +4756,7 @@ newnfs_sndlock(int *flagp)
ts.tv_sec = 0;
ts.tv_nsec = 0;
(void) nfsmsleep((caddr_t)flagp, NFSSOCKMUTEXPTR,
- PZERO - 1, "nfsndlck", &ts);
+ PVFS, "nfsndlck", &ts);
}
*flagp |= NFSR_SNDLOCK;
NFSUNLOCKSOCK();
@@ -5025,6 +5137,8 @@ nfsv4_freeslot(struct nfsclsession *sep, int slot, bool resetseq)
mtx_lock(&sep->nfsess_mtx);
if (resetseq)
sep->nfsess_slotseq[slot]--;
+ else if (slot > sep->nfsess_foreslots)
+ sep->nfsess_slotseq[slot] = 0;
if ((bitval & sep->nfsess_slots) == 0)
printf("freeing free slot!!\n");
sep->nfsess_slots &= ~bitval;
@@ -5154,3 +5268,46 @@ nfsrpc_destroysession(struct nfsmount *nmp, struct nfsclsession *tsep,
m_freem(nd->nd_mrep);
return (error);
}
+
+/*
+ * Translate a vnode type into an NFSv4 type, including the named
+ * attribute types.
+ */
+static uint32_t
+vtonfsv4_type(struct vattr *vap)
+{
+ nfstype ntyp;
+
+ if (vap->va_type >= 9)
+ ntyp = NFNON;
+ else
+ ntyp = nfsv34_type[vap->va_type];
+ if ((vap->va_bsdflags & SFBSD_NAMEDATTR) != 0) {
+ if (ntyp == NFDIR)
+ ntyp = NFATTRDIR;
+ else if (ntyp == NFREG)
+ ntyp = NFNAMEDATTR;
+ }
+ return (txdr_unsigned((uint32_t)ntyp));
+}
+
+/*
+ * Translate an NFS type to a vnode type.
+ */
+static __enum_uint8(vtype)
+nfsv4tov_type(uint32_t ntyp, uint16_t *bsdflags)
+{
+ __enum_uint8(vtype) vtyp;
+
+ ntyp = fxdr_unsigned(uint32_t, ntyp) % (NFNAMEDATTR + 1);
+ if (ntyp == NFATTRDIR) {
+ vtyp = VDIR;
+ *bsdflags |= SFBSD_NAMEDATTR;
+ } else if (ntyp == NFNAMEDATTR) {
+ vtyp = VREG;
+ *bsdflags |= SFBSD_NAMEDATTR;
+ } else {
+ vtyp = nv34tov_type[ntyp];
+ }
+ return (vtyp);
+}