(root)/
glibc-2.38/
sunrpc/
clnt_raw.c
       1  /*
       2   * clnt_raw.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   * Memory based rpc for simple testing and timing.
      34   * Interface to create an rpc client and server in the same process.
      35   * This lets us simulate rpc and get round trip overhead, without
      36   * any interference from the kernel.
      37   */
      38  
      39  #include <rpc/rpc.h>
      40  #include <rpc/svc.h>
      41  #include <rpc/xdr.h>
      42  #include <libintl.h>
      43  #include <shlib-compat.h>
      44  
      45  #define MCALL_MSG_SIZE 24
      46  
      47  /*
      48   * This is the "network" we will be moving stuff over.
      49   */
      50  struct clntraw_private_s
      51    {
      52      CLIENT client_object;
      53      XDR xdr_stream;
      54      char _raw_buf[UDPMSGSIZE];
      55      union
      56      {
      57        char msg[MCALL_MSG_SIZE];
      58        u_long rm_xid;
      59      } mashl_callmsg;
      60      u_int mcnt;
      61    };
      62  #define clntraw_private RPC_THREAD_VARIABLE(clntraw_private_s)
      63  
      64  static enum clnt_stat clntraw_call (CLIENT *, u_long, xdrproc_t, caddr_t,
      65  				    xdrproc_t, caddr_t, struct timeval);
      66  static void clntraw_abort (void);
      67  static void clntraw_geterr (CLIENT *, struct rpc_err *);
      68  static bool_t clntraw_freeres (CLIENT *, xdrproc_t, caddr_t);
      69  static bool_t clntraw_control (CLIENT *, int, char *);
      70  static void clntraw_destroy (CLIENT *);
      71  
      72  static const struct clnt_ops client_ops =
      73  {
      74    clntraw_call,
      75    clntraw_abort,
      76    clntraw_geterr,
      77    clntraw_freeres,
      78    clntraw_destroy,
      79    clntraw_control
      80  };
      81  
      82  /*
      83   * Create a client handle for memory based rpc.
      84   */
      85  CLIENT *
      86  clntraw_create (u_long prog, u_long vers)
      87  {
      88    struct clntraw_private_s *clp = clntraw_private;
      89    struct rpc_msg call_msg;
      90    XDR *xdrs;
      91    CLIENT *client;
      92  
      93    if (clp == 0)
      94      {
      95        clp = (struct clntraw_private_s *) calloc (1, sizeof (*clp));
      96        if (clp == 0)
      97  	return (0);
      98        clntraw_private = clp;
      99      }
     100    xdrs = &clp->xdr_stream;
     101    client = &clp->client_object;
     102    /*
     103     * pre-serialize the static part of the call msg and stash it away
     104     */
     105    call_msg.rm_direction = CALL;
     106    call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
     107    call_msg.rm_call.cb_prog = prog;
     108    call_msg.rm_call.cb_vers = vers;
     109    xdrmem_create (xdrs, clp->mashl_callmsg.msg, MCALL_MSG_SIZE, XDR_ENCODE);
     110    if (!xdr_callhdr (xdrs, &call_msg))
     111      {
     112        perror (_ ("clnt_raw.c: fatal header serialization error"));
     113      }
     114    clp->mcnt = XDR_GETPOS (xdrs);
     115    XDR_DESTROY (xdrs);
     116  
     117    /*
     118     * Set xdrmem for client/server shared buffer
     119     */
     120    xdrmem_create (xdrs, clp->_raw_buf, UDPMSGSIZE, XDR_FREE);
     121  
     122    /*
     123     * create client handle
     124     */
     125    client->cl_ops = (struct clnt_ops *) &client_ops;
     126    client->cl_auth = authnone_create ();
     127    return client;
     128  }
     129  libc_hidden_nolink_sunrpc (clntraw_create, GLIBC_2_0)
     130  
     131  static enum clnt_stat
     132  clntraw_call (CLIENT *h, u_long proc, xdrproc_t xargs, caddr_t argsp,
     133  	      xdrproc_t xresults, caddr_t resultsp, struct timeval timeout)
     134  {
     135    struct clntraw_private_s *clp = clntraw_private;
     136    XDR *xdrs = &clp->xdr_stream;
     137    struct rpc_msg msg;
     138    enum clnt_stat status;
     139    struct rpc_err error;
     140  
     141    if (clp == NULL)
     142      return RPC_FAILED;
     143  call_again:
     144    /*
     145     * send request
     146     */
     147    xdrs->x_op = XDR_ENCODE;
     148    XDR_SETPOS (xdrs, 0);
     149    /* Just checking the union definition to access rm_xid is correct.  */
     150    if (offsetof (struct rpc_msg, rm_xid) != 0)
     151      abort ();
     152    clp->mashl_callmsg.rm_xid++;
     153    if ((!XDR_PUTBYTES (xdrs, clp->mashl_callmsg.msg, clp->mcnt)) ||
     154        (!XDR_PUTLONG (xdrs, (long *) &proc)) ||
     155        (!AUTH_MARSHALL (h->cl_auth, xdrs)) ||
     156        (!(*xargs) (xdrs, argsp)))
     157      {
     158        return (RPC_CANTENCODEARGS);
     159      }
     160    (void) XDR_GETPOS (xdrs);	/* called just to cause overhead */
     161  
     162    /*
     163     * We have to call server input routine here because this is
     164     * all going on in one process. Yuk.
     165     */
     166    svc_getreq (1);
     167  
     168    /*
     169     * get results
     170     */
     171    xdrs->x_op = XDR_DECODE;
     172    XDR_SETPOS (xdrs, 0);
     173    msg.acpted_rply.ar_verf = _null_auth;
     174    msg.acpted_rply.ar_results.where = resultsp;
     175    msg.acpted_rply.ar_results.proc = xresults;
     176    if (!xdr_replymsg (xdrs, &msg))
     177      return RPC_CANTDECODERES;
     178    _seterr_reply (&msg, &error);
     179    status = error.re_status;
     180  
     181    if (status == RPC_SUCCESS)
     182      {
     183        if (!AUTH_VALIDATE (h->cl_auth, &msg.acpted_rply.ar_verf))
     184  	{
     185  	  status = RPC_AUTHERROR;
     186  	}
     187      }				/* end successful completion */
     188    else
     189      {
     190        if (AUTH_REFRESH (h->cl_auth))
     191  	goto call_again;
     192      }				/* end of unsuccessful completion */
     193  
     194    if (status == RPC_SUCCESS)
     195      {
     196        if (!AUTH_VALIDATE (h->cl_auth, &msg.acpted_rply.ar_verf))
     197  	{
     198  	  status = RPC_AUTHERROR;
     199  	}
     200        if (msg.acpted_rply.ar_verf.oa_base != NULL)
     201  	{
     202  	  xdrs->x_op = XDR_FREE;
     203  	  (void) xdr_opaque_auth (xdrs, &(msg.acpted_rply.ar_verf));
     204  	}
     205      }
     206  
     207    return status;
     208  }
     209  
     210  static void
     211  clntraw_geterr (CLIENT *cl, struct rpc_err *err)
     212  {
     213  }
     214  
     215  
     216  static bool_t
     217  clntraw_freeres (CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr)
     218  {
     219    struct clntraw_private_s *clp = clntraw_private;
     220    XDR *xdrs = &clp->xdr_stream;
     221    bool_t rval;
     222  
     223    if (clp == NULL)
     224      {
     225        rval = (bool_t) RPC_FAILED;
     226        return rval;
     227      }
     228    xdrs->x_op = XDR_FREE;
     229    return (*xdr_res) (xdrs, res_ptr);
     230  }
     231  
     232  static void
     233  clntraw_abort (void)
     234  {
     235  }
     236  
     237  static bool_t
     238  clntraw_control (CLIENT *cl, int i, char *c)
     239  {
     240    return FALSE;
     241  }
     242  
     243  static void
     244  clntraw_destroy (CLIENT *cl)
     245  {
     246  }