/*
 * 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 (INTUSE(xdr_enum) (xdrs, &(ap->oa_flavor)))
    return INTUSE(xdr_bytes) (xdrs, &ap->oa_base,
		      &ap->oa_length, MAX_AUTH_BYTES);
  return FALSE;
}
INTDEF(xdr_opaque_auth)

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

/* * * * * * * * * * * * * * 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 (!INTUSE(xdr_opaque_auth) (xdrs, &(ar->ar_verf)))
    return FALSE;
  if (!INTUSE(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 (!INTUSE(xdr_u_long) (xdrs, &(ar->ar_vers.low)))
	return FALSE;
      return (INTUSE(xdr_u_long) (xdrs, &(ar->ar_vers.high)));
    default:
      return TRUE;
    }
  return TRUE;		/* TRUE => open ended set of problems */
}
INTDEF(xdr_accepted_reply)

/*
 * 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 (!INTUSE(xdr_enum) (xdrs, (enum_t *) & (rr->rj_stat)))
    return FALSE;
  switch (rr->rj_stat)
    {
    case RPC_MISMATCH:
      if (!INTUSE(xdr_u_long) (xdrs, &(rr->rj_vers.low)))
	return FALSE;
      return INTUSE(xdr_u_long) (xdrs, &(rr->rj_vers.high));

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

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

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


/*
 * 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) &&
       INTUSE(xdr_u_long) (xdrs, &(cmsg->rm_xid)) &&
       INTUSE(xdr_enum) (xdrs, (enum_t *) & (cmsg->rm_direction)) &&
       INTUSE(xdr_u_long) (xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
       INTUSE(xdr_u_long) (xdrs, &(cmsg->rm_call.cb_prog)))
    return INTUSE(xdr_u_long) (xdrs, &(cmsg->rm_call.cb_vers));
  return FALSE;
}
INTDEF(xdr_callhdr)

/* ************************** 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_VERSMISMATCH:
      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_def (_seterr_reply)
