/*
 * rpc_callmsg.c
 *
 * Copyright (c) 2010, Oracle America, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials
 *       provided with the distribution.
 *     * Neither the name of the "Oracle America, Inc." nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <string.h>
#include <sys/param.h>
#include <rpc/rpc.h>

/*
 * XDR a call message
 */
bool_t
xdr_callmsg (XDR *xdrs, struct rpc_msg *cmsg)
{
  int32_t *buf;
  struct opaque_auth *oa;

  if (xdrs->x_op == XDR_ENCODE)
    {
      if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES)
	{
	  return (FALSE);
	}
      if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES)
	{
	  return (FALSE);
	}
      buf = XDR_INLINE (xdrs, 8 * BYTES_PER_XDR_UNIT
			+ RNDUP (cmsg->rm_call.cb_cred.oa_length)
			+ 2 * BYTES_PER_XDR_UNIT
			+ RNDUP (cmsg->rm_call.cb_verf.oa_length));
      if (buf != NULL)
	{
	  (void) IXDR_PUT_LONG (buf, cmsg->rm_xid);
	  (void) IXDR_PUT_ENUM (buf, cmsg->rm_direction);
	  if (cmsg->rm_direction != CALL)
	    return FALSE;
	  (void) IXDR_PUT_LONG (buf, cmsg->rm_call.cb_rpcvers);
	  if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION)
	    return FALSE;
	  (void) IXDR_PUT_LONG (buf, cmsg->rm_call.cb_prog);
	  (void) IXDR_PUT_LONG (buf, cmsg->rm_call.cb_vers);
	  (void) IXDR_PUT_LONG (buf, cmsg->rm_call.cb_proc);
	  oa = &cmsg->rm_call.cb_cred;
	  (void) IXDR_PUT_ENUM (buf, oa->oa_flavor);
	  (void) IXDR_PUT_INT32 (buf, oa->oa_length);
	  if (oa->oa_length)
	    {
	      memcpy ((caddr_t) buf, oa->oa_base, oa->oa_length);
	      buf = (int32_t *) ((char *) buf + RNDUP (oa->oa_length));
	    }
	  oa = &cmsg->rm_call.cb_verf;
	  (void) IXDR_PUT_ENUM (buf, oa->oa_flavor);
	  (void) IXDR_PUT_INT32 (buf, oa->oa_length);
	  if (oa->oa_length)
	    {
	      memcpy ((caddr_t) buf, oa->oa_base, oa->oa_length);
	      /* no real need....
		 buf = (long *) ((char *) buf + RNDUP(oa->oa_length));
	       */
	    }
	  return TRUE;
	}
    }
  if (xdrs->x_op == XDR_DECODE)
    {
      buf = XDR_INLINE (xdrs, 8 * BYTES_PER_XDR_UNIT);
      if (buf != NULL)
	{
	  cmsg->rm_xid = IXDR_GET_LONG (buf);
	  cmsg->rm_direction = IXDR_GET_ENUM (buf, enum msg_type);
	  if (cmsg->rm_direction != CALL)
	    {
	      return FALSE;
	    }
	  cmsg->rm_call.cb_rpcvers = IXDR_GET_LONG (buf);
	  if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION)
	    {
	      return FALSE;
	    }
	  cmsg->rm_call.cb_prog = IXDR_GET_LONG (buf);
	  cmsg->rm_call.cb_vers = IXDR_GET_LONG (buf);
	  cmsg->rm_call.cb_proc = IXDR_GET_LONG (buf);
	  oa = &cmsg->rm_call.cb_cred;
	  oa->oa_flavor = IXDR_GET_ENUM (buf, enum_t);
	  oa->oa_length = IXDR_GET_INT32 (buf);
	  if (oa->oa_length)
	    {
	      if (oa->oa_length > MAX_AUTH_BYTES)
		return FALSE;
	      if (oa->oa_base == NULL)
		{
		  oa->oa_base = (caddr_t)
		    mem_alloc (oa->oa_length);
		}
	      buf = XDR_INLINE (xdrs, RNDUP (oa->oa_length));
	      if (buf == NULL)
		{
		  if (INTUSE(xdr_opaque) (xdrs, oa->oa_base,
					  oa->oa_length) == FALSE)
		    return FALSE;
		}
	      else
		{
		  memcpy (oa->oa_base, (caddr_t) buf, oa->oa_length);
		  /* no real need....
		     buf = (long *) ((char *) buf
		     + RNDUP(oa->oa_length));
		   */
		}
	    }
	  oa = &cmsg->rm_call.cb_verf;
	  buf = XDR_INLINE (xdrs, 2 * BYTES_PER_XDR_UNIT);
	  if (buf == NULL)
	    {
	      if (INTUSE(xdr_enum) (xdrs, &oa->oa_flavor) == FALSE ||
		  INTUSE(xdr_u_int) (xdrs, &oa->oa_length) == FALSE)
		{
		  return FALSE;
		}
	    }
	  else
	    {
	      oa->oa_flavor = IXDR_GET_ENUM (buf, enum_t);
	      oa->oa_length = IXDR_GET_INT32 (buf);
	    }
	  if (oa->oa_length)
	    {
	      if (oa->oa_length > MAX_AUTH_BYTES)
		return FALSE;
	      if (oa->oa_base == NULL)
		{
		  oa->oa_base = (caddr_t)
		    mem_alloc (oa->oa_length);
		}
	      buf = XDR_INLINE (xdrs, RNDUP (oa->oa_length));
	      if (buf == NULL)
		{
		  if (INTUSE(xdr_opaque) (xdrs, oa->oa_base,
					  oa->oa_length) == FALSE)
		    return FALSE;
		}
	      else
		{
		  memcpy (oa->oa_base, (caddr_t) buf, oa->oa_length);
		  /* no real need...
		     buf = (long *) ((char *) buf
		     + RNDUP(oa->oa_length));
		   */
		}
	    }
	  return TRUE;
	}
    }
  if (
       INTUSE(xdr_u_long) (xdrs, &(cmsg->rm_xid)) &&
       INTUSE(xdr_enum) (xdrs, (enum_t *) & (cmsg->rm_direction)) &&
       (cmsg->rm_direction == CALL) &&
       INTUSE(xdr_u_long) (xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
       (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) &&
       INTUSE(xdr_u_long) (xdrs, &(cmsg->rm_call.cb_prog)) &&
       INTUSE(xdr_u_long) (xdrs, &(cmsg->rm_call.cb_vers)) &&
       INTUSE(xdr_u_long) (xdrs, &(cmsg->rm_call.cb_proc)) &&
       INTUSE(xdr_opaque_auth) (xdrs, &(cmsg->rm_call.cb_cred)))
    return INTUSE(xdr_opaque_auth) (xdrs, &(cmsg->rm_call.cb_verf));
  return FALSE;
}
INTDEF(xdr_callmsg)
