(root)/
glibc-2.38/
sunrpc/
rpc_prot.c
       1  /*
       2   * rpc_prot.c
       3   *
       4   * Copyright (c) 2010, Oracle America, Inc.
       5   *
       6   * Redistribution and use in source and binary forms, with or without
       7   * modification, are permitted provided that the following conditions are
       8   * met:
       9   *
      10   *     * Redistributions of source code must retain the above copyright
      11   *       notice, this list of conditions and the following disclaimer.
      12   *     * Redistributions in binary form must reproduce the above
      13   *       copyright notice, this list of conditions and the following
      14   *       disclaimer in the documentation and/or other materials
      15   *       provided with the distribution.
      16   *     * Neither the name of the "Oracle America, Inc." nor the names of its
      17   *       contributors may be used to endorse or promote products derived
      18   *       from this software without specific prior written permission.
      19   *
      20   *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      21   *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      22   *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
      23   *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
      24   *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
      25   *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26   *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
      27   *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      28   *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      29   *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
      30   *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      31   *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      32   *
      33   * This set of routines implements the rpc message definition,
      34   * its serializer and some common rpc utility routines.
      35   * The routines are meant for various implementations of rpc -
      36   * they are NOT for the rpc client or rpc service implementations!
      37   * Because authentication stuff is easy and is part of rpc, the opaque
      38   * routines are also in this program.
      39   */
      40  
      41  #include <sys/param.h>
      42  #include <rpc/rpc.h>
      43  #include <shlib-compat.h>
      44  
      45  /* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
      46  
      47  /*
      48   * XDR an opaque authentication struct
      49   * (see auth.h)
      50   */
      51  bool_t
      52  xdr_opaque_auth (XDR *xdrs, struct opaque_auth *ap)
      53  {
      54  
      55    if (xdr_enum (xdrs, &(ap->oa_flavor)))
      56      return xdr_bytes (xdrs, &ap->oa_base,
      57  		      &ap->oa_length, MAX_AUTH_BYTES);
      58    return FALSE;
      59  }
      60  libc_hidden_nolink_sunrpc (xdr_opaque_auth, GLIBC_2_0)
      61  
      62  /*
      63   * XDR a DES block
      64   */
      65  bool_t
      66  xdr_des_block (XDR *xdrs, des_block *blkp)
      67  {
      68    return xdr_opaque (xdrs, (caddr_t) blkp, sizeof (des_block));
      69  }
      70  libc_hidden_nolink_sunrpc (xdr_des_block, GLIBC_2_0)
      71  
      72  /* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
      73  
      74  /*
      75   * XDR the MSG_ACCEPTED part of a reply message union
      76   */
      77  bool_t
      78  xdr_accepted_reply (XDR *xdrs, struct accepted_reply *ar)
      79  {
      80    /* personalized union, rather than calling xdr_union */
      81    if (!xdr_opaque_auth (xdrs, &(ar->ar_verf)))
      82      return FALSE;
      83    if (!xdr_enum (xdrs, (enum_t *) & (ar->ar_stat)))
      84      return FALSE;
      85    switch (ar->ar_stat)
      86      {
      87      case SUCCESS:
      88        return ((*(ar->ar_results.proc)) (xdrs, ar->ar_results.where));
      89      case PROG_MISMATCH:
      90        if (!xdr_u_long (xdrs, &(ar->ar_vers.low)))
      91  	return FALSE;
      92        return (xdr_u_long (xdrs, &(ar->ar_vers.high)));
      93      default:
      94        return TRUE;
      95      }
      96    return TRUE;		/* TRUE => open ended set of problems */
      97  }
      98  libc_hidden_nolink_sunrpc (xdr_accepted_reply, GLIBC_2_0)
      99  
     100  /*
     101   * XDR the MSG_DENIED part of a reply message union
     102   */
     103  bool_t
     104  xdr_rejected_reply (XDR *xdrs, struct rejected_reply *rr)
     105  {
     106    /* personalized union, rather than calling xdr_union */
     107    if (!xdr_enum (xdrs, (enum_t *) & (rr->rj_stat)))
     108      return FALSE;
     109    switch (rr->rj_stat)
     110      {
     111      case RPC_MISMATCH:
     112        if (!xdr_u_long (xdrs, &(rr->rj_vers.low)))
     113  	return FALSE;
     114        return xdr_u_long (xdrs, &(rr->rj_vers.high));
     115  
     116      case AUTH_ERROR:
     117        return xdr_enum (xdrs, (enum_t *) & (rr->rj_why));
     118      }
     119    return FALSE;
     120  }
     121  libc_hidden_nolink_sunrpc (xdr_rejected_reply, GLIBC_2_0)
     122  
     123  static const struct xdr_discrim reply_dscrm[3] =
     124  {
     125    {(int) MSG_ACCEPTED, (xdrproc_t) xdr_accepted_reply},
     126    {(int) MSG_DENIED, (xdrproc_t) xdr_rejected_reply},
     127    {__dontcare__, NULL_xdrproc_t}};
     128  
     129  /*
     130   * XDR a reply message
     131   */
     132  bool_t
     133  xdr_replymsg (XDR *xdrs, struct rpc_msg *rmsg)
     134  {
     135    if (xdr_u_long (xdrs, &(rmsg->rm_xid)) &&
     136        xdr_enum (xdrs, (enum_t *) & (rmsg->rm_direction)) &&
     137        (rmsg->rm_direction == REPLY))
     138      return xdr_union (xdrs, (enum_t *) & (rmsg->rm_reply.rp_stat),
     139  		      (caddr_t) & (rmsg->rm_reply.ru), reply_dscrm,
     140  		      NULL_xdrproc_t);
     141    return FALSE;
     142  }
     143  libc_hidden_nolink_sunrpc (xdr_replymsg, GLIBC_2_0)
     144  
     145  
     146  /*
     147   * Serializes the "static part" of a call message header.
     148   * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
     149   * The rm_xid is not really static, but the user can easily munge on the fly.
     150   */
     151  bool_t
     152  xdr_callhdr (XDR *xdrs, struct rpc_msg *cmsg)
     153  {
     154  
     155    cmsg->rm_direction = CALL;
     156    cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
     157    if (
     158         (xdrs->x_op == XDR_ENCODE) &&
     159         xdr_u_long (xdrs, &(cmsg->rm_xid)) &&
     160         xdr_enum (xdrs, (enum_t *) & (cmsg->rm_direction)) &&
     161         xdr_u_long (xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
     162         xdr_u_long (xdrs, &(cmsg->rm_call.cb_prog)))
     163      return xdr_u_long (xdrs, &(cmsg->rm_call.cb_vers));
     164    return FALSE;
     165  }
     166  libc_hidden_nolink_sunrpc (xdr_callhdr, GLIBC_2_0)
     167  
     168  /* ************************** Client utility routine ************* */
     169  
     170  static void
     171  accepted (enum accept_stat acpt_stat,
     172  	  struct rpc_err *error)
     173  {
     174    switch (acpt_stat)
     175      {
     176  
     177      case PROG_UNAVAIL:
     178        error->re_status = RPC_PROGUNAVAIL;
     179        return;
     180  
     181      case PROG_MISMATCH:
     182        error->re_status = RPC_PROGVERSMISMATCH;
     183        return;
     184  
     185      case PROC_UNAVAIL:
     186        error->re_status = RPC_PROCUNAVAIL;
     187        return;
     188  
     189      case GARBAGE_ARGS:
     190        error->re_status = RPC_CANTDECODEARGS;
     191        return;
     192  
     193      case SYSTEM_ERR:
     194        error->re_status = RPC_SYSTEMERROR;
     195        return;
     196  
     197      case SUCCESS:
     198        error->re_status = RPC_SUCCESS;
     199        return;
     200      }
     201    /* something's wrong, but we don't know what ... */
     202    error->re_status = RPC_FAILED;
     203    error->re_lb.s1 = (long) MSG_ACCEPTED;
     204    error->re_lb.s2 = (long) acpt_stat;
     205  }
     206  
     207  static void
     208  rejected (enum reject_stat rjct_stat,
     209  	  struct rpc_err *error)
     210  {
     211    switch (rjct_stat)
     212      {
     213      case RPC_MISMATCH:
     214        error->re_status = RPC_VERSMISMATCH;
     215        return;
     216      case AUTH_ERROR:
     217        error->re_status = RPC_AUTHERROR;
     218        return;
     219      default:
     220        /* something's wrong, but we don't know what ... */
     221        error->re_status = RPC_FAILED;
     222        error->re_lb.s1 = (long) MSG_DENIED;
     223        error->re_lb.s2 = (long) rjct_stat;
     224        return;
     225      }
     226  }
     227  
     228  /*
     229   * given a reply message, fills in the error
     230   */
     231  void
     232  _seterr_reply (struct rpc_msg *msg,
     233  	       struct rpc_err *error)
     234  {
     235    /* optimized for normal, SUCCESSful case */
     236    switch (msg->rm_reply.rp_stat)
     237      {
     238      case MSG_ACCEPTED:
     239        if (msg->acpted_rply.ar_stat == SUCCESS)
     240  	{
     241  	  error->re_status = RPC_SUCCESS;
     242  	  return;
     243  	};
     244        accepted (msg->acpted_rply.ar_stat, error);
     245        break;
     246  
     247      case MSG_DENIED:
     248        rejected (msg->rjcted_rply.rj_stat, error);
     249        break;
     250  
     251      default:
     252        error->re_status = RPC_FAILED;
     253        error->re_lb.s1 = (long) (msg->rm_reply.rp_stat);
     254        break;
     255      }
     256    switch (error->re_status)
     257      {
     258  
     259      case RPC_VERSMISMATCH:
     260        error->re_vers.low = msg->rjcted_rply.rj_vers.low;
     261        error->re_vers.high = msg->rjcted_rply.rj_vers.high;
     262        break;
     263  
     264      case RPC_AUTHERROR:
     265        error->re_why = msg->rjcted_rply.rj_why;
     266        break;
     267  
     268      case RPC_PROGVERSMISMATCH:
     269        error->re_vers.low = msg->acpted_rply.ar_vers.low;
     270        error->re_vers.high = msg->acpted_rply.ar_vers.high;
     271        break;
     272      default:
     273        break;
     274      }
     275  }
     276  libc_hidden_nolink_sunrpc (_seterr_reply, GLIBC_2_0)