nfs4_xdr.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/salib.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/rpc.h>
#include <rpcsvc/nfs4_prot.h>
#include "nfs_inet.h"
#define dprintf if (boothowto & RB_DEBUG) printf
/*
* XDR routines for NFSv4 ops.
*/
static bool_t
xdr_b_utf8string(XDR *xdrs, utf8string *objp)
{
return (xdr_bytes(xdrs, (char **)&objp->utf8string_val,
(uint_t *)&objp->utf8string_len, NFS4_MAX_UTF8STRING));
}
static bool_t
xdr_nfs_bfh4(XDR *xdrs, struct nfs_bfh4 *objp)
{
char *data = (char *)&objp->data;
return (xdr_bytes(xdrs, (char **)&data, (uint_t *)&objp->len,
NFS4_FHSIZE));
}
static bool_t
xdr_b_putfh4_args(XDR *xdrs, putfh4arg_t *objp)
{
if (!xdr_u_int(xdrs, (uint_t *)&objp->pf_opnum))
return (FALSE);
return (xdr_nfs_bfh4(xdrs, (struct nfs_bfh4 *)&objp->pf_filehandle));
}
/*
* Common xdr routines for compound. Let the specific op routines handle
* op specific portions of the compound.
*/
static bool_t
xdr_b_compound_args(XDR *xdrs, b_compound_t *objp)
{
if (!xdr_b_utf8string(xdrs, &objp->ca_tag)) {
return (FALSE);
}
if (!xdr_u_int(xdrs, &objp->ca_minorversion))
return (FALSE);
if (!xdr_u_int(xdrs, &objp->ca_argarray_len))
return (FALSE);
if (objp->ca_isputrootfh)
return (xdr_u_int(xdrs, &objp->ca_opputfh.pf_opnum));
return (xdr_b_putfh4_args(xdrs, &objp->ca_opputfh));
}
static bool_t
xdr_b_compound_res(XDR *xdrs, b_compound_t *objp)
{
if (!xdr_enum(xdrs, (enum_t *)&objp->cr_status))
return (FALSE);
if (!xdr_b_utf8string(xdrs, &objp->cr_tag))
return (FALSE);
if (!xdr_u_int(xdrs, &objp->cr_resarray_len))
return (FALSE);
if (!xdr_u_int(xdrs, &objp->cr_opputfh))
return (FALSE);
return (xdr_enum(xdrs, (enum_t *)&objp->cr_putfh_status));
}
static bool_t
xdr_b_bitmap4(XDR *xdrs, b_bitmap4_t *objp)
{
char *arp = (char *)&objp->b_bitmap_val;
return (xdr_array(xdrs, (char **)&arp,
(uint_t *)&objp->b_bitmap_len, ~0,
sizeof (uint_t), (xdrproc_t)xdr_u_int));
}
static bool_t
xdr_b_stateid4(XDR *xdrs, stateid4 *objp)
{
if (!xdr_u_int(xdrs, (uint_t *)&objp->seqid))
return (FALSE);
return (xdr_opaque(xdrs, objp->other, 12));
}
bool_t
xdr_getattr4_args(XDR *xdrs, getattr4arg_t *objp)
{
if (!xdr_b_compound_args(xdrs, (b_compound_t *)&objp->ga_arg))
return (FALSE);
if (!xdr_u_int(xdrs, (uint_t *)&objp->ga_opgetattr))
return (FALSE);
return (xdr_b_bitmap4(xdrs, (b_bitmap4_t *)&objp->ga_attr_req));
}
static bool_t
xdr_b_getattr_res_common(XDR *xdrs, getattrres_cmn_t *objp)
{
if (!xdr_u_int(xdrs, (uint_t *)&objp->gc_opgetattr))
return (FALSE);
if (!xdr_enum(xdrs, (enum_t *)&objp->gc_attr_status))
return (FALSE);
/*
* If the getattr suceeded, proceed and begin to decode the attributes.
*/
if (objp->gc_attr_status == NFS4_OK) {
char attrvals[sizeof (b_fattr4_t)];
char *ap = attrvals;
if (!xdr_b_bitmap4(xdrs, (b_bitmap4_t *)&objp->gc_retattr))
return (FALSE);
bzero(&attrvals, sizeof (attrvals));
if (!xdr_bytes(xdrs, (char **)&ap,
(uint_t *)&objp->gc_attrlist_len,
sizeof (b_fattr4_t)))
return (FALSE);
#ifdef DEBUG
printf("xdr_b_getattr_res_common: attrlist_len = %d\n",
objp->gc_attrlist_len);
#endif
/*
* Go through the bitmap and see if the server
* sent us anything.
*/
if (objp->gc_attrlist_len > 0) {
XDR mxdrs;
b_fattr4_t *fattrp = &objp->gc_attrs;
attr4_bitmap1_t bitmap1;
attr4_bitmap2_t bitmap2;
#ifdef DEBUG
int i;
printf("dumping contents of attr buffer\n");
for (i = 0; i < objp->gc_attrlist_len; i++) {
printf("[%d] = 0x%x\n", i, ap[i]);
}
#endif
bitmap1.word = objp->gc_retattr.b_bitmap_val[0];
bitmap2.word = objp->gc_retattr.b_bitmap_val[1];
#ifdef DEBUG
printf("xdr_b_getattr_res_common: bitmap1 = %d "
" bitmap2 = %d\n",
bitmap1.word, bitmap2.word);
#endif
xdrmem_create(&mxdrs, ap, objp->gc_attrlist_len,
XDR_DECODE);
/*
* Start with the first bitmap
*/
if (bitmap1.word > 0) {
if (bitmap1.bm_supported_attrs) {
if (!xdr_b_bitmap4(&mxdrs,
(b_bitmap4_t *)&fattrp->b_supported_attrs))
return (FALSE);
}
if (bitmap1.bm_fattr4_type) {
if (!xdr_enum(&mxdrs,
(enum_t *)&fattrp->b_fattr4_type)) {
return (FALSE);
}
}
if (bitmap1.bm_fattr4_size) {
if (!xdr_u_longlong_t(&mxdrs,
(u_longlong_t *)&fattrp->b_fattr4_size))
return (FALSE);
}
if (bitmap1.bm_fattr4_fsid) {
if (!xdr_u_longlong_t(&mxdrs,
(u_longlong_t *)&fattrp->b_fattr4_fsid.major))
return (FALSE);
if (!xdr_u_longlong_t(&mxdrs,
(u_longlong_t *)&fattrp->b_fattr4_fsid.minor))
return (FALSE);
}
if (bitmap1.bm_fattr4_filehandle) {
if (!xdr_nfs_bfh4(&mxdrs,
(struct nfs_bfh4 *)&fattrp->b_fattr4_filehandle))
return (FALSE);
}
if (bitmap1.bm_fattr4_fileid) {
if (!xdr_u_longlong_t(&mxdrs,
(u_longlong_t *)&fattrp->b_fattr4_fileid))
return (FALSE);
}
}
/*
* Now the second bitmap
*/
if (bitmap2.word > 0) {
if (bitmap2.bm_fattr4_mode) {
if (!xdr_u_int(&mxdrs,
(uint_t *)&objp->gc_attrs.b_fattr4_mode))
return (FALSE);
}
if (bitmap2.bm_fattr4_time_access) {
if (!xdr_longlong_t(&mxdrs,
(longlong_t *)&objp->gc_attrs.b_fattr4_time_access.seconds))
return (FALSE);
if (!xdr_u_int(&mxdrs,
(uint_t *)&objp->gc_attrs.b_fattr4_time_access.nseconds))
return (FALSE);
}
if (bitmap2.bm_fattr4_time_metadata) {
if (!xdr_longlong_t(&mxdrs,
(longlong_t *)&objp->gc_attrs.b_fattr4_time_metadata.seconds))
return (FALSE);
if (!xdr_u_int(&mxdrs,
(uint_t *)&objp->gc_attrs.b_fattr4_time_metadata.nseconds))
return (FALSE);
}
if (bitmap2.bm_fattr4_time_modify) {
if (!xdr_longlong_t(&mxdrs,
(longlong_t *)&objp->gc_attrs.b_fattr4_time_modify.seconds))
return (FALSE);
if (!xdr_u_int(&mxdrs,
(uint_t *)&objp->gc_attrs.b_fattr4_time_modify.nseconds))
return (FALSE);
}
}
}
}
return (TRUE);
}
bool_t
xdr_getattr4_res(XDR *xdrs, getattr4res_t *objp)
{
if (!xdr_b_compound_res(xdrs, (b_compound_t *)&objp->gr_res))
return (FALSE);
return (xdr_b_getattr_res_common(xdrs,
(getattrres_cmn_t *)&objp->gr_cmn));
}
bool_t
xdr_lookup4_args(XDR *xdrs, lookup4arg_t *objp)
{
if (!xdr_b_compound_args(xdrs, (b_compound_t *)&objp->la_arg))
return (FALSE);
if (!xdr_u_int(xdrs, (uint_t *)&objp->la_oplookup))
return (FALSE);
if (!xdr_b_utf8string(xdrs, (utf8string *)&objp->la_pathname))
return (FALSE);
if (!xdr_u_int(xdrs, (uint_t *)&objp->la_opgetattr))
return (FALSE);
return (xdr_b_bitmap4(xdrs, (b_bitmap4_t *)&objp->la_attr_req));
}
bool_t
xdr_lookup4_res(XDR *xdrs, lookup4res_t *objp)
{
if (!xdr_b_compound_res(xdrs, (b_compound_t *)&objp->lr_res))
return (FALSE);
if (!xdr_u_int(xdrs, (uint_t *)&objp->lr_oplookup))
return (FALSE);
if (!xdr_enum(xdrs, (enum_t *)&objp->lr_lookup_status))
return (FALSE);
if (objp->lr_lookup_status == NFS4_OK) {
return (xdr_b_getattr_res_common(xdrs,
(getattrres_cmn_t *)&objp->lr_gcmn));
}
return (TRUE);
}
bool_t
xdr_lookupp4_args(XDR *xdrs, lookupp4arg_t *objp)
{
if (!xdr_b_compound_args(xdrs, (b_compound_t *)&objp->la_arg))
return (FALSE);
if (!xdr_u_int(xdrs, (uint_t *)&objp->la_oplookupp))
return (FALSE);
if (!xdr_u_int(xdrs, (uint_t *)&objp->la_opgetattr))
return (FALSE);
return (xdr_b_bitmap4(xdrs, (b_bitmap4_t *)&objp->la_attr_req));
}
bool_t
xdr_read4_args(XDR *xdrs, read4arg_t *objp)
{
if (!xdr_b_compound_args(xdrs, (b_compound_t *)&objp->r_arg))
return (FALSE);
if (!xdr_u_int(xdrs, (uint_t *)&objp->r_opread))
return (FALSE);
if (!xdr_b_stateid4(xdrs, (stateid4 *)&objp->r_stateid))
return (FALSE);
if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->r_offset))
return (FALSE);
return (xdr_u_int(xdrs, (uint_t *)&objp->r_count));
}
bool_t
xdr_read4_res(XDR *xdrs, read4res_t *objp)
{
if (!xdr_b_compound_res(xdrs, (b_compound_t *)&objp->r_res))
return (FALSE);
if (!xdr_u_int(xdrs, (uint_t *)&objp->r_opread))
return (FALSE);
if (!xdr_enum(xdrs, (enum_t *)&objp->r_status))
return (FALSE);
if (objp->r_status == NFS4_OK) {
if (!xdr_bool(xdrs, (bool_t *)&objp->r_eof))
return (FALSE);
return (xdr_bytes(xdrs, (char **)&objp->r_data_val,
(uint_t *)&objp->r_data_len, ~0));
}
return (TRUE);
}
bool_t
xdr_readdir4_args(XDR *xdrs, readdir4arg_t *objp)
{
if (!xdr_b_compound_args(xdrs, (b_compound_t *)&objp->rd_arg))
return (FALSE);
if (!xdr_u_int(xdrs, (uint_t *)&objp->rd_opreaddir))
return (FALSE);
if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->rd_cookie))
return (FALSE);
if (!xdr_opaque(xdrs, objp->rd_cookieverf, NFS4_VERIFIER_SIZE))
return (FALSE);
if (!xdr_u_int(xdrs, (uint_t *)&objp->rd_dircount))
return (FALSE);
if (!xdr_u_int(xdrs, (uint_t *)&objp->rd_maxcount))
return (FALSE);
return (xdr_b_bitmap4(xdrs, (b_bitmap4_t *)&objp->rd_attr_req));
}
static bool_t
xdr_b_entry4(XDR *xdrs, b_entry4_t *objp)
{
uint_t attrlen;
char attrvals[sizeof (b_fattr4_t)];
char *ap = attrvals;
XDR mxdrs;
if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->b_cookie))
return (FALSE);
if (!xdr_b_utf8string(xdrs, &objp->b_name))
return (FALSE);
bzero(&attrvals, sizeof (attrvals));
if (!xdr_bytes(xdrs, (char **)&ap, (uint_t *)&attrlen,
sizeof (b_fattr4_t)))
return (FALSE);
/*
* We are *only* interested in the fileid, so just extract that.
*/
if (attrlen < sizeof (uint64_t))
return (FALSE);
xdrmem_create(&mxdrs, ap, attrlen, XDR_DECODE);
if (!xdr_u_longlong_t(&mxdrs, (u_longlong_t *)&objp->b_fileid))
return (FALSE);
return (xdr_pointer(xdrs, (char **)&objp->b_nextentry,
sizeof (b_entry4_t), (xdrproc_t)xdr_b_entry4));
}
bool_t
xdr_readdir4_res(XDR *xdrs, readdir4res_t *objp)
{
if (!xdr_b_compound_res(xdrs, (b_compound_t *)&objp->rd_res))
return (FALSE);
if (!xdr_u_int(xdrs, (uint_t *)&objp->rd_opreaddir))
return (FALSE);
if (!xdr_enum(xdrs, (enum_t *)&objp->rd_status))
return (FALSE);
if (objp->rd_status == NFS4_OK) {
if (!xdr_opaque(xdrs, objp->rd_cookieverf, NFS4_VERIFIER_SIZE))
return (FALSE);
if (!xdr_pointer(xdrs, (char **)&objp->rd_entries,
sizeof (b_entry4_t), (xdrproc_t)xdr_b_entry4))
return (FALSE);
return (xdr_bool(xdrs, &objp->rd_eof));
}
return (TRUE);
}
bool_t
xdr_readlink4_args(XDR *xdrs, readlink4arg_t *objp)
{
if (!xdr_b_compound_args(xdrs, (b_compound_t *)&objp->rl_arg))
return (FALSE);
return (xdr_u_int(xdrs, (uint_t *)&objp->rl_opreadlink));
}
bool_t
xdr_readlink4_res(XDR *xdrs, readlink4res_t *objp)
{
if (!xdr_b_compound_res(xdrs, (b_compound_t *)&objp->rl_res))
return (FALSE);
if (!xdr_u_int(xdrs, (uint_t *)&objp->rl_opreadlink))
return (FALSE);
if (!xdr_enum(xdrs, (enum_t *)&objp->rl_status))
return (FALSE);
if (objp->rl_status == NFS4_OK)
return (xdr_b_utf8string(xdrs, (utf8string *)&objp->rl_link));
return (TRUE);
}