Date: Sat, 7 Sep 2019 04:09:43 +0000 (UTC) From: Rick Macklem <rmacklem@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r351968 - in projects/nfsv42/sys/fs: nfs nfsclient nfsserver Message-ID: <201909070409.x8749h4O074603@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: rmacklem Date: Sat Sep 7 04:09:43 2019 New Revision: 351968 URL: https://svnweb.freebsd.org/changeset/base/351968 Log: Add support for the List Extended Attributes RPC. This patch also saves the maxrequest and maxreply for the session in nd_maxreq and nd_maxresp so they can be used to limit the size of extended attribute requests/replies. The code for doing this on the client side still needs to be done. Modified: projects/nfsv42/sys/fs/nfs/nfs.h projects/nfsv42/sys/fs/nfs/nfs_commonsubs.c projects/nfsv42/sys/fs/nfs/nfs_var.h projects/nfsv42/sys/fs/nfs/nfsport.h projects/nfsv42/sys/fs/nfs/nfsproto.h projects/nfsv42/sys/fs/nfsclient/nfs_clrpcops.c projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c projects/nfsv42/sys/fs/nfsserver/nfs_nfsdport.c projects/nfsv42/sys/fs/nfsserver/nfs_nfsdserv.c projects/nfsv42/sys/fs/nfsserver/nfs_nfsdsocket.c projects/nfsv42/sys/fs/nfsserver/nfs_nfsdstate.c Modified: projects/nfsv42/sys/fs/nfs/nfs.h ============================================================================== --- projects/nfsv42/sys/fs/nfs/nfs.h Sat Sep 7 03:51:26 2019 (r351967) +++ projects/nfsv42/sys/fs/nfs/nfs.h Sat Sep 7 04:09:43 2019 (r351968) @@ -667,6 +667,8 @@ struct nfsrv_descript { uint32_t *nd_sequence; /* Sequence Op. ptr */ nfsv4stateid_t nd_curstateid; /* Current StateID */ nfsv4stateid_t nd_savedcurstateid; /* Saved Current StateID */ + uint32_t nd_maxreq; /* Max. request (session). */ + uint32_t nd_maxresp; /* Max. reply (session). */ }; #define nd_princlen nd_gssnamelen Modified: projects/nfsv42/sys/fs/nfs/nfs_commonsubs.c ============================================================================== --- projects/nfsv42/sys/fs/nfs/nfs_commonsubs.c Sat Sep 7 03:51:26 2019 (r351967) +++ projects/nfsv42/sys/fs/nfs/nfs_commonsubs.c Sat Sep 7 04:09:43 2019 (r351968) @@ -182,7 +182,7 @@ struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS] = { { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Clone */ { 0, 1, 0, 0, LK_SHARED, 1, 1 }, /* Getxattr */ { 0, 1, 1, 1, LK_EXCLUSIVE, 1, 1 }, /* Setxattr */ - { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Listxattrs */ + { 0, 1, 0, 0, LK_SHARED, 1, 1 }, /* Listxattrs */ { 0, 1, 1, 1, LK_EXCLUSIVE, 1, 1 }, /* Removexattr */ }; #endif /* !APPLEKEXT */ @@ -211,7 +211,7 @@ static struct nfsrv_lughash *nfsgroupnamehash; 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, 1 }; /* local functions */ static int nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep); @@ -293,6 +293,7 @@ static struct { { NFSV4OP_GETXATTR, 2, "Getxattr", 8, }, { NFSV4OP_SETXATTR, 2, "Setxattr", 8, }, { NFSV4OP_REMOVEXATTR, 2, "Rmxattr", 7, }, + { NFSV4OP_LISTXATTRS, 2, "Listxattr", 9, }, }; /* @@ -301,7 +302,7 @@ static struct { 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, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }; /* @@ -4632,6 +4633,8 @@ nfsv4_setsequence(struct nfsmount *nmp, struct nfsrv_d error = nfsv4_sequencelookup(nmp, sep, &slotpos, &maxslot, &slotseq, sessionid); + nd->nd_maxreq = sep->sess_maxreq; + nd->nd_maxresp = sep->sess_maxresp; /* Build the Sequence arguments. */ NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 4 * NFSX_UNSIGNED); Modified: projects/nfsv42/sys/fs/nfs/nfs_var.h ============================================================================== --- projects/nfsv42/sys/fs/nfs/nfs_var.h Sat Sep 7 03:51:26 2019 (r351967) +++ projects/nfsv42/sys/fs/nfs/nfs_var.h Sat Sep 7 04:09:43 2019 (r351968) @@ -290,6 +290,8 @@ int nfsrvd_setxattr(struct nfsrv_descript *, int, vnode_t, struct nfsexstuff *); int nfsrvd_rmxattr(struct nfsrv_descript *, int, vnode_t, struct nfsexstuff *); +int nfsrvd_listxattr(struct nfsrv_descript *, int, + vnode_t, struct nfsexstuff *); int nfsrvd_notsupp(struct nfsrv_descript *, int, vnode_t, struct nfsexstuff *); @@ -555,6 +557,8 @@ int nfsrpc_getextattr(vnode_t, const char *, struct ui struct nfsvattr *, int *, struct ucred *, NFSPROC_T *); int nfsrpc_setextattr(vnode_t, const char *, struct uio *, struct nfsvattr *, int *, struct ucred *, NFSPROC_T *); +int nfsrpc_listextattr(vnode_t, uint64_t *, struct uio *, size_t *, bool *, + struct nfsvattr *, int *, struct ucred *, NFSPROC_T *); int nfsrpc_rmextattr(vnode_t, const char *, struct nfsvattr *, int *, struct ucred *, NFSPROC_T *); @@ -740,12 +744,14 @@ void nfsrv_killrpcs(struct nfsmount *); int nfsrv_setacl(struct vnode *, NFSACL_T *, struct ucred *, NFSPROC_T *); int nfsvno_seek(struct nfsrv_descript *, struct vnode *, u_long, off_t *, int, bool *, struct ucred *, NFSPROC_T *); -int nfsvno_getxattr(struct vnode *, char *, struct ucred *, struct thread *, - struct mbuf **, struct mbuf **, int *); +int nfsvno_getxattr(struct vnode *, char *, uint32_t, struct ucred *, + struct thread *, struct mbuf **, struct mbuf **, int *); int nfsvno_setxattr(struct vnode *, char *, int, struct mbuf *, char *, struct ucred *, struct thread *); int nfsvno_rmxattr(struct nfsrv_descript *, struct vnode *, char *, struct ucred *, struct thread *); +int nfsvno_listxattr(struct vnode *, uint64_t, struct ucred *, struct thread *, + u_char **, uint32_t *, bool *); /* nfs_commonkrpc.c */ int newnfs_nmcancelreqs(struct nfsmount *); Modified: projects/nfsv42/sys/fs/nfs/nfsport.h ============================================================================== --- projects/nfsv42/sys/fs/nfs/nfsport.h Sat Sep 7 03:51:26 2019 (r351967) +++ projects/nfsv42/sys/fs/nfs/nfsport.h Sat Sep 7 04:09:43 2019 (r351968) @@ -410,11 +410,12 @@ #define NFSPROC_GETEXTATTR 61 #define NFSPROC_SETEXTATTR 62 #define NFSPROC_RMEXTATTR 63 +#define NFSPROC_LISTEXTATTR 64 /* * Must be defined as one higher than the last NFSv4.2 Proc# above. */ -#define NFSV42_NPROCS 64 +#define NFSV42_NPROCS 65 #endif /* NFS_V3NPROCS */ @@ -443,7 +444,7 @@ struct nfsstatsv1 { uint64_t readlink_bios; uint64_t biocache_readdirs; uint64_t readdir_bios; - uint64_t rpccnt[NFSV42_NPROCS + 5]; + uint64_t rpccnt[NFSV42_NPROCS + 4]; uint64_t rpcretries; uint64_t srvrpccnt[NFSV42_NOPS + NFSV4OP_FAKENOPS]; uint64_t srvrpc_errs; Modified: projects/nfsv42/sys/fs/nfs/nfsproto.h ============================================================================== --- projects/nfsv42/sys/fs/nfs/nfsproto.h Sat Sep 7 03:51:26 2019 (r351967) +++ projects/nfsv42/sys/fs/nfs/nfsproto.h Sat Sep 7 04:09:43 2019 (r351968) @@ -392,11 +392,12 @@ #define NFSPROC_GETEXTATTR 61 #define NFSPROC_SETEXTATTR 62 #define NFSPROC_RMEXTATTR 63 +#define NFSPROC_LISTEXTATTR 64 /* * Must be defined as one higher than the last NFSv4.2 Proc# above. */ -#define NFSV42_NPROCS 64 +#define NFSV42_NPROCS 65 #endif /* NFS_V3NPROCS */ Modified: projects/nfsv42/sys/fs/nfsclient/nfs_clrpcops.c ============================================================================== --- projects/nfsv42/sys/fs/nfsclient/nfs_clrpcops.c Sat Sep 7 03:51:26 2019 (r351967) +++ projects/nfsv42/sys/fs/nfsclient/nfs_clrpcops.c Sat Sep 7 04:09:43 2019 (r351968) @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include <fs/nfs/nfsport.h> #include <fs/nfsclient/nfs.h> +#include <sys/extattr.h> #include <sys/sysctl.h> #include <sys/taskqueue.h> @@ -8381,6 +8382,83 @@ nfsrpc_rmextattr(vnode_t vp, const char *name, struct /* Just skip over the reply and Getattr op status. */ NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_HYPER + 2 * NFSX_UNSIGNED); + error = nfsm_loadattr(nd, nap); + if (error == 0) + *attrflagp = 1; + } + if (error == 0) + error = nd->nd_repstat; +nfsmout: + mbuf_freem(nd->nd_mrep); + return (error); +} + +/* + * The listextattr RPC. + */ +APPLESTATIC int +nfsrpc_listextattr(vnode_t vp, uint64_t *cookiep, struct uio *uiop, + size_t *lenp, bool *eofp, struct nfsvattr *nap, int *attrflagp, + struct ucred *cred, NFSPROC_T *p) +{ + uint32_t *tl; + int cnt, error, i, len; + struct nfsrv_descript nfsd; + struct nfsrv_descript *nd = &nfsd; + nfsattrbit_t attrbits; + u_char c; + + *attrflagp = 0; + NFSCL_REQSTART(nd, NFSPROC_LISTEXTATTR, vp); + NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + 2 * NFSX_UNSIGNED); + txdr_hyper(*cookiep, tl); tl += 2; + *tl++ = txdr_unsigned(*lenp); + *tl = txdr_unsigned(NFSV4OP_GETATTR); + NFSGETATTR_ATTRBIT(&attrbits); + nfsrv_putattrbit(nd, &attrbits); + error = nfscl_request(nd, vp, p, cred, NULL); + if (error != 0) + return (error); + *eofp = true; + *lenp = 0; + if (nd->nd_repstat == 0) { + NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + NFSX_UNSIGNED); + *cookiep = fxdr_hyper(tl); tl += 2; + cnt = fxdr_unsigned(int, *tl); + if (cnt <= 0) { + error = EBADRPC; + goto nfsmout; + } + for (i = 0; i < cnt; i++) { + NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); + len = fxdr_unsigned(int, *tl); + if (len <= 0 || len > EXTATTR_MAXNAMELEN) { + error = EBADRPC; + goto nfsmout; + } + if (uiop == NULL) + error = nfsm_advance(nd, NFSM_RNDUP(len), -1); + else if (uiop->uio_resid >= len + 1) { + c = len; + error = uiomove(&c, sizeof(c), uiop); + if (error == 0) + error = nfsm_mbufuio(nd, uiop, len); + } else { + error = nfsm_advance(nd, NFSM_RNDUP(len), -1); + *eofp = false; + } + if (error != 0) + goto nfsmout; + *lenp += (len + 1); + } + /* Get the eof and skip over the Getattr op status. */ + NFSM_DISSECT(tl, uint32_t *, 3 * NFSX_UNSIGNED); + /* + * *eofp is set false above, because it wasn't able to copy + * all of the reply. + */ + if (*eofp && *tl == 0) + *eofp = false; error = nfsm_loadattr(nd, nap); if (error == 0) *attrflagp = 1; Modified: projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c ============================================================================== --- projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c Sat Sep 7 03:51:26 2019 (r351967) +++ projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c Sat Sep 7 04:09:43 2019 (r351968) @@ -150,6 +150,7 @@ static vop_copy_file_range_t nfs_copy_file_range; static vop_ioctl_t nfs_ioctl; static vop_getextattr_t nfs_getextattr; static vop_setextattr_t nfs_setextattr; +static vop_listextattr_t nfs_listextattr; static vop_deleteextattr_t nfs_deleteextattr; /* @@ -194,6 +195,7 @@ static struct vop_vector newnfs_vnodeops_nosig = { .vop_ioctl = nfs_ioctl, .vop_getextattr = nfs_getextattr, .vop_setextattr = nfs_setextattr, + .vop_listextattr = nfs_listextattr, .vop_deleteextattr = nfs_deleteextattr, }; @@ -3847,6 +3849,80 @@ nfs_setextattr(struct vop_setextattr_args *ap) if (error == 0 && ret != 0) error = ret; } + + switch (error) { + case NFSERR_NOTSUPP: + case NFSERR_OPILLEGAL: + mtx_lock(&nmp->nm_mtx); + nmp->nm_privflag |= NFSMNTP_NOXATTR; + mtx_unlock(&nmp->nm_mtx); + error = EOPNOTSUPP; + break; + case NFSERR_NOXATTR: + case NFSERR_XATTR2BIG: + error = ENOATTR; + break; + default: + error = nfscl_maperr(td, error, 0, 0); + break; + } + return (error); +} + +/* + * nfs listextattr call + */ +static int +nfs_listextattr(struct vop_listextattr_args *ap) +{ + struct vnode *vp = ap->a_vp; + struct nfsmount *nmp; + struct ucred *cred; + struct thread *td = ap->a_td; + struct nfsvattr nfsva; + size_t len, len2; + uint64_t cookie; + int attrflag, error, ret; + bool eof; + + nmp = VFSTONFS(vp->v_mount); + mtx_lock(&nmp->nm_mtx); + if (!NFSHASNFSV4(nmp) || nmp->nm_minorvers < NFSV42_MINORVERSION || + (nmp->nm_privflag & NFSMNTP_NOXATTR) != 0 || + ap->a_attrnamespace != EXTATTR_NAMESPACE_USER) { + mtx_unlock(&nmp->nm_mtx); + return (EOPNOTSUPP); + } + mtx_unlock(&nmp->nm_mtx); + + cred = ap->a_cred; + if (cred == NULL) + cred = td->td_ucred; + + /* Loop around doing List Extended Attribute RPCs. */ + eof = false; + cookie = 0; + len2 = 0; + error = 0; + while (!eof && error == 0) { + len = nmp->nm_rsize; + attrflag = 0; + error = nfsrpc_listextattr(vp, &cookie, ap->a_uio, &len, &eof, + &nfsva, &attrflag, cred, td); + if (attrflag != 0) { + ret = nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, + 1); + if (error == 0 && ret != 0) + error = ret; + } + if (error == 0) { + len2 += len; + if (len2 > SSIZE_MAX) + error = ENOATTR; + } + } + if (error == 0 && ap->a_size != NULL) + *ap->a_size = len2; switch (error) { case NFSERR_NOTSUPP: Modified: projects/nfsv42/sys/fs/nfsserver/nfs_nfsdport.c ============================================================================== --- projects/nfsv42/sys/fs/nfsserver/nfs_nfsdport.c Sat Sep 7 03:51:26 2019 (r351967) +++ projects/nfsv42/sys/fs/nfsserver/nfs_nfsdport.c Sat Sep 7 04:09:43 2019 (r351968) @@ -5914,8 +5914,9 @@ nfsvno_seek(struct nfsrv_descript *nd, struct vnode *v * Get Extended Atribute vnode op into an mbuf list. */ int -nfsvno_getxattr(struct vnode *vp, char *name, struct ucred *cred, - struct thread *p, struct mbuf **mpp, struct mbuf **mpendp, int *lenp) +nfsvno_getxattr(struct vnode *vp, char *name, uint32_t maxresp, + struct ucred *cred, struct thread *p, struct mbuf **mpp, + struct mbuf **mpendp, int *lenp) { struct iovec *iv; struct uio io, *uiop = &io; @@ -5928,7 +5929,7 @@ nfsvno_getxattr(struct vnode *vp, char *name, struct u &siz, cred, p); if (error != 0) return (NFSERR_NOXATTR); - if (siz > 1000000) + if (siz > maxresp - NFS_MAXXDR) return (NFSERR_XATTR2BIG); len = siz; tlen = NFSM_RNDUP(len); @@ -6039,6 +6040,72 @@ nfsvno_rmxattr(struct nfsrv_descript *nd, struct vnode #ifdef MAC out: #endif + NFSEXITCODE(error); + return (error); +} + +/* + * List Extended Atribute vnode op into an mbuf list. + */ +int +nfsvno_listxattr(struct vnode *vp, uint64_t cookie, struct ucred *cred, + struct thread *p, u_char **bufp, uint32_t *lenp, bool *eofp) +{ + struct iovec iv; + struct uio io; + int error; + size_t siz; + + *bufp = NULL; + /* First, find out the size of the extended attribute. */ + error = VOP_LISTEXTATTR(vp, EXTATTR_NAMESPACE_USER, NULL, &siz, cred, + p); + if (error != 0) + return (NFSERR_NOXATTR); + if (siz <= cookie) { + *lenp = 0; + *eofp = true; + goto out; + } + if (siz > cookie + *lenp) { + siz = cookie + *lenp; + *eofp = false; + } else + *eofp = true; + /* Just choose a sanity limit of 10Mbytes for malloc(M_TEMP). */ + if (siz > 10 * 1024 * 1024) { + error = NFSERR_XATTR2BIG; + goto out; + } + *bufp = malloc(siz, M_TEMP, M_WAITOK); + iv.iov_base = *bufp; + iv.iov_len = siz; + io.uio_iovcnt = 1; + io.uio_iov = &iv; + io.uio_offset = 0; + io.uio_resid = siz; + io.uio_rw = UIO_READ; + io.uio_segflg = UIO_SYSSPACE; + io.uio_td = p; +#ifdef MAC + error = mac_vnode_check_listextattr(cred, vp, EXTATTR_NAMESPACE_USER); + if (error != 0) + goto out; +#endif + + error = VOP_LISTEXTATTR(vp, EXTATTR_NAMESPACE_USER, &io, NULL, cred, + p); + if (error != 0) + goto out; + if (io.uio_resid > 0) + siz -= io.uio_resid; + *lenp = siz; + +out: + if (error != 0) { + free(*bufp, M_TEMP); + *bufp = NULL; + } NFSEXITCODE(error); return (error); } Modified: projects/nfsv42/sys/fs/nfsserver/nfs_nfsdserv.c ============================================================================== --- projects/nfsv42/sys/fs/nfsserver/nfs_nfsdserv.c Sat Sep 7 03:51:26 2019 (r351967) +++ projects/nfsv42/sys/fs/nfsserver/nfs_nfsdserv.c Sat Sep 7 04:09:43 2019 (r351968) @@ -5482,8 +5482,8 @@ nfsrvd_getxattr(struct nfsrv_descript *nd, __unused in name = malloc(len + 1, M_TEMP, M_WAITOK); nd->nd_repstat = nfsrv_mtostr(nd, name, len); if (nd->nd_repstat == 0) - nd->nd_repstat = nfsvno_getxattr(vp, name, nd->nd_cred, p, - &mp, &mpend, &len); + nd->nd_repstat = nfsvno_getxattr(vp, name, nd->nd_maxresp, + nd->nd_cred, p, &mp, &mpend, &len); if (nd->nd_repstat == ENOATTR) nd->nd_repstat = NFSERR_NOXATTR; else if (nd->nd_repstat == EOPNOTSUPP) @@ -5513,11 +5513,11 @@ nfsrvd_setxattr(struct nfsrv_descript *nd, __unused in vnode_t vp, __unused struct nfsexstuff *exp) { uint32_t *tl; - mbuf_t mp = NULL, mpend = NULL; struct nfsvattr ova, nva; nfsattrbit_t attrbits; - int error, len, opt, retlen; + int error, len, opt; char *name; + size_t siz; struct thread *p = curthread; error = 0; @@ -5549,20 +5549,16 @@ nfsrvd_setxattr(struct nfsrv_descript *nd, __unused in } switch (opt) { case NFSV4SXATTR_CREATE: - error = nfsvno_getxattr(vp, name, nd->nd_cred, p, &mp, &mpend, - &retlen); - if (error == 0) - m_freem(mp); + error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, NULL, + &siz, nd->nd_cred, p); if (error != ENOATTR) nd->nd_repstat = NFSERR_EXIST; error = 0; break; case NFSV4SXATTR_REPLACE: - error = nfsvno_getxattr(vp, name, nd->nd_cred, p, &mp, &mpend, - &retlen); - if (error == 0) - m_freem(mp); - else + error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, NULL, + &siz, nd->nd_cred, p); + if (error != 0) nd->nd_repstat = NFSERR_NOXATTR; break; case NFSV4SXATTR_EITHER: @@ -5665,6 +5661,118 @@ nfsrvd_rmxattr(struct nfsrv_descript *nd, __unused int nfsmout: free(name, M_TEMP); + if (nd->nd_repstat == 0) + nd->nd_repstat = error; + vput(vp); + NFSEXITCODE2(0, nd); + return (0); +} + +/* + * nfs list extended attribute service + */ +APPLESTATIC int +nfsrvd_listxattr(struct nfsrv_descript *nd, __unused int isdgram, + vnode_t vp, __unused struct nfsexstuff *exp) +{ + uint32_t cnt, *tl, len, len2, i, pos, retlen; + int error; + uint64_t cookie, cookie2; + u_char *buf; + bool eof; + struct thread *p = curthread; + + error = 0; + buf = NULL; + if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { + nd->nd_repstat = NFSERR_WRONGSEC; + goto nfsmout; + } + NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + NFSX_UNSIGNED); + /* + * The cookie doesn't need to be in net byte order, but FreeBSD + * does so to make it more readable in packet traces. + */ + cookie = fxdr_hyper(tl); tl += 2; + len = fxdr_unsigned(uint32_t, *tl); + if (len == 0 || cookie >= IOSIZE_MAX) { + nd->nd_repstat = NFSERR_BADXDR; + goto nfsmout; + } + if (len > nd->nd_maxresp - NFS_MAXXDR) + len = nd->nd_maxresp - NFS_MAXXDR; + len2 = len; + nd->nd_repstat = nfsvno_listxattr(vp, cookie, nd->nd_cred, p, &buf, + &len, &eof); + if (nd->nd_repstat == EOPNOTSUPP) + nd->nd_repstat = NFSERR_NOTSUPP; + if (nd->nd_repstat == 0) { + cookie2 = cookie + len; + if (cookie2 < cookie) + nd->nd_repstat = NFSERR_BADXDR; + } + if (nd->nd_repstat == 0) { + /* Now copy the entries out. */ + retlen = NFSX_HYPER + 2 * NFSX_UNSIGNED; + if (len == 0 && retlen <= len2) { + /* The cookie was at eof. */ + NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + 2 * + NFSX_UNSIGNED); + txdr_hyper(cookie2, tl); tl += 2; + *tl++ = txdr_unsigned(0); + *tl = newnfs_true; + goto nfsmout; + } + + /* Sanity check the cookie. */ + for (pos = 0; pos < len; pos += (i + 1)) { + if (pos == cookie) + break; + i = buf[pos]; + } + if (pos != cookie) { + nd->nd_repstat = NFSERR_INVAL; + goto nfsmout; + } + + /* Loop around copying the entrie(s) out. */ + cnt = 0; + len -= cookie; + i = buf[pos]; + while (i < len && len2 >= retlen + NFSM_RNDUP(i) + + NFSX_UNSIGNED) { + if (cnt == 0) { + NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + + NFSX_UNSIGNED); + txdr_hyper(cookie2, tl); tl += 2; + } + retlen += nfsm_strtom(nd, &buf[pos + 1], i); + len -= (i + 1); + pos += (i + 1); + i = buf[pos]; + cnt++; + } + /* + * eof is set true/false by nfsvno_listxattr(), but if we + * can't copy all entries returned by nfsvno_listxattr(), + * we are not at eof. + */ + if (len > 0) + eof = false; + if (cnt > 0) { + /* *tl is set above. */ + *tl = txdr_unsigned(cnt); + NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); + if (eof) + *tl = newnfs_true; + else + *tl = newnfs_false; + } else + nd->nd_repstat = NFSERR_TOOSMALL; + } + +nfsmout: + free(buf, M_TEMP); if (nd->nd_repstat == 0) nd->nd_repstat = error; vput(vp); Modified: projects/nfsv42/sys/fs/nfsserver/nfs_nfsdsocket.c ============================================================================== --- projects/nfsv42/sys/fs/nfsserver/nfs_nfsdsocket.c Sat Sep 7 03:51:26 2019 (r351967) +++ projects/nfsv42/sys/fs/nfsserver/nfs_nfsdsocket.c Sat Sep 7 04:09:43 2019 (r351968) @@ -211,7 +211,7 @@ int (*nfsrv4_ops0[NFSV42_NOPS])(struct nfsrv_descript nfsrvd_notsupp, nfsrvd_getxattr, nfsrvd_setxattr, - nfsrvd_notsupp, + nfsrvd_listxattr, nfsrvd_rmxattr, }; Modified: projects/nfsv42/sys/fs/nfsserver/nfs_nfsdstate.c ============================================================================== --- projects/nfsv42/sys/fs/nfsserver/nfs_nfsdstate.c Sat Sep 7 03:51:26 2019 (r351967) +++ projects/nfsv42/sys/fs/nfsserver/nfs_nfsdstate.c Sat Sep 7 04:09:43 2019 (r351968) @@ -6209,6 +6209,10 @@ nfsrv_checksequence(struct nfsrv_descript *nd, uint32_ nd->nd_clientid.qval = sep->sess_clp->lc_clientid.qval; nd->nd_flag |= ND_IMPLIEDCLID; + /* Save maximum request and reply sizes. */ + nd->nd_maxreq = sep->sess_maxreq; + nd->nd_maxresp = sep->sess_maxresp; + /* * If this session handles the backchannel, save the nd_xprt for this * RPC, since this is the one being used.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201909070409.x8749h4O074603>