18360efbdSAlfred Perlstein /* $NetBSD: svc_simple.c,v 1.20 2000/07/06 03:10:35 christos Exp $ */ 28360efbdSAlfred Perlstein 32e322d37SHiroki Sato /*- 42e322d37SHiroki Sato * Copyright (c) 2009, Sun Microsystems, Inc. 52e322d37SHiroki Sato * All rights reserved. 699064799SGarrett Wollman * 72e322d37SHiroki Sato * Redistribution and use in source and binary forms, with or without 82e322d37SHiroki Sato * modification, are permitted provided that the following conditions are met: 92e322d37SHiroki Sato * - Redistributions of source code must retain the above copyright notice, 102e322d37SHiroki Sato * this list of conditions and the following disclaimer. 112e322d37SHiroki Sato * - Redistributions in binary form must reproduce the above copyright notice, 122e322d37SHiroki Sato * this list of conditions and the following disclaimer in the documentation 132e322d37SHiroki Sato * and/or other materials provided with the distribution. 142e322d37SHiroki Sato * - Neither the name of Sun Microsystems, Inc. nor the names of its 152e322d37SHiroki Sato * contributors may be used to endorse or promote products derived 162e322d37SHiroki Sato * from this software without specific prior written permission. 1799064799SGarrett Wollman * 182e322d37SHiroki Sato * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 192e322d37SHiroki Sato * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 202e322d37SHiroki Sato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 212e322d37SHiroki Sato * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 222e322d37SHiroki Sato * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 232e322d37SHiroki Sato * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 242e322d37SHiroki Sato * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 252e322d37SHiroki Sato * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 262e322d37SHiroki Sato * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 272e322d37SHiroki Sato * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 282e322d37SHiroki Sato * POSSIBILITY OF SUCH DAMAGE. 2999064799SGarrett Wollman */ 308360efbdSAlfred Perlstein /* 318360efbdSAlfred Perlstein * Copyright (c) 1986-1991 by Sun Microsystems Inc. 328360efbdSAlfred Perlstein */ 3399064799SGarrett Wollman 348360efbdSAlfred Perlstein /* #pragma ident "@(#)svc_simple.c 1.18 94/04/24 SMI" */ 35d3d20c82SDavid E. O'Brien #include <sys/cdefs.h> 36d3d20c82SDavid E. O'Brien __FBSDID("$FreeBSD$"); 3799064799SGarrett Wollman 3899064799SGarrett Wollman /* 3999064799SGarrett Wollman * svc_simple.c 4099064799SGarrett Wollman * Simplified front end to rpc. 4199064799SGarrett Wollman */ 4299064799SGarrett Wollman 438360efbdSAlfred Perlstein /* 448360efbdSAlfred Perlstein * This interface creates a virtual listener for all the services 4532223c1bSPedro F. Giffuni * started through rpc_reg(). It listens on the same endpoint for 468360efbdSAlfred Perlstein * all the services and then executes the corresponding service 478360efbdSAlfred Perlstein * for the given prognum and procnum. 488360efbdSAlfred Perlstein */ 498360efbdSAlfred Perlstein 508360efbdSAlfred Perlstein #include "namespace.h" 519f5afc13SIan Dowse #include "reentrant.h" 528360efbdSAlfred Perlstein #include <sys/types.h> 538360efbdSAlfred Perlstein #include <rpc/rpc.h> 548360efbdSAlfred Perlstein #include <rpc/nettype.h> 5599064799SGarrett Wollman #include <stdio.h> 564c3af266SPoul-Henning Kamp #include <stdlib.h> 574c3af266SPoul-Henning Kamp #include <string.h> 588360efbdSAlfred Perlstein #include <err.h> 598360efbdSAlfred Perlstein #include "un-namespace.h" 608360efbdSAlfred Perlstein 618360efbdSAlfred Perlstein #include "rpc_com.h" 62235baf26SDaniel Eischen #include "mt_misc.h" 638360efbdSAlfred Perlstein 64c05ac53bSDavid E. O'Brien static void universal(struct svc_req *, SVCXPRT *); 6599064799SGarrett Wollman 6699064799SGarrett Wollman static struct proglst { 67c05ac53bSDavid E. O'Brien char *(*p_progname)(char *); 688360efbdSAlfred Perlstein rpcprog_t p_prognum; 698360efbdSAlfred Perlstein rpcvers_t p_versnum; 708360efbdSAlfred Perlstein rpcproc_t p_procnum; 718360efbdSAlfred Perlstein SVCXPRT *p_transp; 728360efbdSAlfred Perlstein char *p_netid; 738360efbdSAlfred Perlstein char *p_xdrbuf; 748360efbdSAlfred Perlstein int p_recvsz; 7599064799SGarrett Wollman xdrproc_t p_inproc, p_outproc; 7699064799SGarrett Wollman struct proglst *p_nxt; 7799064799SGarrett Wollman } *proglst; 788360efbdSAlfred Perlstein 798360efbdSAlfred Perlstein static const char rpc_reg_err[] = "%s: %s"; 808360efbdSAlfred Perlstein static const char rpc_reg_msg[] = "rpc_reg: "; 818360efbdSAlfred Perlstein static const char __reg_err1[] = "can't find appropriate transport"; 828360efbdSAlfred Perlstein static const char __reg_err2[] = "can't get protocol info"; 838360efbdSAlfred Perlstein static const char __reg_err3[] = "unsupported transport size"; 848360efbdSAlfred Perlstein static const char __no_mem_str[] = "out of memory"; 858360efbdSAlfred Perlstein 868360efbdSAlfred Perlstein /* 878360efbdSAlfred Perlstein * For simplified, easy to use kind of rpc interfaces. 888360efbdSAlfred Perlstein * nettype indicates the type of transport on which the service will be 898360efbdSAlfred Perlstein * listening. Used for conservation of the system resource. Only one 908360efbdSAlfred Perlstein * handle is created for all the services (actually one of each netid) 918360efbdSAlfred Perlstein * and same xdrbuf is used for same netid. The size of the arguments 928360efbdSAlfred Perlstein * is also limited by the recvsize for that transport, even if it is 938360efbdSAlfred Perlstein * a COTS transport. This may be wrong, but for cases like these, they 948360efbdSAlfred Perlstein * should not use the simplified interfaces like this. 95587cf682SCraig Rodrigues * 96587cf682SCraig Rodrigues * prognum - program number 97587cf682SCraig Rodrigues * versnum - version number 98587cf682SCraig Rodrigues * procnum - procedure number 99587cf682SCraig Rodrigues * progname - Server routine 100587cf682SCraig Rodrigues * inproc, outproc - in/out XDR procedures 101587cf682SCraig Rodrigues * nettype - nettype 1028360efbdSAlfred Perlstein */ 10375a98e21SPeter Wemm int 104587cf682SCraig Rodrigues rpc_reg(rpcprog_t prognum, rpcvers_t versnum, rpcproc_t procnum, 105587cf682SCraig Rodrigues char *(*progname)(char *), xdrproc_t inproc, xdrproc_t outproc, 106587cf682SCraig Rodrigues char *nettype) 10799064799SGarrett Wollman { 1088360efbdSAlfred Perlstein struct netconfig *nconf; 1098360efbdSAlfred Perlstein int done = FALSE; 1108360efbdSAlfred Perlstein void *handle; 1118360efbdSAlfred Perlstein 11299064799SGarrett Wollman 11399064799SGarrett Wollman if (procnum == NULLPROC) { 1148360efbdSAlfred Perlstein warnx("%s can't reassign procedure number %u", rpc_reg_msg, 1158360efbdSAlfred Perlstein NULLPROC); 11699064799SGarrett Wollman return (-1); 11799064799SGarrett Wollman } 1188360efbdSAlfred Perlstein 1198360efbdSAlfred Perlstein if (nettype == NULL) 1208360efbdSAlfred Perlstein nettype = "netpath"; /* The default behavior */ 1218360efbdSAlfred Perlstein if ((handle = __rpc_setconf(nettype)) == NULL) { 1228360efbdSAlfred Perlstein warnx(rpc_reg_err, rpc_reg_msg, __reg_err1); 12399064799SGarrett Wollman return (-1); 12499064799SGarrett Wollman } 1258360efbdSAlfred Perlstein /* VARIABLES PROTECTED BY proglst_lock: proglst */ 1268360efbdSAlfred Perlstein mutex_lock(&proglst_lock); 1278360efbdSAlfred Perlstein while ((nconf = __rpc_getconf(handle)) != NULL) { 1288360efbdSAlfred Perlstein struct proglst *pl; 1298360efbdSAlfred Perlstein SVCXPRT *svcxprt; 1308360efbdSAlfred Perlstein int madenow; 1318360efbdSAlfred Perlstein u_int recvsz; 1328360efbdSAlfred Perlstein char *xdrbuf; 1338360efbdSAlfred Perlstein char *netid; 1348360efbdSAlfred Perlstein 1358360efbdSAlfred Perlstein madenow = FALSE; 1368360efbdSAlfred Perlstein svcxprt = NULL; 1378d630135SAlfred Perlstein recvsz = 0; 1388d630135SAlfred Perlstein xdrbuf = netid = NULL; 1398d630135SAlfred Perlstein for (pl = proglst; pl; pl = pl->p_nxt) { 1408360efbdSAlfred Perlstein if (strcmp(pl->p_netid, nconf->nc_netid) == 0) { 1418360efbdSAlfred Perlstein svcxprt = pl->p_transp; 1428360efbdSAlfred Perlstein xdrbuf = pl->p_xdrbuf; 1438360efbdSAlfred Perlstein recvsz = pl->p_recvsz; 1448360efbdSAlfred Perlstein netid = pl->p_netid; 1458360efbdSAlfred Perlstein break; 14699064799SGarrett Wollman } 1478d630135SAlfred Perlstein } 1488360efbdSAlfred Perlstein 1498360efbdSAlfred Perlstein if (svcxprt == NULL) { 1508360efbdSAlfred Perlstein struct __rpc_sockinfo si; 1518360efbdSAlfred Perlstein 1528360efbdSAlfred Perlstein svcxprt = svc_tli_create(RPC_ANYFD, nconf, NULL, 0, 0); 1538360efbdSAlfred Perlstein if (svcxprt == NULL) 1548360efbdSAlfred Perlstein continue; 1558360efbdSAlfred Perlstein if (!__rpc_fd2sockinfo(svcxprt->xp_fd, &si)) { 1568360efbdSAlfred Perlstein warnx(rpc_reg_err, rpc_reg_msg, __reg_err2); 1578360efbdSAlfred Perlstein SVC_DESTROY(svcxprt); 1588360efbdSAlfred Perlstein continue; 15999064799SGarrett Wollman } 1608360efbdSAlfred Perlstein recvsz = __rpc_get_t_size(si.si_af, si.si_proto, 0); 1618360efbdSAlfred Perlstein if (recvsz == 0) { 1628360efbdSAlfred Perlstein warnx(rpc_reg_err, rpc_reg_msg, __reg_err3); 1638360efbdSAlfred Perlstein SVC_DESTROY(svcxprt); 1648360efbdSAlfred Perlstein continue; 1658360efbdSAlfred Perlstein } 1668360efbdSAlfred Perlstein if (((xdrbuf = malloc((unsigned)recvsz)) == NULL) || 1678360efbdSAlfred Perlstein ((netid = strdup(nconf->nc_netid)) == NULL)) { 1688360efbdSAlfred Perlstein warnx(rpc_reg_err, rpc_reg_msg, __no_mem_str); 1698306b515SMartin Blapp free(xdrbuf); 1708306b515SMartin Blapp free(netid); 1718360efbdSAlfred Perlstein SVC_DESTROY(svcxprt); 1728360efbdSAlfred Perlstein break; 1738360efbdSAlfred Perlstein } 1748360efbdSAlfred Perlstein madenow = TRUE; 1758360efbdSAlfred Perlstein } 1768360efbdSAlfred Perlstein /* 1778360efbdSAlfred Perlstein * Check if this (program, version, netid) had already been 1788360efbdSAlfred Perlstein * registered. The check may save a few RPC calls to rpcbind 1798360efbdSAlfred Perlstein */ 1808360efbdSAlfred Perlstein for (pl = proglst; pl; pl = pl->p_nxt) 1818360efbdSAlfred Perlstein if ((pl->p_prognum == prognum) && 1828360efbdSAlfred Perlstein (pl->p_versnum == versnum) && 1838360efbdSAlfred Perlstein (strcmp(pl->p_netid, netid) == 0)) 1848360efbdSAlfred Perlstein break; 1858360efbdSAlfred Perlstein if (pl == NULL) { /* Not yet */ 1868360efbdSAlfred Perlstein (void) rpcb_unset(prognum, versnum, nconf); 1878360efbdSAlfred Perlstein } else { 1888360efbdSAlfred Perlstein /* so that svc_reg does not call rpcb_set() */ 1898360efbdSAlfred Perlstein nconf = NULL; 1908360efbdSAlfred Perlstein } 1918360efbdSAlfred Perlstein 1928360efbdSAlfred Perlstein if (!svc_reg(svcxprt, prognum, versnum, universal, nconf)) { 1938360efbdSAlfred Perlstein warnx("%s couldn't register prog %u vers %u for %s", 1948360efbdSAlfred Perlstein rpc_reg_msg, (unsigned)prognum, 1958360efbdSAlfred Perlstein (unsigned)versnum, netid); 1968360efbdSAlfred Perlstein if (madenow) { 1978360efbdSAlfred Perlstein SVC_DESTROY(svcxprt); 1988360efbdSAlfred Perlstein free(xdrbuf); 1998360efbdSAlfred Perlstein free(netid); 2008360efbdSAlfred Perlstein } 2018360efbdSAlfred Perlstein continue; 2028360efbdSAlfred Perlstein } 2038360efbdSAlfred Perlstein 2048360efbdSAlfred Perlstein pl = malloc(sizeof (struct proglst)); 20599064799SGarrett Wollman if (pl == NULL) { 2068360efbdSAlfred Perlstein warnx(rpc_reg_err, rpc_reg_msg, __no_mem_str); 2078360efbdSAlfred Perlstein if (madenow) { 2088360efbdSAlfred Perlstein SVC_DESTROY(svcxprt); 2098360efbdSAlfred Perlstein free(xdrbuf); 2108360efbdSAlfred Perlstein free(netid); 2118360efbdSAlfred Perlstein } 2128360efbdSAlfred Perlstein break; 21399064799SGarrett Wollman } 21499064799SGarrett Wollman pl->p_progname = progname; 21599064799SGarrett Wollman pl->p_prognum = prognum; 2168360efbdSAlfred Perlstein pl->p_versnum = versnum; 21799064799SGarrett Wollman pl->p_procnum = procnum; 21899064799SGarrett Wollman pl->p_inproc = inproc; 21999064799SGarrett Wollman pl->p_outproc = outproc; 2208360efbdSAlfred Perlstein pl->p_transp = svcxprt; 2218360efbdSAlfred Perlstein pl->p_xdrbuf = xdrbuf; 2228360efbdSAlfred Perlstein pl->p_recvsz = recvsz; 2238360efbdSAlfred Perlstein pl->p_netid = netid; 22499064799SGarrett Wollman pl->p_nxt = proglst; 22599064799SGarrett Wollman proglst = pl; 2268360efbdSAlfred Perlstein done = TRUE; 2278360efbdSAlfred Perlstein } 2288360efbdSAlfred Perlstein __rpc_endconf(handle); 2298360efbdSAlfred Perlstein mutex_unlock(&proglst_lock); 2308360efbdSAlfred Perlstein 2318360efbdSAlfred Perlstein if (done == FALSE) { 23232223c1bSPedro F. Giffuni warnx("%s can't find suitable transport for %s", 2338360efbdSAlfred Perlstein rpc_reg_msg, nettype); 2348360efbdSAlfred Perlstein return (-1); 2358360efbdSAlfred Perlstein } 23699064799SGarrett Wollman return (0); 23799064799SGarrett Wollman } 23899064799SGarrett Wollman 2398360efbdSAlfred Perlstein /* 2408360efbdSAlfred Perlstein * The universal handler for the services registered using registerrpc. 2418360efbdSAlfred Perlstein * It handles both the connectionless and the connection oriented cases. 2428360efbdSAlfred Perlstein */ 2438360efbdSAlfred Perlstein 24499064799SGarrett Wollman static void 245587cf682SCraig Rodrigues universal(struct svc_req *rqstp, SVCXPRT *transp) 24699064799SGarrett Wollman { 2478360efbdSAlfred Perlstein rpcprog_t prog; 2488360efbdSAlfred Perlstein rpcvers_t vers; 2498360efbdSAlfred Perlstein rpcproc_t proc; 25099064799SGarrett Wollman char *outdata; 2518360efbdSAlfred Perlstein char *xdrbuf; 25299064799SGarrett Wollman struct proglst *pl; 25399064799SGarrett Wollman 25499064799SGarrett Wollman /* 25599064799SGarrett Wollman * enforce "procnum 0 is echo" convention 25699064799SGarrett Wollman */ 25799064799SGarrett Wollman if (rqstp->rq_proc == NULLPROC) { 2588360efbdSAlfred Perlstein if (svc_sendreply(transp, (xdrproc_t) xdr_void, NULL) == 2598360efbdSAlfred Perlstein FALSE) { 2608360efbdSAlfred Perlstein warnx("svc_sendreply failed"); 26199064799SGarrett Wollman } 26299064799SGarrett Wollman return; 26399064799SGarrett Wollman } 26499064799SGarrett Wollman prog = rqstp->rq_prog; 2658360efbdSAlfred Perlstein vers = rqstp->rq_vers; 26699064799SGarrett Wollman proc = rqstp->rq_proc; 2678360efbdSAlfred Perlstein mutex_lock(&proglst_lock); 2688360efbdSAlfred Perlstein for (pl = proglst; pl; pl = pl->p_nxt) 2698360efbdSAlfred Perlstein if (pl->p_prognum == prog && pl->p_procnum == proc && 2708360efbdSAlfred Perlstein pl->p_versnum == vers && 2718360efbdSAlfred Perlstein (strcmp(pl->p_netid, transp->xp_netid) == 0)) { 27299064799SGarrett Wollman /* decode arguments into a CLEAN buffer */ 2738360efbdSAlfred Perlstein xdrbuf = pl->p_xdrbuf; 2748360efbdSAlfred Perlstein /* Zero the arguments: reqd ! */ 275a6221f7bSPedro F. Giffuni (void) memset(xdrbuf, 0, (size_t)pl->p_recvsz); 2768360efbdSAlfred Perlstein /* 2778360efbdSAlfred Perlstein * Assuming that sizeof (xdrbuf) would be enough 2788360efbdSAlfred Perlstein * for the arguments; if not then the program 2798360efbdSAlfred Perlstein * may bomb. BEWARE! 2808360efbdSAlfred Perlstein */ 28199064799SGarrett Wollman if (!svc_getargs(transp, pl->p_inproc, xdrbuf)) { 28299064799SGarrett Wollman svcerr_decode(transp); 2838360efbdSAlfred Perlstein mutex_unlock(&proglst_lock); 28499064799SGarrett Wollman return; 28599064799SGarrett Wollman } 28699064799SGarrett Wollman outdata = (*(pl->p_progname))(xdrbuf); 2878360efbdSAlfred Perlstein if (outdata == NULL && 2888360efbdSAlfred Perlstein pl->p_outproc != (xdrproc_t) xdr_void){ 28999064799SGarrett Wollman /* there was an error */ 2908360efbdSAlfred Perlstein mutex_unlock(&proglst_lock); 29199064799SGarrett Wollman return; 2928360efbdSAlfred Perlstein } 29399064799SGarrett Wollman if (!svc_sendreply(transp, pl->p_outproc, outdata)) { 2948360efbdSAlfred Perlstein warnx( 2958360efbdSAlfred Perlstein "rpc: rpc_reg trouble replying to prog %u vers %u", 2968360efbdSAlfred Perlstein (unsigned)prog, (unsigned)vers); 2978360efbdSAlfred Perlstein mutex_unlock(&proglst_lock); 2988360efbdSAlfred Perlstein return; 29999064799SGarrett Wollman } 30099064799SGarrett Wollman /* free the decoded arguments */ 30199064799SGarrett Wollman (void)svc_freeargs(transp, pl->p_inproc, xdrbuf); 3028360efbdSAlfred Perlstein mutex_unlock(&proglst_lock); 30399064799SGarrett Wollman return; 30499064799SGarrett Wollman } 3058360efbdSAlfred Perlstein mutex_unlock(&proglst_lock); 3068360efbdSAlfred Perlstein /* This should never happen */ 3078360efbdSAlfred Perlstein warnx("rpc: rpc_reg: never registered prog %u vers %u", 3088360efbdSAlfred Perlstein (unsigned)prog, (unsigned)vers); 3098360efbdSAlfred Perlstein return; 31099064799SGarrett Wollman } 311