#include <sys/param.h>
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/user.h>
#include <sys/vnode.h>
#include <sys/file.h>
#include <sys/dirent.h>
#include <sys/vfs.h>
#include <sys/stream.h>
#include <sys/strsubr.h>
#include <sys/debug.h>
#include <sys/t_lock.h>
#include <sys/cmn_err.h>
#include <sys/dnlc.h>
#include <sys/cred.h>
#include <sys/time.h>
#include <sys/sdt.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <nfs/nfs.h>
#include <nfs/rnode.h>
#include <rpc/rpc_rdma.h>
bool_t
xdr_string3(XDR *xdrs, char **cpp, uint_t maxsize)
{
char *sp;
uint_t size;
uint_t nodesize;
bool_t mem_alloced = FALSE;
sp = *cpp;
switch (xdrs->x_op) {
case XDR_FREE:
if (sp == NULL || sp == nfs3nametoolong)
return (TRUE);
case XDR_ENCODE:
size = (uint_t)strlen(sp);
break;
case XDR_DECODE:
break;
}
if (!xdr_u_int(xdrs, &size))
return (FALSE);
switch (xdrs->x_op) {
case XDR_DECODE:
if (size >= maxsize) {
*cpp = nfs3nametoolong;
if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &size))
return (FALSE);
return (TRUE);
}
nodesize = size + 1;
if (nodesize == 0)
return (TRUE);
if (sp == NULL) {
sp = kmem_alloc(nodesize, KM_NOSLEEP);
*cpp = sp;
if (sp == NULL)
return (FALSE);
mem_alloced = TRUE;
}
sp[size] = 0;
if (xdr_opaque(xdrs, sp, size)) {
if (strlen(sp) != size) {
if (mem_alloced)
kmem_free(sp, nodesize);
*cpp = NULL;
return (FALSE);
}
} else {
if (mem_alloced)
kmem_free(sp, nodesize);
*cpp = NULL;
return (FALSE);
}
return (TRUE);
case XDR_ENCODE:
return (xdr_opaque(xdrs, sp, size));
case XDR_FREE:
nodesize = size + 1;
kmem_free(sp, nodesize);
*cpp = NULL;
return (TRUE);
}
return (FALSE);
}
bool_t
xdr_inline_decode_nfs_fh3(uint32_t *ptr, nfs_fh3 *fhp, uint32_t fhsize)
{
uchar_t *bp = (uchar_t *)ptr;
uchar_t *cp;
uint32_t dsize;
uintptr_t resid;
if (fhsize > sizeof (fhandle3_t) || fhsize < (sizeof (fsid_t) +
sizeof (ushort_t) + NFS_FHMAXDATA +
sizeof (ushort_t) + NFS_FHMAXDATA)) {
return (FALSE);
}
fhp->fh3_fsid.val[0] = *(uint32_t *)bp;
bp += BYTES_PER_XDR_UNIT;
fhp->fh3_fsid.val[1] = *(uint32_t *)bp;
bp += BYTES_PER_XDR_UNIT;
cp = (uchar_t *)&fhp->fh3_len;
*cp++ = *bp++;
*cp++ = *bp++;
fhsize -= 2 * BYTES_PER_XDR_UNIT + sizeof (ushort_t);
dsize = fhp->fh3_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh3_len;
if (fhsize < dsize)
return (FALSE);
bcopy(bp, fhp->fh3_data, dsize);
bp += dsize;
fhsize -= dsize;
if (fhsize < sizeof (ushort_t))
return (FALSE);
cp = (uchar_t *)&fhp->fh3_xlen;
*cp++ = *bp++;
*cp++ = *bp++;
fhsize -= sizeof (ushort_t);
dsize = fhp->fh3_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh3_xlen;
if (fhsize < dsize)
return (FALSE);
bcopy(bp, fhp->fh3_xdata, dsize);
fhsize -= dsize;
bp += dsize;
resid = (uintptr_t)bp % BYTES_PER_XDR_UNIT;
if (resid != 0) {
if (fhsize < (BYTES_PER_XDR_UNIT - resid))
return (FALSE);
bp += BYTES_PER_XDR_UNIT - resid;
fhsize -= BYTES_PER_XDR_UNIT - resid;
}
if (fhsize != 0)
return (FALSE);
return (TRUE);
}
static bool_t
xdr_decode_nfs_fh3(XDR *xdrs, nfs_fh3 *objp)
{
uint32_t fhsize;
uint32_t bufsize;
rpc_inline_t *ptr;
uchar_t *bp;
ASSERT(xdrs->x_op == XDR_DECODE);
if (!XDR_GETINT32(xdrs, (int32_t *)&fhsize))
return (FALSE);
bzero(objp->fh3_u.data, sizeof (objp->fh3_u.data));
objp->fh3_length = 0;
if (fhsize > sizeof (fhandle3_t) || fhsize < (sizeof (fsid_t) +
sizeof (ushort_t) + NFS_FHMAXDATA +
sizeof (ushort_t) + NFS_FHMAXDATA)) {
if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &fhsize))
return (FALSE);
return (TRUE);
}
bufsize = RNDUP(fhsize);
ptr = XDR_INLINE(xdrs, bufsize);
bp = (uchar_t *)ptr;
if (ptr == NULL) {
bp = kmem_alloc(bufsize, KM_SLEEP);
if (!xdr_opaque(xdrs, (char *)bp, bufsize)) {
kmem_free(bp, bufsize);
return (FALSE);
}
}
objp->fh3_length = sizeof (fhandle3_t);
if (xdr_inline_decode_nfs_fh3((uint32_t *)bp, objp, fhsize) == FALSE) {
bzero(objp->fh3_u.data, sizeof (objp->fh3_u.data));
objp->fh3_length = 0;
}
if (ptr == NULL)
kmem_free(bp, bufsize);
return (TRUE);
}
bool_t
xdr_inline_encode_nfs_fh3(uint32_t **ptrp, uint32_t *ptr_redzone,
nfs_fh3 *fhp)
{
uint32_t *ptr = *ptrp;
uchar_t *cp;
uint_t otw_len, fsize, xsize;
uint32_t padword;
fsize = fhp->fh3_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh3_len;
xsize = fhp->fh3_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh3_xlen;
otw_len = sizeof (fhp->fh3_fsid) +
sizeof (fhp->fh3_len) + fsize +
sizeof (fhp->fh3_xlen) + xsize;
otw_len = RNDUP(otw_len);
padword = (otw_len / BYTES_PER_XDR_UNIT);
if ((ptr + (otw_len / BYTES_PER_XDR_UNIT) + 1) > ptr_redzone)
return (FALSE);
ptr[padword] = 0;
IXDR_PUT_U_INT32(ptr, otw_len);
*ptr++ = (uint32_t)fhp->fh3_fsid.val[0];
*ptr++ = (uint32_t)fhp->fh3_fsid.val[1];
cp = (uchar_t *)ptr;
bcopy(&fhp->fh3_len, cp, sizeof (fhp->fh3_len) + fsize);
cp += sizeof (fhp->fh3_len) + fsize;
bcopy(&fhp->fh3_xlen, cp, sizeof (fhp->fh3_xlen) + xsize);
cp += sizeof (fhp->fh3_xlen) + xsize;
cp = (uchar_t *)RNDUP((uintptr_t)cp);
ptr = (uint32_t *)cp;
ASSERT(((uintptr_t)ptr % BYTES_PER_XDR_UNIT) == 0);
*ptrp = ptr;
return (TRUE);
}
static bool_t
xdr_encode_nfs_fh3(XDR *xdrs, nfs_fh3 *objp)
{
uint_t otw_len, fsize, xsize;
bool_t ret;
rpc_inline_t *ptr;
rpc_inline_t *buf = NULL;
uint32_t *ptr_redzone;
ASSERT(xdrs->x_op == XDR_ENCODE);
fsize = objp->fh3_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : objp->fh3_len;
xsize = objp->fh3_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : objp->fh3_xlen;
otw_len = BYTES_PER_XDR_UNIT + sizeof (objp->fh3_fsid) +
sizeof (objp->fh3_len) + fsize +
sizeof (objp->fh3_xlen) + xsize;
otw_len = RNDUP(otw_len);
ptr = XDR_INLINE(xdrs, otw_len);
if (ptr == NULL)
ptr = buf = kmem_alloc(otw_len, KM_SLEEP);
ptr_redzone = (uint32_t *)(ptr + (otw_len / BYTES_PER_XDR_UNIT));
ret = xdr_inline_encode_nfs_fh3((uint32_t **)&ptr, ptr_redzone, objp);
if (buf != NULL) {
if (ret == TRUE)
ret = xdr_opaque(xdrs, (char *)buf, otw_len);
kmem_free(buf, otw_len);
}
return (ret);
}
bool_t
xdr_nfs_fh3(XDR *xdrs, nfs_fh3 *objp)
{
if (xdrs->x_op == XDR_FREE)
return (TRUE);
if (!xdr_u_int(xdrs, &objp->fh3_length))
return (FALSE);
if (objp->fh3_length > NFS3_FHSIZE)
return (FALSE);
return (xdr_opaque(xdrs, objp->fh3_u.data, objp->fh3_length));
}
bool_t
xdr_nfs_fh3_server(XDR *xdrs, nfs_fh3 *objp)
{
switch (xdrs->x_op) {
case XDR_ENCODE:
if (objp->fh3_flags & FH_WEBNFS)
return (xdr_nfs_fh3(xdrs, objp));
else
return (xdr_encode_nfs_fh3(xdrs, objp));
case XDR_DECODE:
return (xdr_decode_nfs_fh3(xdrs, objp));
case XDR_FREE:
bzero(objp->fh3_u.data, sizeof (objp->fh3_u.data));
return (TRUE);
}
return (FALSE);
}
bool_t
xdr_diropargs3(XDR *xdrs, diropargs3 *objp)
{
switch (xdrs->x_op) {
case XDR_FREE:
case XDR_ENCODE:
if (!xdr_nfs_fh3(xdrs, objp->dirp))
return (FALSE);
break;
case XDR_DECODE:
if (!xdr_nfs_fh3_server(xdrs, &objp->dir))
return (FALSE);
break;
}
return (xdr_string3(xdrs, &objp->name, MAXNAMELEN));
}
static bool_t
xdr_fattr3(XDR *xdrs, fattr3 *na)
{
int32_t *ptr;
if (xdrs->x_op == XDR_FREE)
return (TRUE);
ptr = XDR_INLINE(xdrs, NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT);
if (ptr != NULL) {
if (xdrs->x_op == XDR_DECODE) {
na->type = IXDR_GET_ENUM(ptr, enum ftype3);
na->mode = IXDR_GET_U_INT32(ptr);
na->nlink = IXDR_GET_U_INT32(ptr);
na->uid = IXDR_GET_U_INT32(ptr);
na->gid = IXDR_GET_U_INT32(ptr);
IXDR_GET_U_HYPER(ptr, na->size);
IXDR_GET_U_HYPER(ptr, na->used);
na->rdev.specdata1 = IXDR_GET_U_INT32(ptr);
na->rdev.specdata2 = IXDR_GET_U_INT32(ptr);
IXDR_GET_U_HYPER(ptr, na->fsid);
IXDR_GET_U_HYPER(ptr, na->fileid);
na->atime.seconds = IXDR_GET_U_INT32(ptr);
na->atime.nseconds = IXDR_GET_U_INT32(ptr);
na->mtime.seconds = IXDR_GET_U_INT32(ptr);
na->mtime.nseconds = IXDR_GET_U_INT32(ptr);
na->ctime.seconds = IXDR_GET_U_INT32(ptr);
na->ctime.nseconds = IXDR_GET_U_INT32(ptr);
} else {
IXDR_PUT_ENUM(ptr, na->type);
IXDR_PUT_U_INT32(ptr, na->mode);
IXDR_PUT_U_INT32(ptr, na->nlink);
IXDR_PUT_U_INT32(ptr, na->uid);
IXDR_PUT_U_INT32(ptr, na->gid);
IXDR_PUT_U_HYPER(ptr, na->size);
IXDR_PUT_U_HYPER(ptr, na->used);
IXDR_PUT_U_INT32(ptr, na->rdev.specdata1);
IXDR_PUT_U_INT32(ptr, na->rdev.specdata2);
IXDR_PUT_U_HYPER(ptr, na->fsid);
IXDR_PUT_U_HYPER(ptr, na->fileid);
IXDR_PUT_U_INT32(ptr, na->atime.seconds);
IXDR_PUT_U_INT32(ptr, na->atime.nseconds);
IXDR_PUT_U_INT32(ptr, na->mtime.seconds);
IXDR_PUT_U_INT32(ptr, na->mtime.nseconds);
IXDR_PUT_U_INT32(ptr, na->ctime.seconds);
IXDR_PUT_U_INT32(ptr, na->ctime.nseconds);
}
return (TRUE);
}
if (!(xdr_enum(xdrs, (enum_t *)&na->type) &&
xdr_u_int(xdrs, &na->mode) &&
xdr_u_int(xdrs, &na->nlink) &&
xdr_u_int(xdrs, &na->uid) &&
xdr_u_int(xdrs, &na->gid) &&
xdr_u_longlong_t(xdrs, &na->size) &&
xdr_u_longlong_t(xdrs, &na->used) &&
xdr_u_int(xdrs, &na->rdev.specdata1) &&
xdr_u_int(xdrs, &na->rdev.specdata2) &&
xdr_u_longlong_t(xdrs, &na->fsid) &&
xdr_u_longlong_t(xdrs, &na->fileid) &&
xdr_u_int(xdrs, &na->atime.seconds) &&
xdr_u_int(xdrs, &na->atime.nseconds) &&
xdr_u_int(xdrs, &na->mtime.seconds) &&
xdr_u_int(xdrs, &na->mtime.nseconds) &&
xdr_u_int(xdrs, &na->ctime.seconds) &&
xdr_u_int(xdrs, &na->ctime.nseconds)))
return (FALSE);
return (TRUE);
}
static bool_t
xdr_fattr3_to_vattr(XDR *xdrs, fattr3_res *objp)
{
int32_t *ptr;
size3 used;
specdata3 rdev;
uint32_t ntime;
vattr_t *vap = objp->vap;
ASSERT(xdrs->x_op == XDR_DECODE);
vap->va_mask = AT_ALL;
objp->status = 0;
ptr = XDR_INLINE(xdrs, NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT);
if (ptr != NULL) {
vap->va_type = IXDR_GET_ENUM(ptr, enum vtype);
if ((ftype3)vap->va_type < NF3REG ||
(ftype3)vap->va_type > NF3FIFO)
vap->va_type = VBAD;
else
vap->va_type = nf3_to_vt[vap->va_type];
vap->va_mode = IXDR_GET_U_INT32(ptr);
vap->va_nlink = IXDR_GET_U_INT32(ptr);
vap->va_uid = (uid_t)IXDR_GET_U_INT32(ptr);
if (vap->va_uid == NFS_UID_NOBODY)
vap->va_uid = UID_NOBODY;
vap->va_gid = (gid_t)IXDR_GET_U_INT32(ptr);
if (vap->va_gid == NFS_GID_NOBODY)
vap->va_gid = GID_NOBODY;
IXDR_GET_U_HYPER(ptr, vap->va_size);
if (!NFS3_SIZE_OK(vap->va_size)) {
objp->status = EFBIG;
return (TRUE);
}
IXDR_GET_U_HYPER(ptr, used);
rdev.specdata1 = IXDR_GET_U_INT32(ptr);
rdev.specdata2 = IXDR_GET_U_INT32(ptr);
ptr += 2;
IXDR_GET_U_HYPER(ptr, vap->va_nodeid);
if (nfs_allow_preepoch_time) {
vap->va_atime.tv_sec = IXDR_GET_INT32(ptr);
vap->va_atime.tv_nsec = IXDR_GET_U_INT32(ptr);
vap->va_mtime.tv_sec = IXDR_GET_INT32(ptr);
vap->va_mtime.tv_nsec = IXDR_GET_U_INT32(ptr);
vap->va_ctime.tv_sec = IXDR_GET_INT32(ptr);
vap->va_ctime.tv_nsec = IXDR_GET_U_INT32(ptr);
} else {
ntime = IXDR_GET_U_INT32(ptr);
if (NFS3_TIME_OVERFLOW(ntime)) {
objp->status = EOVERFLOW;
return (TRUE);
}
vap->va_atime.tv_sec = ntime;
vap->va_atime.tv_nsec = IXDR_GET_U_INT32(ptr);
ntime = IXDR_GET_U_INT32(ptr);
if (NFS3_TIME_OVERFLOW(ntime)) {
objp->status = EOVERFLOW;
return (TRUE);
}
vap->va_mtime.tv_sec = ntime;
vap->va_mtime.tv_nsec = IXDR_GET_U_INT32(ptr);
ntime = IXDR_GET_U_INT32(ptr);
if (NFS3_TIME_OVERFLOW(ntime)) {
objp->status = EOVERFLOW;
return (TRUE);
}
vap->va_ctime.tv_sec = ntime;
vap->va_ctime.tv_nsec = IXDR_GET_U_INT32(ptr);
}
} else {
uint64 fsid;
if (!(xdr_enum(xdrs, (enum_t *)&vap->va_type) &&
xdr_u_int(xdrs, &vap->va_mode) &&
xdr_u_int(xdrs, &vap->va_nlink) &&
xdr_u_int(xdrs, (uint_t *)&vap->va_uid) &&
xdr_u_int(xdrs, (uint_t *)&vap->va_gid) &&
xdr_u_longlong_t(xdrs, &vap->va_size) &&
xdr_u_longlong_t(xdrs, &used) &&
xdr_u_int(xdrs, &rdev.specdata1) &&
xdr_u_int(xdrs, &rdev.specdata2) &&
xdr_u_longlong_t(xdrs, &fsid) &&
xdr_u_longlong_t(xdrs, &vap->va_nodeid)))
return (FALSE);
if (nfs_allow_preepoch_time) {
if (!xdr_u_int(xdrs, &ntime))
return (FALSE);
vap->va_atime.tv_sec = (int32_t)ntime;
if (!xdr_u_int(xdrs, &ntime))
return (FALSE);
vap->va_atime.tv_nsec = ntime;
if (!xdr_u_int(xdrs, &ntime))
return (FALSE);
vap->va_mtime.tv_sec = (int32_t)ntime;
if (!xdr_u_int(xdrs, &ntime))
return (FALSE);
vap->va_mtime.tv_nsec = ntime;
if (!xdr_u_int(xdrs, &ntime))
return (FALSE);
vap->va_ctime.tv_sec = (int32_t)ntime;
if (!xdr_u_int(xdrs, &ntime))
return (FALSE);
vap->va_ctime.tv_nsec = ntime;
} else {
if (!xdr_u_int(xdrs, &ntime))
return (FALSE);
if (NFS3_TIME_OVERFLOW(ntime)) {
objp->status = EOVERFLOW;
}
vap->va_atime.tv_sec = ntime;
if (!xdr_u_int(xdrs, &ntime))
return (FALSE);
vap->va_atime.tv_nsec = ntime;
if (!xdr_u_int(xdrs, &ntime))
return (FALSE);
if (NFS3_TIME_OVERFLOW(ntime)) {
objp->status = EOVERFLOW;
}
vap->va_mtime.tv_sec = ntime;
if (!xdr_u_int(xdrs, &ntime))
return (FALSE);
vap->va_mtime.tv_nsec = ntime;
if (!xdr_u_int(xdrs, &ntime))
return (FALSE);
if (NFS3_TIME_OVERFLOW(ntime)) {
objp->status = EOVERFLOW;
}
vap->va_ctime.tv_sec = ntime;
if (!xdr_u_int(xdrs, &ntime))
return (FALSE);
vap->va_ctime.tv_nsec = ntime;
}
if ((ftype3)vap->va_type < NF3REG ||
(ftype3)vap->va_type > NF3FIFO)
vap->va_type = VBAD;
else
vap->va_type = nf3_to_vt[vap->va_type];
if (vap->va_uid == NFS_UID_NOBODY)
vap->va_uid = UID_NOBODY;
if (vap->va_gid == NFS_GID_NOBODY)
vap->va_gid = GID_NOBODY;
if (!NFS3_SIZE_OK(vap->va_size)) {
objp->status = EFBIG;
return (TRUE);
}
}
vap->va_fsid = objp->vp->v_vfsp->vfs_dev;
vap->va_seq = 0;
vap->va_rdev = 0;
vap->va_blksize = MAXBSIZE;
vap->va_nblocks = 0;
switch (vap->va_type) {
case VREG:
case VDIR:
case VLNK:
vap->va_nblocks = (u_longlong_t)
((used + (size3)DEV_BSIZE - (size3)1) /
(size3)DEV_BSIZE);
break;
case VBLK:
vap->va_blksize = DEV_BSIZE;
case VCHR:
vap->va_rdev = makedevice(rdev.specdata1, rdev.specdata2);
break;
case VSOCK:
case VFIFO:
default:
break;
}
return (TRUE);
}
static bool_t
xdr_post_op_vattr(XDR *xdrs, post_op_vattr *objp)
{
ASSERT(xdrs->x_op == XDR_DECODE);
if (!xdr_bool(xdrs, &objp->attributes))
return (FALSE);
if (objp->attributes == FALSE)
return (TRUE);
if (objp->attributes != TRUE)
return (FALSE);
if (!xdr_fattr3_to_vattr(xdrs, &objp->fres))
return (FALSE);
if (objp->fres.status != NFS3_OK)
objp->attributes = FALSE;
return (TRUE);
}
bool_t
xdr_post_op_attr(XDR *xdrs, post_op_attr *objp)
{
if (!xdr_bool(xdrs, &objp->attributes))
return (FALSE);
if (objp->attributes == FALSE)
return (TRUE);
if (objp->attributes != TRUE)
return (FALSE);
if (!xdr_fattr3(xdrs, &objp->attr))
return (FALSE);
if (xdrs->x_op == XDR_DECODE) {
if (!NFS3_SIZE_OK(objp->attr.size)) {
objp->attributes = FALSE;
return (TRUE);
}
#ifndef _LP64
if (!NFS3_FATTR_TIME_OK(&objp->attr))
objp->attributes = FALSE;
#endif
}
return (TRUE);
}
static bool_t
xdr_wcc_data(XDR *xdrs, wcc_data *objp)
{
int32_t *ptr;
wcc_attr *attrp;
if (xdrs->x_op == XDR_FREE)
return (TRUE);
if (xdrs->x_op == XDR_DECODE) {
if (!xdr_bool(xdrs, &objp->before.attributes))
return (FALSE);
switch (objp->before.attributes) {
case TRUE:
attrp = &objp->before.attr;
ptr = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
if (ptr != NULL) {
IXDR_GET_U_HYPER(ptr, attrp->size);
attrp->mtime.seconds = IXDR_GET_U_INT32(ptr);
attrp->mtime.nseconds = IXDR_GET_U_INT32(ptr);
attrp->ctime.seconds = IXDR_GET_U_INT32(ptr);
attrp->ctime.nseconds = IXDR_GET_U_INT32(ptr);
} else {
if (!xdr_u_longlong_t(xdrs, &attrp->size))
return (FALSE);
if (!xdr_u_int(xdrs, &attrp->mtime.seconds))
return (FALSE);
if (!xdr_u_int(xdrs, &attrp->mtime.nseconds))
return (FALSE);
if (!xdr_u_int(xdrs, &attrp->ctime.seconds))
return (FALSE);
if (!xdr_u_int(xdrs, &attrp->ctime.nseconds))
return (FALSE);
}
#ifndef _LP64
if (!NFS3_TIME_OK(attrp->mtime.seconds) ||
!NFS3_TIME_OK(attrp->ctime.seconds))
objp->before.attributes = FALSE;
#endif
break;
case FALSE:
break;
default:
return (FALSE);
}
}
if (xdrs->x_op == XDR_ENCODE) {
if (!xdr_bool(xdrs, &objp->before.attributes))
return (FALSE);
switch (objp->before.attributes) {
case TRUE:
attrp = &objp->before.attr;
ptr = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
if (ptr != NULL) {
IXDR_PUT_U_HYPER(ptr, attrp->size);
IXDR_PUT_U_INT32(ptr, attrp->mtime.seconds);
IXDR_PUT_U_INT32(ptr, attrp->mtime.nseconds);
IXDR_PUT_U_INT32(ptr, attrp->ctime.seconds);
IXDR_PUT_U_INT32(ptr, attrp->ctime.nseconds);
} else {
if (!xdr_u_longlong_t(xdrs, &attrp->size))
return (FALSE);
if (!xdr_u_int(xdrs, &attrp->mtime.seconds))
return (FALSE);
if (!xdr_u_int(xdrs, &attrp->mtime.nseconds))
return (FALSE);
if (!xdr_u_int(xdrs, &attrp->ctime.seconds))
return (FALSE);
if (!xdr_u_int(xdrs, &attrp->ctime.nseconds))
return (FALSE);
}
break;
case FALSE:
break;
default:
return (FALSE);
}
}
return (xdr_post_op_attr(xdrs, &objp->after));
}
bool_t
xdr_post_op_fh3(XDR *xdrs, post_op_fh3 *objp)
{
if (!xdr_bool(xdrs, &objp->handle_follows))
return (FALSE);
switch (objp->handle_follows) {
case TRUE:
switch (xdrs->x_op) {
case XDR_ENCODE:
if (!xdr_nfs_fh3_server(xdrs, &objp->handle))
return (FALSE);
break;
case XDR_FREE:
case XDR_DECODE:
if (!xdr_nfs_fh3(xdrs, &objp->handle))
return (FALSE);
break;
}
return (TRUE);
case FALSE:
return (TRUE);
default:
return (FALSE);
}
}
static bool_t
xdr_sattr3(XDR *xdrs, sattr3 *objp)
{
if (!xdr_bool(xdrs, &objp->mode.set_it))
return (FALSE);
if (objp->mode.set_it)
if (!xdr_u_int(xdrs, &objp->mode.mode))
return (FALSE);
if (!xdr_bool(xdrs, &objp->uid.set_it))
return (FALSE);
if (objp->uid.set_it)
if (!xdr_u_int(xdrs, &objp->uid.uid))
return (FALSE);
if (!xdr_bool(xdrs, &objp->gid.set_it))
return (FALSE);
if (objp->gid.set_it)
if (!xdr_u_int(xdrs, &objp->gid.gid))
return (FALSE);
if (!xdr_bool(xdrs, &objp->size.set_it))
return (FALSE);
if (objp->size.set_it)
if (!xdr_u_longlong_t(xdrs, &objp->size.size))
return (FALSE);
if (!xdr_enum(xdrs, (enum_t *)&objp->atime.set_it))
return (FALSE);
if (objp->atime.set_it == SET_TO_CLIENT_TIME) {
if (!xdr_u_int(xdrs, &objp->atime.atime.seconds))
return (FALSE);
if (!xdr_u_int(xdrs, &objp->atime.atime.nseconds))
return (FALSE);
}
if (!xdr_enum(xdrs, (enum_t *)&objp->mtime.set_it))
return (FALSE);
if (objp->mtime.set_it == SET_TO_CLIENT_TIME) {
if (!xdr_u_int(xdrs, &objp->mtime.mtime.seconds))
return (FALSE);
if (!xdr_u_int(xdrs, &objp->mtime.mtime.nseconds))
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_GETATTR3res(XDR *xdrs, GETATTR3res *objp)
{
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
if (objp->status != NFS3_OK)
return (TRUE);
return (xdr_fattr3(xdrs, &objp->resok.obj_attributes));
}
bool_t
xdr_GETATTR3vres(XDR *xdrs, GETATTR3vres *objp)
{
if (xdrs->x_op == XDR_FREE)
return (TRUE);
if (xdrs->x_op != XDR_DECODE)
return (FALSE);
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
if (objp->status != NFS3_OK)
return (TRUE);
return (xdr_fattr3_to_vattr(xdrs, &objp->fres));
}
bool_t
xdr_SETATTR3args(XDR *xdrs, SETATTR3args *objp)
{
switch (xdrs->x_op) {
case XDR_FREE:
case XDR_ENCODE:
if (!xdr_nfs_fh3(xdrs, &objp->object))
return (FALSE);
break;
case XDR_DECODE:
if (!xdr_nfs_fh3_server(xdrs, &objp->object))
return (FALSE);
break;
}
if (!xdr_sattr3(xdrs, &objp->new_attributes))
return (FALSE);
if (!xdr_bool(xdrs, &objp->guard.check))
return (FALSE);
switch (objp->guard.check) {
case TRUE:
if (!xdr_u_int(xdrs, &objp->guard.obj_ctime.seconds))
return (FALSE);
return (xdr_u_int(xdrs, &objp->guard.obj_ctime.nseconds));
case FALSE:
return (TRUE);
default:
return (FALSE);
}
}
bool_t
xdr_SETATTR3res(XDR *xdrs, SETATTR3res *objp)
{
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
switch (objp->status) {
case NFS3_OK:
return (xdr_wcc_data(xdrs, &objp->resok.obj_wcc));
default:
return (xdr_wcc_data(xdrs, &objp->resfail.obj_wcc));
}
}
bool_t
xdr_LOOKUP3res(XDR *xdrs, LOOKUP3res *objp)
{
LOOKUP3resok *resokp;
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
if (objp->status != NFS3_OK)
return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes));
resokp = &objp->resok;
switch (xdrs->x_op) {
case XDR_ENCODE:
if (!xdr_nfs_fh3_server(xdrs, &resokp->object))
return (FALSE);
break;
case XDR_FREE:
case XDR_DECODE:
if (!xdr_nfs_fh3(xdrs, &resokp->object))
return (FALSE);
break;
}
if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
return (FALSE);
return (xdr_post_op_attr(xdrs, &resokp->dir_attributes));
}
bool_t
xdr_LOOKUP3vres(XDR *xdrs, LOOKUP3vres *objp)
{
if (xdrs->x_op == XDR_FREE)
return (TRUE);
if (xdrs->x_op != XDR_DECODE)
return (FALSE);
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
if (objp->status != NFS3_OK)
return (xdr_post_op_vattr(xdrs, &objp->dir_attributes));
if (!xdr_nfs_fh3(xdrs, &objp->object))
return (FALSE);
if (!xdr_post_op_vattr(xdrs, &objp->obj_attributes))
return (FALSE);
return (xdr_post_op_vattr(xdrs, &objp->dir_attributes));
}
bool_t
xdr_ACCESS3args(XDR *xdrs, ACCESS3args *objp)
{
switch (xdrs->x_op) {
case XDR_FREE:
case XDR_ENCODE:
if (!xdr_nfs_fh3(xdrs, &objp->object))
return (FALSE);
break;
case XDR_DECODE:
if (!xdr_nfs_fh3_server(xdrs, &objp->object))
return (FALSE);
break;
}
return (xdr_u_int(xdrs, &objp->access));
}
bool_t
xdr_ACCESS3res(XDR *xdrs, ACCESS3res *objp)
{
ACCESS3resok *resokp;
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
if (objp->status != NFS3_OK)
return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
resokp = &objp->resok;
if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
return (FALSE);
return (xdr_u_int(xdrs, &resokp->access));
}
bool_t
xdr_READLINK3args(XDR *xdrs, READLINK3args *objp)
{
rdma_chunkinfo_t rci;
struct xdr_ops *xops = xdrrdma_xops();
if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
xdrs->x_op == XDR_ENCODE) {
rci.rci_type = RCI_REPLY_CHUNK;
rci.rci_len = MAXPATHLEN;
XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
}
if (!xdr_nfs_fh3(xdrs, (nfs_fh3 *)objp))
return (FALSE);
return (TRUE);
}
bool_t
xdr_READLINK3res(XDR *xdrs, READLINK3res *objp)
{
READLINK3resok *resokp;
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
if (objp->status != NFS3_OK)
return (xdr_post_op_attr(xdrs,
&objp->resfail.symlink_attributes));
resokp = &objp->resok;
if (!xdr_post_op_attr(xdrs, &resokp->symlink_attributes))
return (FALSE);
return (xdr_string3(xdrs, &resokp->data, MAXPATHLEN));
}
bool_t
xdr_READ3args(XDR *xdrs, READ3args *objp)
{
rdma_chunkinfo_t rci;
rdma_wlist_conn_info_t rwci;
struct xdr_ops *xops = xdrrdma_xops();
switch (xdrs->x_op) {
case XDR_FREE:
case XDR_ENCODE:
if (!xdr_nfs_fh3(xdrs, &objp->file))
return (FALSE);
break;
case XDR_DECODE:
if (!xdr_nfs_fh3_server(xdrs, &objp->file))
return (FALSE);
break;
}
if (!xdr_u_longlong_t(xdrs, &objp->offset))
return (FALSE);
if (!xdr_u_int(xdrs, &objp->count))
return (FALSE);
DTRACE_PROBE1(xdr__i__read3_buf_len, int, objp->count);
objp->wlist = NULL;
if (xdrs->x_ops == xops && xdrs->x_op == XDR_ENCODE) {
rci.rci_type = RCI_WRITE_ADDR_CHUNK;
rci.rci_len = objp->count;
(void) XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
}
if (xdrs->x_ops != &xdrrdma_ops || xdrs->x_op == XDR_FREE)
return (TRUE);
if (xdrs->x_op == XDR_ENCODE) {
if (objp->res_uiop != NULL) {
rci.rci_type = RCI_WRITE_UIO_CHUNK;
rci.rci_a.rci_uiop = objp->res_uiop;
rci.rci_len = objp->count;
rci.rci_clpp = &objp->wlist;
} else {
rci.rci_type = RCI_WRITE_ADDR_CHUNK;
rci.rci_a.rci_addr = objp->res_data_val_alt;
rci.rci_len = objp->count;
rci.rci_clpp = &objp->wlist;
}
return (XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci));
}
(void) XDR_CONTROL(xdrs, XDR_RDMA_GET_WCINFO, &rwci);
objp->wlist = rwci.rwci_wlist;
objp->conn = rwci.rwci_conn;
return (TRUE);
}
bool_t
xdr_READ3res(XDR *xdrs, READ3res *objp)
{
READ3resok *resokp;
bool_t ret;
mblk_t *mp;
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
if (objp->status != NFS3_OK)
return (xdr_post_op_attr(xdrs, &objp->resfail.file_attributes));
resokp = &objp->resok;
if (xdr_post_op_attr(xdrs, &resokp->file_attributes) == FALSE ||
xdr_u_int(xdrs, &resokp->count) == FALSE ||
xdr_bool(xdrs, &resokp->eof) == FALSE) {
return (FALSE);
}
if (xdrs->x_op == XDR_ENCODE) {
mp = resokp->data.mp;
if (mp != NULL) {
if (xdrs->x_ops == &xdrmblk_ops) {
if (xdrmblk_putmblk(xdrs, mp, resokp->count)) {
resokp->data.mp = NULL;
return (TRUE);
} else {
return (FALSE);
}
} else if (mp->b_cont != NULL) {
if (pullupmsg(mp, -1) == 0)
return (FALSE);
resokp->data.data_val = (caddr_t)mp->b_rptr;
}
} else {
if (xdr_u_int(xdrs, &resokp->count) == FALSE) {
return (FALSE);
}
if (resokp->wlist) {
if (resokp->count != 0) {
return (xdrrdma_send_read_data(
xdrs, resokp->count,
resokp->wlist));
}
return (TRUE);
}
}
}
ret = xdr_bytes(xdrs, (char **)&resokp->data.data_val,
&resokp->data.data_len, nfs3tsize());
return (ret);
}
bool_t
xdr_READ3vres(XDR *xdrs, READ3vres *objp)
{
count3 ocount;
if (xdrs->x_op == XDR_FREE)
return (TRUE);
if (xdrs->x_op != XDR_DECODE)
return (FALSE);
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
if (!xdr_post_op_vattr(xdrs, &objp->pov))
return (FALSE);
if (objp->status != NFS3_OK)
return (TRUE);
if (!xdr_u_int(xdrs, &objp->count))
return (FALSE);
if (!xdr_bool(xdrs, &objp->eof))
return (FALSE);
if (xdrs->x_ops == &xdrrdma_ops) {
struct clist *cl;
XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl);
if (cl) {
if (!xdr_u_int(xdrs, &ocount)) {
return (FALSE);
}
if (ocount != objp->count) {
DTRACE_PROBE2(xdr__e__read3vres_fail,
int, ocount, int, objp->count);
objp->wlist = NULL;
return (FALSE);
}
objp->wlist_len = clist_len(cl);
objp->data.data_len = ocount;
if (objp->wlist_len !=
roundup(objp->data.data_len, BYTES_PER_XDR_UNIT)) {
DTRACE_PROBE2(
xdr__e__read3vres_fail,
int, ocount,
int, objp->data.data_len);
objp->wlist = NULL;
return (FALSE);
}
return (TRUE);
}
}
return (xdr_bytes(xdrs, (char **)&objp->data.data_val,
&objp->data.data_len, nfs3tsize()));
}
bool_t
xdr_READ3uiores(XDR *xdrs, READ3uiores *objp)
{
count3 ocount;
bool_t attributes;
mblk_t *mp;
size_t n;
int error;
int size = (int)objp->size;
struct uio *uiop = objp->uiop;
int32_t fattr3_len = NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
int32_t *ptr;
if (xdrs->x_op == XDR_FREE)
return (TRUE);
if (xdrs->x_op != XDR_DECODE)
return (FALSE);
if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status))
return (FALSE);
if (!XDR_GETINT32(xdrs, (int32_t *)&attributes))
return (FALSE);
switch (attributes) {
case TRUE:
if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &fattr3_len))
return (FALSE);
break;
case FALSE:
break;
default:
return (FALSE);
}
if (objp->status != NFS3_OK)
return (TRUE);
if (!XDR_GETINT32(xdrs, (int32_t *)&objp->count))
return (FALSE);
if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof))
return (FALSE);
if (xdrs->x_ops == &xdrmblk_ops) {
if (!xdrmblk_getmblk(xdrs, &mp, &objp->size))
return (FALSE);
if (objp->size == 0)
return (TRUE);
if (objp->size > size)
return (FALSE);
size = (int)objp->size;
do {
n = MIN(size, mp->b_wptr - mp->b_rptr);
if ((n = MIN(uiop->uio_resid, n)) != 0) {
error = uiomove((char *)mp->b_rptr, n, UIO_READ,
uiop);
if (error)
return (FALSE);
mp->b_rptr += n;
size -= n;
}
while (mp && (mp->b_rptr >= mp->b_wptr))
mp = mp->b_cont;
} while (mp && size > 0 && uiop->uio_resid > 0);
return (TRUE);
}
if (xdrs->x_ops == &xdrrdma_ops) {
struct clist *cl;
XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl);
objp->wlist = cl;
if (objp->wlist) {
if (!xdr_u_int(xdrs, &ocount)) {
objp->wlist = NULL;
return (FALSE);
}
if (ocount != objp->count) {
DTRACE_PROBE2(xdr__e__read3uiores_fail,
int, ocount, int, objp->count);
objp->wlist = NULL;
return (FALSE);
}
objp->wlist_len = clist_len(cl);
uiop->uio_resid -= objp->count;
uiop->uio_iov->iov_len -= objp->count;
uiop->uio_iov->iov_base += objp->count;
uiop->uio_loffset += objp->count;
objp->size = objp->count;
return (TRUE);
}
}
if (!XDR_GETINT32(xdrs, (int32_t *)&objp->size))
return (FALSE);
if (objp->size == 0)
return (TRUE);
if (objp->size > size)
return (FALSE);
size = (int)objp->size;
if ((ptr = XDR_INLINE(xdrs, size)) != NULL)
return (uiomove(ptr, size, UIO_READ, uiop) ? FALSE : TRUE);
if ((ptr = kmem_alloc(size, KM_NOSLEEP)) == NULL)
return (FALSE);
if (!XDR_GETBYTES(xdrs, (caddr_t)ptr, size)) {
kmem_free(ptr, size);
return (FALSE);
}
error = uiomove(ptr, size, UIO_READ, uiop);
kmem_free(ptr, size);
return (error ? FALSE : TRUE);
}
bool_t
xdr_WRITE3args(XDR *xdrs, WRITE3args *objp)
{
switch (xdrs->x_op) {
case XDR_FREE:
case XDR_ENCODE:
if (!xdr_nfs_fh3(xdrs, &objp->file))
return (FALSE);
break;
case XDR_DECODE:
if (!xdr_nfs_fh3_server(xdrs, &objp->file))
return (FALSE);
break;
}
if (!xdr_u_longlong_t(xdrs, &objp->offset))
return (FALSE);
if (!xdr_u_int(xdrs, &objp->count))
return (FALSE);
if (!xdr_enum(xdrs, (enum_t *)&objp->stable))
return (FALSE);
if (xdrs->x_op == XDR_DECODE) {
if (xdrs->x_ops == &xdrmblk_ops) {
if (xdrmblk_getmblk(xdrs, &objp->mblk,
&objp->data.data_len) == TRUE) {
objp->data.data_val = NULL;
return (TRUE);
}
}
objp->mblk = NULL;
if (xdrs->x_ops == &xdrrdmablk_ops) {
if (xdrrdma_getrdmablk(xdrs, &objp->rlist,
&objp->data.data_len,
&objp->conn, nfs3tsize()) == TRUE) {
objp->data.data_val = NULL;
if (xdrrdma_read_from_client(
objp->rlist,
&objp->conn,
objp->count) == FALSE) {
return (FALSE);
}
return (TRUE);
}
}
objp->rlist = NULL;
}
if (xdrs->x_op == XDR_FREE) {
if (objp->rlist != NULL) {
(void) xdrrdma_free_clist(objp->conn, objp->rlist);
objp->rlist = NULL;
objp->data.data_val = NULL;
return (TRUE);
}
}
DTRACE_PROBE1(xdr__i__write3_buf_len,
int, objp->data.data_len);
return (xdr_bytes(xdrs, (char **)&objp->data.data_val,
&objp->data.data_len, nfs3tsize()));
}
bool_t
xdr_WRITE3res(XDR *xdrs, WRITE3res *objp)
{
WRITE3resok *resokp;
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
if (objp->status != NFS3_OK)
return (xdr_wcc_data(xdrs, &objp->resfail.file_wcc));
resokp = &objp->resok;
if (!xdr_wcc_data(xdrs, &resokp->file_wcc))
return (FALSE);
if (!xdr_u_int(xdrs, &resokp->count))
return (FALSE);
if (!xdr_enum(xdrs, (enum_t *)&resokp->committed))
return (FALSE);
return (xdr_u_longlong_t(xdrs, &resokp->verf));
}
bool_t
xdr_CREATE3args(XDR *xdrs, CREATE3args *objp)
{
createhow3 *howp;
if (!xdr_diropargs3(xdrs, &objp->where))
return (FALSE);
howp = &objp->how;
if (!xdr_enum(xdrs, (enum_t *)&howp->mode))
return (FALSE);
switch (howp->mode) {
case UNCHECKED:
case GUARDED:
return (xdr_sattr3(xdrs, &howp->createhow3_u.obj_attributes));
case EXCLUSIVE:
return (xdr_u_longlong_t(xdrs, &howp->createhow3_u.verf));
default:
return (FALSE);
}
}
bool_t
xdr_CREATE3res(XDR *xdrs, CREATE3res *objp)
{
CREATE3resok *resokp;
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
switch (objp->status) {
case NFS3_OK:
resokp = &objp->resok;
if (!xdr_post_op_fh3(xdrs, &resokp->obj))
return (FALSE);
if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
return (FALSE);
return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
default:
return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
}
}
bool_t
xdr_MKDIR3args(XDR *xdrs, MKDIR3args *objp)
{
if (!xdr_diropargs3(xdrs, &objp->where))
return (FALSE);
return (xdr_sattr3(xdrs, &objp->attributes));
}
bool_t
xdr_MKDIR3res(XDR *xdrs, MKDIR3res *objp)
{
MKDIR3resok *resokp;
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
switch (objp->status) {
case NFS3_OK:
resokp = &objp->resok;
if (!xdr_post_op_fh3(xdrs, &resokp->obj))
return (FALSE);
if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
return (FALSE);
return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
default:
return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
}
}
bool_t
xdr_SYMLINK3args(XDR *xdrs, SYMLINK3args *objp)
{
if (!xdr_diropargs3(xdrs, &objp->where))
return (FALSE);
if (!xdr_sattr3(xdrs, &objp->symlink.symlink_attributes))
return (FALSE);
return (xdr_string3(xdrs, &objp->symlink.symlink_data, MAXPATHLEN));
}
bool_t
xdr_SYMLINK3res(XDR *xdrs, SYMLINK3res *objp)
{
SYMLINK3resok *resokp;
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
switch (objp->status) {
case NFS3_OK:
resokp = &objp->resok;
if (!xdr_post_op_fh3(xdrs, &resokp->obj))
return (FALSE);
if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
return (FALSE);
return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
default:
return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
}
}
bool_t
xdr_MKNOD3args(XDR *xdrs, MKNOD3args *objp)
{
mknoddata3 *whatp;
devicedata3 *nod_objp;
if (!xdr_diropargs3(xdrs, &objp->where))
return (FALSE);
whatp = &objp->what;
if (!xdr_enum(xdrs, (enum_t *)&whatp->type))
return (FALSE);
switch (whatp->type) {
case NF3CHR:
case NF3BLK:
nod_objp = &whatp->mknoddata3_u.device;
if (!xdr_sattr3(xdrs, &nod_objp->dev_attributes))
return (FALSE);
if (!xdr_u_int(xdrs, &nod_objp->spec.specdata1))
return (FALSE);
return (xdr_u_int(xdrs, &nod_objp->spec.specdata2));
case NF3SOCK:
case NF3FIFO:
return (xdr_sattr3(xdrs, &whatp->mknoddata3_u.pipe_attributes));
default:
break;
}
return (TRUE);
}
bool_t
xdr_MKNOD3res(XDR *xdrs, MKNOD3res *objp)
{
MKNOD3resok *resokp;
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
switch (objp->status) {
case NFS3_OK:
resokp = &objp->resok;
if (!xdr_post_op_fh3(xdrs, &resokp->obj))
return (FALSE);
if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
return (FALSE);
return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
default:
return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
}
}
bool_t
xdr_REMOVE3res(XDR *xdrs, REMOVE3res *objp)
{
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
switch (objp->status) {
case NFS3_OK:
return (xdr_wcc_data(xdrs, &objp->resok.dir_wcc));
default:
return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
}
}
bool_t
xdr_RMDIR3res(XDR *xdrs, RMDIR3res *objp)
{
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
switch (objp->status) {
case NFS3_OK:
return (xdr_wcc_data(xdrs, &objp->resok.dir_wcc));
default:
return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
}
}
bool_t
xdr_RENAME3args(XDR *xdrs, RENAME3args *objp)
{
if (!xdr_diropargs3(xdrs, &objp->from))
return (FALSE);
return (xdr_diropargs3(xdrs, &objp->to));
}
bool_t
xdr_RENAME3res(XDR *xdrs, RENAME3res *objp)
{
RENAME3resok *resokp;
RENAME3resfail *resfailp;
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
switch (objp->status) {
case NFS3_OK:
resokp = &objp->resok;
if (!xdr_wcc_data(xdrs, &resokp->fromdir_wcc))
return (FALSE);
return (xdr_wcc_data(xdrs, &resokp->todir_wcc));
default:
resfailp = &objp->resfail;
if (!xdr_wcc_data(xdrs, &resfailp->fromdir_wcc))
return (FALSE);
return (xdr_wcc_data(xdrs, &resfailp->todir_wcc));
}
}
bool_t
xdr_LINK3args(XDR *xdrs, LINK3args *objp)
{
switch (xdrs->x_op) {
case XDR_FREE:
case XDR_ENCODE:
if (!xdr_nfs_fh3(xdrs, &objp->file))
return (FALSE);
break;
case XDR_DECODE:
if (!xdr_nfs_fh3_server(xdrs, &objp->file))
return (FALSE);
break;
}
return (xdr_diropargs3(xdrs, &objp->link));
}
bool_t
xdr_LINK3res(XDR *xdrs, LINK3res *objp)
{
LINK3resok *resokp;
LINK3resfail *resfailp;
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
switch (objp->status) {
case NFS3_OK:
resokp = &objp->resok;
if (!xdr_post_op_attr(xdrs, &resokp->file_attributes))
return (FALSE);
return (xdr_wcc_data(xdrs, &resokp->linkdir_wcc));
default:
resfailp = &objp->resfail;
if (!xdr_post_op_attr(xdrs, &resfailp->file_attributes))
return (FALSE);
return (xdr_wcc_data(xdrs, &resfailp->linkdir_wcc));
}
}
bool_t
xdr_READDIR3args(XDR *xdrs, READDIR3args *objp)
{
rdma_chunkinfo_t rci;
struct xdr_ops *xops = xdrrdma_xops();
if (xdrs->x_op == XDR_FREE)
return (TRUE);
switch (xdrs->x_op) {
case XDR_FREE:
case XDR_ENCODE:
if (!xdr_nfs_fh3(xdrs, &objp->dir))
return (FALSE);
break;
case XDR_DECODE:
if (!xdr_nfs_fh3_server(xdrs, &objp->dir))
return (FALSE);
break;
}
if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
xdrs->x_op == XDR_ENCODE) {
rci.rci_type = RCI_REPLY_CHUNK;
rci.rci_len = objp->count;
XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
}
if (!xdr_u_longlong_t(xdrs, &objp->cookie))
return (FALSE);
if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
return (FALSE);
return (xdr_u_int(xdrs, &objp->count));
}
#ifdef nextdp
#undef nextdp
#endif
#define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
#ifdef roundup
#undef roundup
#endif
#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
static bool_t
xdr_putdirlist(XDR *xdrs, READDIR3resok *objp)
{
struct dirent64 *dp;
char *name;
int size;
int bufsize;
uint_t namlen;
bool_t true = TRUE;
bool_t false = FALSE;
int entrysz;
int tofit;
fileid3 fileid;
cookie3 cookie;
if (xdrs->x_op != XDR_ENCODE)
return (FALSE);
bufsize = (1 + 1 + 2) * BYTES_PER_XDR_UNIT;
if (objp->dir_attributes.attributes)
bufsize += NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
for (size = objp->size, dp = (struct dirent64 *)objp->reply.entries;
size > 0;
size -= dp->d_reclen, dp = nextdp(dp)) {
if (dp->d_reclen == 0)
return (FALSE);
if (dp->d_ino == 0)
continue;
name = dp->d_name;
namlen = (uint_t)strlen(dp->d_name);
entrysz = (1 + 2 + 1 + 2) * BYTES_PER_XDR_UNIT +
roundup(namlen, BYTES_PER_XDR_UNIT);
tofit = entrysz + (1 + 1) * BYTES_PER_XDR_UNIT;
if (bufsize + tofit > objp->count) {
objp->reply.eof = FALSE;
break;
}
fileid = (fileid3)(dp->d_ino);
cookie = (cookie3)(dp->d_off);
if (!xdr_bool(xdrs, &true) ||
!xdr_u_longlong_t(xdrs, &fileid) ||
!xdr_bytes(xdrs, &name, &namlen, ~0) ||
!xdr_u_longlong_t(xdrs, &cookie)) {
return (FALSE);
}
bufsize += entrysz;
}
if (!xdr_bool(xdrs, &false))
return (FALSE);
if (!xdr_bool(xdrs, &objp->reply.eof))
return (FALSE);
return (TRUE);
}
bool_t
xdr_READDIR3res(XDR *xdrs, READDIR3res *objp)
{
READDIR3resok *resokp;
if (xdrs->x_op == XDR_DECODE)
return (FALSE);
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
if (objp->status != NFS3_OK)
return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes));
resokp = &objp->resok;
if (!xdr_post_op_attr(xdrs, &resokp->dir_attributes))
return (FALSE);
if (xdrs->x_op != XDR_ENCODE)
return (TRUE);
if (!xdr_u_longlong_t(xdrs, &resokp->cookieverf))
return (FALSE);
return (xdr_putdirlist(xdrs, resokp));
}
bool_t
xdr_READDIR3vres(XDR *xdrs, READDIR3vres *objp)
{
dirent64_t *dp;
uint_t entries_size;
int outcount = 0;
if (xdrs->x_op == XDR_FREE)
return (TRUE);
if (xdrs->x_op != XDR_DECODE)
return (FALSE);
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
if (!xdr_post_op_vattr(xdrs, &objp->dir_attributes))
return (FALSE);
if (objp->status != NFS3_OK)
return (TRUE);
if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
return (FALSE);
entries_size = objp->entries_size;
dp = objp->entries;
for (;;) {
uint_t this_reclen;
bool_t valid;
uint_t namlen;
ino64_t fileid;
if (!XDR_GETINT32(xdrs, (int32_t *)&valid))
return (FALSE);
if (!valid) {
if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof))
return (FALSE);
break;
}
if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&fileid))
return (FALSE);
if (!XDR_GETINT32(xdrs, (int32_t *)&namlen))
return (FALSE);
this_reclen = DIRENT64_RECLEN(namlen);
if ((outcount + this_reclen) > entries_size) {
objp->eof = FALSE;
break;
}
dp->d_reclen = this_reclen;
dp->d_ino = fileid;
if (!xdr_opaque(xdrs, dp->d_name, namlen))
return (FALSE);
bzero(&dp->d_name[namlen],
DIRENT64_NAMELEN(this_reclen) - namlen);
if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&dp->d_off))
return (FALSE);
objp->loff = dp->d_off;
outcount += this_reclen;
dp = (dirent64_t *)((intptr_t)dp + this_reclen);
}
objp->size = outcount;
return (TRUE);
}
bool_t
xdr_READDIRPLUS3args(XDR *xdrs, READDIRPLUS3args *objp)
{
rdma_chunkinfo_t rci;
struct xdr_ops *xops = xdrrdma_xops();
if (xdrs->x_op == XDR_FREE)
return (TRUE);
switch (xdrs->x_op) {
case XDR_FREE:
case XDR_ENCODE:
if (!xdr_nfs_fh3(xdrs, &objp->dir))
return (FALSE);
break;
case XDR_DECODE:
if (!xdr_nfs_fh3_server(xdrs, &objp->dir))
return (FALSE);
break;
}
if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
xdrs->x_op == XDR_ENCODE) {
rci.rci_type = RCI_REPLY_CHUNK;
rci.rci_len = objp->maxcount;
XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
}
if (!xdr_u_longlong_t(xdrs, &objp->cookie))
return (FALSE);
if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
return (FALSE);
if (!xdr_u_int(xdrs, &objp->dircount))
return (FALSE);
return (xdr_u_int(xdrs, &objp->maxcount));
}
static bool_t
xdr_putdirpluslist(XDR *xdrs, READDIRPLUS3resok *objp)
{
struct dirent64 *dp;
char *name;
int nents;
bool_t true = TRUE;
bool_t false = FALSE;
fileid3 fileid;
cookie3 cookie;
entryplus3_info *infop;
if (xdrs->x_op != XDR_ENCODE)
return (FALSE);
dp = (struct dirent64 *)objp->reply.entries;
nents = objp->size;
infop = objp->infop;
while (nents > 0) {
if (dp->d_reclen == 0)
return (FALSE);
if (dp->d_ino != 0) {
name = dp->d_name;
fileid = (fileid3)(dp->d_ino);
cookie = (cookie3)(dp->d_off);
if (!xdr_bool(xdrs, &true) ||
!xdr_u_longlong_t(xdrs, &fileid) ||
!xdr_bytes(xdrs, &name, &infop->namelen, ~0) ||
!xdr_u_longlong_t(xdrs, &cookie) ||
!xdr_post_op_attr(xdrs, &infop->attr) ||
!xdr_post_op_fh3(xdrs, &infop->fh)) {
return (FALSE);
}
}
dp = nextdp(dp);
infop++;
nents--;
}
if (!xdr_bool(xdrs, &false))
return (FALSE);
if (!xdr_bool(xdrs, &objp->reply.eof))
return (FALSE);
return (TRUE);
}
bool_t
xdr_READDIRPLUS3res(XDR *xdrs, READDIRPLUS3res *objp)
{
READDIRPLUS3resok *resokp;
if (xdrs->x_op == XDR_DECODE)
return (FALSE);
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
switch (objp->status) {
case NFS3_OK:
resokp = &objp->resok;
if (!xdr_post_op_attr(xdrs, &resokp->dir_attributes))
return (FALSE);
if (!xdr_u_longlong_t(xdrs, &resokp->cookieverf))
return (FALSE);
if (xdrs->x_op == XDR_ENCODE) {
if (!xdr_putdirpluslist(xdrs, resokp))
return (FALSE);
}
break;
default:
return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes));
}
return (TRUE);
}
bool_t
xdr_READDIRPLUS3vres(XDR *xdrs, READDIRPLUS3vres *objp)
{
dirent64_t *dp;
vnode_t *dvp;
uint_t entries_size;
int outcount = 0;
vnode_t *nvp;
rnode_t *rp;
post_op_vattr pov;
vattr_t va;
if (xdrs->x_op == XDR_FREE)
return (TRUE);
if (xdrs->x_op != XDR_DECODE)
return (FALSE);
if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status))
return (FALSE);
if (!xdr_post_op_vattr(xdrs, &objp->dir_attributes))
return (FALSE);
if (objp->status != NFS3_OK)
return (TRUE);
if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
return (FALSE);
dvp = objp->dir_attributes.fres.vp;
rp = VTOR(dvp);
pov.fres.vap = &va;
pov.fres.vp = dvp;
entries_size = objp->entries_size;
dp = objp->entries;
for (;;) {
uint_t this_reclen;
bool_t valid;
uint_t namlen;
nfs_fh3 fh;
int va_valid;
int fh_valid;
ino64_t fileid;
if (!XDR_GETINT32(xdrs, (int32_t *)&valid))
return (FALSE);
if (!valid) {
if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof))
return (FALSE);
break;
}
if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&fileid))
return (FALSE);
if (!XDR_GETINT32(xdrs, (int32_t *)&namlen))
return (FALSE);
this_reclen = DIRENT64_RECLEN(namlen);
if ((outcount + this_reclen) > entries_size) {
objp->eof = FALSE;
break;
}
dp->d_reclen = this_reclen;
dp->d_ino = fileid;
if (!xdr_opaque(xdrs, dp->d_name, namlen))
return (FALSE);
bzero(&dp->d_name[namlen],
DIRENT64_NAMELEN(this_reclen) - namlen);
if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&dp->d_off))
return (FALSE);
objp->loff = dp->d_off;
if (!xdr_post_op_vattr(xdrs, &pov))
return (FALSE);
if (pov.attributes == TRUE &&
pov.fres.status == NFS3_OK)
va_valid = TRUE;
else
va_valid = FALSE;
if (!XDR_GETINT32(xdrs, (int32_t *)&fh_valid))
return (FALSE);
if (fh_valid == TRUE) {
if (!xdr_nfs_fh3(xdrs, &fh))
return (FALSE);
} else {
if (fh_valid != FALSE)
return (FALSE);
}
if (!(namlen == 1 && dp->d_name[0] == '.') &&
va_valid && fh_valid) {
nvp = makenfs3node_va(&fh, &va, dvp->v_vfsp,
objp->time, objp->credentials,
rp->r_path, dp->d_name);
dnlc_update(dvp, dp->d_name, nvp);
VN_RELE(nvp);
}
outcount += this_reclen;
dp = (dirent64_t *)((intptr_t)dp + this_reclen);
}
objp->size = outcount;
return (TRUE);
}
bool_t
xdr_FSSTAT3res(XDR *xdrs, FSSTAT3res *objp)
{
FSSTAT3resok *resokp;
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
if (objp->status != NFS3_OK)
return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
resokp = &objp->resok;
if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
return (FALSE);
if (!xdr_u_longlong_t(xdrs, &resokp->tbytes))
return (FALSE);
if (!xdr_u_longlong_t(xdrs, &resokp->fbytes))
return (FALSE);
if (!xdr_u_longlong_t(xdrs, &resokp->abytes))
return (FALSE);
if (!xdr_u_longlong_t(xdrs, &resokp->tfiles))
return (FALSE);
if (!xdr_u_longlong_t(xdrs, &resokp->ffiles))
return (FALSE);
if (!xdr_u_longlong_t(xdrs, &resokp->afiles))
return (FALSE);
return (xdr_u_int(xdrs, &resokp->invarsec));
}
bool_t
xdr_FSINFO3res(XDR *xdrs, FSINFO3res *objp)
{
FSINFO3resok *resokp;
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
if (objp->status != NFS3_OK)
return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
resokp = &objp->resok;
if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
return (FALSE);
if (!xdr_u_int(xdrs, &resokp->rtmax))
return (FALSE);
if (!xdr_u_int(xdrs, &resokp->rtpref))
return (FALSE);
if (!xdr_u_int(xdrs, &resokp->rtmult))
return (FALSE);
if (!xdr_u_int(xdrs, &resokp->wtmax))
return (FALSE);
if (!xdr_u_int(xdrs, &resokp->wtpref))
return (FALSE);
if (!xdr_u_int(xdrs, &resokp->wtmult))
return (FALSE);
if (!xdr_u_int(xdrs, &resokp->dtpref))
return (FALSE);
if (!xdr_u_longlong_t(xdrs, &resokp->maxfilesize))
return (FALSE);
if (!xdr_u_int(xdrs, &resokp->time_delta.seconds))
return (FALSE);
if (!xdr_u_int(xdrs, &resokp->time_delta.nseconds))
return (FALSE);
return (xdr_u_int(xdrs, &resokp->properties));
}
bool_t
xdr_PATHCONF3res(XDR *xdrs, PATHCONF3res *objp)
{
PATHCONF3resok *resokp;
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
if (objp->status != NFS3_OK)
return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
resokp = &objp->resok;
if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
return (FALSE);
if (!xdr_u_int(xdrs, &resokp->info.link_max))
return (FALSE);
if (!xdr_u_int(xdrs, &resokp->info.name_max))
return (FALSE);
if (!xdr_bool(xdrs, &resokp->info.no_trunc))
return (FALSE);
if (!xdr_bool(xdrs, &resokp->info.chown_restricted))
return (FALSE);
if (!xdr_bool(xdrs, &resokp->info.case_insensitive))
return (FALSE);
return (xdr_bool(xdrs, &resokp->info.case_preserving));
}
bool_t
xdr_COMMIT3args(XDR *xdrs, COMMIT3args *objp)
{
if (xdrs->x_op == XDR_FREE)
return (TRUE);
switch (xdrs->x_op) {
case XDR_FREE:
case XDR_ENCODE:
if (!xdr_nfs_fh3(xdrs, &objp->file))
return (FALSE);
break;
case XDR_DECODE:
if (!xdr_nfs_fh3_server(xdrs, &objp->file))
return (FALSE);
break;
}
if (!xdr_u_longlong_t(xdrs, &objp->offset))
return (FALSE);
return (xdr_u_int(xdrs, &objp->count));
}
bool_t
xdr_COMMIT3res(XDR *xdrs, COMMIT3res *objp)
{
COMMIT3resok *resokp;
if (!xdr_enum(xdrs, (enum_t *)&objp->status))
return (FALSE);
if (objp->status != NFS3_OK)
return (xdr_wcc_data(xdrs, &objp->resfail.file_wcc));
resokp = &objp->resok;
if (!xdr_wcc_data(xdrs, &resokp->file_wcc))
return (FALSE);
return (xdr_u_longlong_t(xdrs, &resokp->verf));
}