1  /*
       2   * svc_simple.c
       3   * Simplified front end to rpc.
       4   *
       5   * Copyright (c) 2010, Oracle America, Inc.
       6   *
       7   * Redistribution and use in source and binary forms, with or without
       8   * modification, are permitted provided that the following conditions are
       9   * met:
      10   *
      11   *     * Redistributions of source code must retain the above copyright
      12   *       notice, this list of conditions and the following disclaimer.
      13   *     * Redistributions in binary form must reproduce the above
      14   *       copyright notice, this list of conditions and the following
      15   *       disclaimer in the documentation and/or other materials
      16   *       provided with the distribution.
      17   *     * Neither the name of the "Oracle America, Inc." nor the names of its
      18   *       contributors may be used to endorse or promote products derived
      19   *       from this software without specific prior written permission.
      20   *
      21   *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      22   *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      23   *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
      24   *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
      25   *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
      26   *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      27   *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
      28   *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      29   *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      30   *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
      31   *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      32   *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      33   */
      34  
      35  #include <stdio.h>
      36  #include <string.h>
      37  #include <libintl.h>
      38  #include <unistd.h>
      39  #include <rpc/rpc.h>
      40  #include <rpc/pmap_clnt.h>
      41  #include <sys/socket.h>
      42  #include <netdb.h>
      43  
      44  #include <wchar.h>
      45  #include <libio/iolibio.h>
      46  #include <shlib-compat.h>
      47  
      48  struct proglst_
      49    {
      50      char *(*p_progname) (char *);
      51      int p_prognum;
      52      int p_procnum;
      53      xdrproc_t p_inproc, p_outproc;
      54      struct proglst_ *p_nxt;
      55    };
      56  #define proglst RPC_THREAD_VARIABLE(svcsimple_proglst_s)
      57  
      58  
      59  static void universal (struct svc_req *rqstp, SVCXPRT *transp_s);
      60  #define transp RPC_THREAD_VARIABLE(svcsimple_transp_s)
      61  
      62  int
      63  __registerrpc (u_long prognum, u_long versnum, u_long procnum,
      64  	       char *(*progname) (char *), xdrproc_t inproc, xdrproc_t outproc)
      65  {
      66    struct proglst_ *pl;
      67    char *buf;
      68  
      69    if (procnum == NULLPROC)
      70      {
      71  
      72        if (__asprintf (&buf, _("can't reassign procedure number %ld\n"),
      73  		      NULLPROC) < 0)
      74  	buf = NULL;
      75        goto err_out;
      76      }
      77    if (transp == 0)
      78      {
      79        transp = svcudp_create (RPC_ANYSOCK);
      80        if (transp == NULL)
      81  	{
      82  	  buf = __strdup (_("couldn't create an rpc server\n"));
      83  	  goto err_out;
      84  	}
      85      }
      86    (void) pmap_unset ((u_long) prognum, (u_long) versnum);
      87    if (!svc_register (transp, (u_long) prognum, (u_long) versnum,
      88  		     universal, IPPROTO_UDP))
      89      {
      90        if (__asprintf (&buf, _("couldn't register prog %ld vers %ld\n"),
      91  		      prognum, versnum) < 0)
      92  	buf = NULL;
      93        goto err_out;
      94      }
      95    pl = (struct proglst_ *) malloc (sizeof (struct proglst_));
      96    if (pl == NULL)
      97      {
      98        buf = __strdup (_("registerrpc: out of memory\n"));
      99        goto err_out;
     100      }
     101    pl->p_progname = progname;
     102    pl->p_prognum = prognum;
     103    pl->p_procnum = procnum;
     104    pl->p_inproc = inproc;
     105    pl->p_outproc = outproc;
     106    pl->p_nxt = proglst;
     107    proglst = pl;
     108    return 0;
     109  
     110   err_out:
     111    if (buf == NULL)
     112      return -1;
     113    (void) __fxprintf (NULL, "%s", buf);
     114    free (buf);
     115    return -1;
     116  }
     117  
     118  libc_sunrpc_symbol (__registerrpc, registerrpc, GLIBC_2_0)
     119  
     120  
     121  static void
     122  universal (struct svc_req *rqstp, SVCXPRT *transp_l)
     123  {
     124    int prog, proc;
     125    char *outdata;
     126    char xdrbuf[UDPMSGSIZE];
     127    struct proglst_ *pl;
     128    char *buf = NULL;
     129  
     130    /*
     131     * enforce "procnum 0 is echo" convention
     132     */
     133    if (rqstp->rq_proc == NULLPROC)
     134      {
     135        if (svc_sendreply (transp_l, (xdrproc_t)xdr_void,
     136  			 (char *) NULL) == FALSE)
     137  	{
     138  	  __write (STDERR_FILENO, "xxx\n", 4);
     139  	  exit (1);
     140  	}
     141        return;
     142      }
     143    prog = rqstp->rq_prog;
     144    proc = rqstp->rq_proc;
     145    for (pl = proglst; pl != NULL; pl = pl->p_nxt)
     146      if (pl->p_prognum == prog && pl->p_procnum == proc)
     147        {
     148  	/* decode arguments into a CLEAN buffer */
     149  	memset (xdrbuf, 0, sizeof (xdrbuf));	/* required ! */
     150  	if (!svc_getargs (transp_l, pl->p_inproc, xdrbuf))
     151  	  {
     152  	    svcerr_decode (transp_l);
     153  	    return;
     154  	  }
     155  	outdata = (*(pl->p_progname)) (xdrbuf);
     156  	if (outdata == NULL && pl->p_outproc != (xdrproc_t)xdr_void)
     157  	  /* there was an error */
     158  	  return;
     159  	if (!svc_sendreply (transp_l, pl->p_outproc, outdata))
     160  	  {
     161  	    if (__asprintf (&buf, _("trouble replying to prog %d\n"),
     162  			    pl->p_prognum) < 0)
     163  	      buf = NULL;
     164  	    goto err_out2;
     165  	  }
     166  	/* free the decoded arguments */
     167  	(void) svc_freeargs (transp_l, pl->p_inproc, xdrbuf);
     168  	return;
     169        }
     170    if (__asprintf (&buf, _("never registered prog %d\n"), prog) < 0)
     171      buf = NULL;
     172   err_out2:
     173    if (buf == NULL)
     174      exit (1);
     175    __fxprintf (NULL, "%s", buf);
     176    free (buf);
     177    exit (1);
     178  }