/*
 * rpc_prot.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.
 *
 * This set of routines implements the rpc message definition,
 * its serializer and some common rpc utility routines.
 * The routines are meant for various implementations of rpc -
 * they are NOT for the rpc client or rpc service implementations!
 * Because authentication stuff is easy and is part of rpc, the opaque
 * routines are also in this program.
 */

#include <sys/param.h>

#include <rpc/rpc.h>

/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */

/*
 * XDR an opaque authentication struct
 * (see auth.h)
 */
bool_t
xdr_opaque_auth (XDR *xdrs, struct opaque_auth *ap)
{

  if (xdr_enum (xdrs, &(ap->oa_flavor)))
    return xdr_bytes (xdrs, &ap->oa_base,
		      &ap->oa_length, MAX_AUTH_BYTES);
  return FALSE;
}
libc_hidden_nolink_sunrpc (xdr_opaque_auth, GLIBC_2_0)

/*
 * XDR a DES block
 */
bool_t
xdr_des_block (XDR *xdrs, des_block *blkp)
{
  return xdr_opaque (xdrs, (caddr_t) blkp, sizeof (des_block));
}
libc_hidden_nolink_sunrpc (xdr_des_block, GLIBC_2_0)

/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */

/*
 * XDR the MSG_ACCEPTED part of a reply message union
 */
bool_t
xdr_accepted_reply (XDR *xdrs, struct accepted_reply *ar)
{
  /* personalized union, rather than calling xdr_union */
  if (!xdr_opaque_auth (xdrs, &(ar->ar_verf)))
    return FALSE;
  if (!xdr_enum (xdrs, (enum_t *) & (ar->ar_stat)))
    return FALSE;
  switch (ar->ar_stat)
    {
    case SUCCESS:
      return ((*(ar->ar_results.proc)) (xdrs, ar->ar_results.where));
    case PROG_MISMATCH:
      if (!xdr_u_long (xdrs, &(ar->ar_vers.low)))
	return FALSE;
      return (xdr_u_long (xdrs, &(ar->ar_vers.high)));
    default:
      return TRUE;
    }
  return TRUE;		/* TRUE => open ended set of problems */
}
libc_hidden_nolink_sunrpc (xdr_accepted_reply, GLIBC_2_0)

/*
 * XDR the MSG_DENIED part of a reply message union
 */
bool_t
xdr_rejected_reply (XDR *xdrs, struct rejected_reply *rr)
{
  /* personalized union, rather than calling xdr_union */
  if (!xdr_enum (xdrs, (enum_t *) & (rr->rj_stat)))
    return FALSE;
  switch (rr->rj_stat)
    {
    case RPC_MISMATCH:
      if (!xdr_u_long (xdrs, &(rr->rj_vers.low)))
	return FALSE;
      return xdr_u_long (xdrs, &(rr->rj_vers.high));

    case AUTH_ERROR:
      return xdr_enum (xdrs, (enum_t *) & (rr->rj_why));
    }
  return FALSE;
}
libc_hidden_nolink_sunrpc (xdr_rejected_reply, GLIBC_2_0)

static const struct xdr_discrim reply_dscrm[3] =
{
  {(int) MSG_ACCEPTED, (xdrproc_t) xdr_accepted_reply},
  {(int) MSG_DENIED, (xdrproc_t) xdr_rejected_reply},
  {__dontcare__, NULL_xdrproc_t}};

/*
 * XDR a reply message
 */
bool_t
xdr_replymsg (xdrs, rmsg)
     XDR *xdrs;
     struct rpc_msg *rmsg;
{
  if (xdr_u_long (xdrs, &(rmsg->rm_xid)) &&
      xdr_enum (xdrs, (enum_t *) & (rmsg->rm_direction)) &&
      (rmsg->rm_direction == REPLY))
    return xdr_union (xdrs, (enum_t *) & (rmsg->rm_reply.rp_stat),
		      (caddr_t) & (rmsg->rm_reply.ru), reply_dscrm,
		      NULL_xdrproc_t);
  return FALSE;
}
libc_hidden_nolink_sunrpc (xdr_replymsg, GLIBC_2_0)


/*
 * Serializes the "static part" of a call message header.
 * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
 * The rm_xid is not really static, but the user can easily munge on the fly.
 */
bool_t
xdr_callhdr (xdrs, cmsg)
     XDR *xdrs;
     struct rpc_msg *cmsg;
{

  cmsg->rm_direction = CALL;
  cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
  if (
       (xdrs->x_op == XDR_ENCODE) &&
       xdr_u_long (xdrs, &(cmsg->rm_xid)) &&
       xdr_enum (xdrs, (enum_t *) & (cmsg->rm_direction)) &&
       xdr_u_long (xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
       xdr_u_long (xdrs, &(cmsg->rm_call.cb_prog)))
    return xdr_u_long (xdrs, &(cmsg->rm_call.cb_vers));
  return FALSE;
}
libc_hidden_nolink_sunrpc (xdr_callhdr, GLIBC_2_0)

/* ************************** Client utility routine ************* */

static void
accepted (enum accept_stat acpt_stat,
	  struct rpc_err *error)
{
  switch (acpt_stat)
    {

    case PROG_UNAVAIL:
      error->re_status = RPC_PROGUNAVAIL;
      return;

    case PROG_MISMATCH:
      error->re_status = RPC_PROGVERSMISMATCH;
      return;

    case PROC_UNAVAIL:
      error->re_status = RPC_PROCUNAVAIL;
      return;

    case GARBAGE_ARGS:
      error->re_status = RPC_CANTDECODEARGS;
      return;

    case SYSTEM_ERR:
      error->re_status = RPC_SYSTEMERROR;
      return;

    case SUCCESS:
      error->re_status = RPC_SUCCESS;
      return;
    }
  /* something's wrong, but we don't know what ... */
  error->re_status = RPC_FAILED;
  error->re_lb.s1 = (long) MSG_ACCEPTED;
  error->re_lb.s2 = (long) acpt_stat;
}

static void
rejected (enum reject_stat rjct_stat,
	  struct rpc_err *error)
{
  switch (rjct_stat)
    {
    case RPC_MISMATCH:
      error->re_status = RPC_VERSMISMATCH;
      return;
    case AUTH_ERROR:
      error->re_status = RPC_AUTHERROR;
      return;
    default:
      /* something's wrong, but we don't know what ... */
      error->re_status = RPC_FAILED;
      error->re_lb.s1 = (long) MSG_DENIED;
      error->re_lb.s2 = (long) rjct_stat;
      return;
    }
}

/*
 * given a reply message, fills in the error
 */
void
_seterr_reply (struct rpc_msg *msg,
	       struct rpc_err *error)
{
  /* optimized for normal, SUCCESSful case */
  switch (msg->rm_reply.rp_stat)
    {
    case MSG_ACCEPTED:
      if (msg->acpted_rply.ar_stat == SUCCESS)
	{
	  error->re_status = RPC_SUCCESS;
	  return;
	};
      accepted (msg->acpted_rply.ar_stat, error);
      break;

    case MSG_DENIED:
      rejected (msg->rjcted_rply.rj_stat, error);
      break;

    default:
      error->re_status = RPC_FAILED;
      error->re_lb.s1 = (long) (msg->rm_reply.rp_stat);
      break;
    }
  switch (error->re_status)
    {

    case RPC_VERSMISMATCH:
      error->re_vers.low = msg->rjcted_rply.rj_vers.low;
      error->re_vers.high = msg->rjcted_rply.rj_vers.high;
      break;

    case RPC_AUTHERROR:
      error->re_why = msg->rjcted_rply.rj_why;
      break;

    case RPC_PROGVERSMISMATCH:
      error->re_vers.low = msg->acpted_rply.ar_vers.low;
      error->re_vers.high = msg->acpted_rply.ar_vers.high;
      break;
    default:
      break;
    }
}
libc_hidden_nolink_sunrpc (_seterr_reply, GLIBC_2_0)
