18360efbdSAlfred Perlstein /* $NetBSD: svc_simple.c,v 1.20 2000/07/06 03:10:35 christos Exp $ */ 28360efbdSAlfred Perlstein /* $FreeBSD$ */ 38360efbdSAlfred Perlstein 499064799SGarrett Wollman /* 599064799SGarrett Wollman * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 699064799SGarrett Wollman * unrestricted use provided that this legend is included on all tape 799064799SGarrett Wollman * media and as a part of the software program in whole or part. Users 899064799SGarrett Wollman * may copy or modify Sun RPC without charge, but are not authorized 999064799SGarrett Wollman * to license or distribute it to anyone else except as part of a product or 1099064799SGarrett Wollman * program developed by the user. 1199064799SGarrett Wollman * 1299064799SGarrett Wollman * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 1399064799SGarrett Wollman * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 1499064799SGarrett Wollman * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 1599064799SGarrett Wollman * 1699064799SGarrett Wollman * Sun RPC is provided with no support and without any obligation on the 1799064799SGarrett Wollman * part of Sun Microsystems, Inc. to assist in its use, correction, 1899064799SGarrett Wollman * modification or enhancement. 1999064799SGarrett Wollman * 2099064799SGarrett Wollman * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 2199064799SGarrett Wollman * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 2299064799SGarrett Wollman * OR ANY PART THEREOF. 2399064799SGarrett Wollman * 2499064799SGarrett Wollman * In no event will Sun Microsystems, Inc. be liable for any lost revenue 2599064799SGarrett Wollman * or profits or other special, indirect and consequential damages, even if 2699064799SGarrett Wollman * Sun has been advised of the possibility of such damages. 2799064799SGarrett Wollman * 2899064799SGarrett Wollman * Sun Microsystems, Inc. 2999064799SGarrett Wollman * 2550 Garcia Avenue 3099064799SGarrett Wollman * Mountain View, California 94043 3199064799SGarrett Wollman */ 328360efbdSAlfred Perlstein /* 338360efbdSAlfred Perlstein * Copyright (c) 1986-1991 by Sun Microsystems Inc. 348360efbdSAlfred Perlstein */ 3599064799SGarrett Wollman 368360efbdSAlfred Perlstein /* #pragma ident "@(#)svc_simple.c 1.18 94/04/24 SMI" */ 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 458360efbdSAlfred Perlstein * started thru 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 "reentrant.h" 518360efbdSAlfred Perlstein #include "namespace.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" 628360efbdSAlfred Perlstein 638360efbdSAlfred Perlstein static void universal __P((struct svc_req *, SVCXPRT *)); 6499064799SGarrett Wollman 6599064799SGarrett Wollman static struct proglst { 668360efbdSAlfred Perlstein char *(*p_progname) __P((char *)); 678360efbdSAlfred Perlstein rpcprog_t p_prognum; 688360efbdSAlfred Perlstein rpcvers_t p_versnum; 698360efbdSAlfred Perlstein rpcproc_t p_procnum; 708360efbdSAlfred Perlstein SVCXPRT *p_transp; 718360efbdSAlfred Perlstein char *p_netid; 728360efbdSAlfred Perlstein char *p_xdrbuf; 738360efbdSAlfred Perlstein int p_recvsz; 7499064799SGarrett Wollman xdrproc_t p_inproc, p_outproc; 7599064799SGarrett Wollman struct proglst *p_nxt; 7699064799SGarrett Wollman } *proglst; 778360efbdSAlfred Perlstein 788360efbdSAlfred Perlstein static const char rpc_reg_err[] = "%s: %s"; 798360efbdSAlfred Perlstein static const char rpc_reg_msg[] = "rpc_reg: "; 808360efbdSAlfred Perlstein static const char __reg_err1[] = "can't find appropriate transport"; 818360efbdSAlfred Perlstein static const char __reg_err2[] = "can't get protocol info"; 828360efbdSAlfred Perlstein static const char __reg_err3[] = "unsupported transport size"; 838360efbdSAlfred Perlstein static const char __no_mem_str[] = "out of memory"; 848360efbdSAlfred Perlstein 858360efbdSAlfred Perlstein /* 868360efbdSAlfred Perlstein * For simplified, easy to use kind of rpc interfaces. 878360efbdSAlfred Perlstein * nettype indicates the type of transport on which the service will be 888360efbdSAlfred Perlstein * listening. Used for conservation of the system resource. Only one 898360efbdSAlfred Perlstein * handle is created for all the services (actually one of each netid) 908360efbdSAlfred Perlstein * and same xdrbuf is used for same netid. The size of the arguments 918360efbdSAlfred Perlstein * is also limited by the recvsize for that transport, even if it is 928360efbdSAlfred Perlstein * a COTS transport. This may be wrong, but for cases like these, they 938360efbdSAlfred Perlstein * should not use the simplified interfaces like this. 948360efbdSAlfred Perlstein */ 9599064799SGarrett Wollman 9675a98e21SPeter Wemm int 978360efbdSAlfred Perlstein rpc_reg(prognum, versnum, procnum, progname, inproc, outproc, nettype) 988360efbdSAlfred Perlstein rpcprog_t prognum; /* program number */ 998360efbdSAlfred Perlstein rpcvers_t versnum; /* version number */ 1008360efbdSAlfred Perlstein rpcproc_t procnum; /* procedure number */ 1018360efbdSAlfred Perlstein char *(*progname) __P((char *)); /* Server routine */ 1028360efbdSAlfred Perlstein xdrproc_t inproc, outproc; /* in/out XDR procedures */ 1038360efbdSAlfred Perlstein char *nettype; /* nettype */ 10499064799SGarrett Wollman { 1058360efbdSAlfred Perlstein struct netconfig *nconf; 1068360efbdSAlfred Perlstein int done = FALSE; 1078360efbdSAlfred Perlstein void *handle; 1088360efbdSAlfred Perlstein extern mutex_t proglst_lock; 1098360efbdSAlfred Perlstein 1108360efbdSAlfred Perlstein 11199064799SGarrett Wollman 11299064799SGarrett Wollman if (procnum == NULLPROC) { 1138360efbdSAlfred Perlstein warnx("%s can't reassign procedure number %u", rpc_reg_msg, 1148360efbdSAlfred Perlstein NULLPROC); 11599064799SGarrett Wollman return (-1); 11699064799SGarrett Wollman } 1178360efbdSAlfred Perlstein 1188360efbdSAlfred Perlstein if (nettype == NULL) 1198360efbdSAlfred Perlstein nettype = "netpath"; /* The default behavior */ 1208360efbdSAlfred Perlstein if ((handle = __rpc_setconf(nettype)) == NULL) { 1218360efbdSAlfred Perlstein warnx(rpc_reg_err, rpc_reg_msg, __reg_err1); 12299064799SGarrett Wollman return (-1); 12399064799SGarrett Wollman } 1248360efbdSAlfred Perlstein /* VARIABLES PROTECTED BY proglst_lock: proglst */ 1258360efbdSAlfred Perlstein mutex_lock(&proglst_lock); 1268360efbdSAlfred Perlstein while ((nconf = __rpc_getconf(handle)) != NULL) { 1278360efbdSAlfred Perlstein struct proglst *pl; 1288360efbdSAlfred Perlstein SVCXPRT *svcxprt; 1298360efbdSAlfred Perlstein int madenow; 1308360efbdSAlfred Perlstein u_int recvsz; 1318360efbdSAlfred Perlstein char *xdrbuf; 1328360efbdSAlfred Perlstein char *netid; 1338360efbdSAlfred Perlstein 1348360efbdSAlfred Perlstein madenow = FALSE; 1358360efbdSAlfred Perlstein svcxprt = NULL; 1368360efbdSAlfred Perlstein for (pl = proglst; pl; pl = pl->p_nxt) 1378360efbdSAlfred Perlstein if (strcmp(pl->p_netid, nconf->nc_netid) == 0) { 1388360efbdSAlfred Perlstein svcxprt = pl->p_transp; 1398360efbdSAlfred Perlstein xdrbuf = pl->p_xdrbuf; 1408360efbdSAlfred Perlstein recvsz = pl->p_recvsz; 1418360efbdSAlfred Perlstein netid = pl->p_netid; 1428360efbdSAlfred Perlstein break; 14399064799SGarrett Wollman } 1448360efbdSAlfred Perlstein 1458360efbdSAlfred Perlstein if (svcxprt == NULL) { 1468360efbdSAlfred Perlstein struct __rpc_sockinfo si; 1478360efbdSAlfred Perlstein 1488360efbdSAlfred Perlstein svcxprt = svc_tli_create(RPC_ANYFD, nconf, NULL, 0, 0); 1498360efbdSAlfred Perlstein if (svcxprt == NULL) 1508360efbdSAlfred Perlstein continue; 1518360efbdSAlfred Perlstein if (!__rpc_fd2sockinfo(svcxprt->xp_fd, &si)) { 1528360efbdSAlfred Perlstein warnx(rpc_reg_err, rpc_reg_msg, __reg_err2); 1538360efbdSAlfred Perlstein SVC_DESTROY(svcxprt); 1548360efbdSAlfred Perlstein continue; 15599064799SGarrett Wollman } 1568360efbdSAlfred Perlstein recvsz = __rpc_get_t_size(si.si_af, si.si_proto, 0); 1578360efbdSAlfred Perlstein if (recvsz == 0) { 1588360efbdSAlfred Perlstein warnx(rpc_reg_err, rpc_reg_msg, __reg_err3); 1598360efbdSAlfred Perlstein SVC_DESTROY(svcxprt); 1608360efbdSAlfred Perlstein continue; 1618360efbdSAlfred Perlstein } 1628360efbdSAlfred Perlstein if (((xdrbuf = malloc((unsigned)recvsz)) == NULL) || 1638360efbdSAlfred Perlstein ((netid = strdup(nconf->nc_netid)) == NULL)) { 1648360efbdSAlfred Perlstein warnx(rpc_reg_err, rpc_reg_msg, __no_mem_str); 1658360efbdSAlfred Perlstein SVC_DESTROY(svcxprt); 1668360efbdSAlfred Perlstein break; 1678360efbdSAlfred Perlstein } 1688360efbdSAlfred Perlstein madenow = TRUE; 1698360efbdSAlfred Perlstein } 1708360efbdSAlfred Perlstein /* 1718360efbdSAlfred Perlstein * Check if this (program, version, netid) had already been 1728360efbdSAlfred Perlstein * registered. The check may save a few RPC calls to rpcbind 1738360efbdSAlfred Perlstein */ 1748360efbdSAlfred Perlstein for (pl = proglst; pl; pl = pl->p_nxt) 1758360efbdSAlfred Perlstein if ((pl->p_prognum == prognum) && 1768360efbdSAlfred Perlstein (pl->p_versnum == versnum) && 1778360efbdSAlfred Perlstein (strcmp(pl->p_netid, netid) == 0)) 1788360efbdSAlfred Perlstein break; 1798360efbdSAlfred Perlstein if (pl == NULL) { /* Not yet */ 1808360efbdSAlfred Perlstein (void) rpcb_unset(prognum, versnum, nconf); 1818360efbdSAlfred Perlstein } else { 1828360efbdSAlfred Perlstein /* so that svc_reg does not call rpcb_set() */ 1838360efbdSAlfred Perlstein nconf = NULL; 1848360efbdSAlfred Perlstein } 1858360efbdSAlfred Perlstein 1868360efbdSAlfred Perlstein if (!svc_reg(svcxprt, prognum, versnum, universal, nconf)) { 1878360efbdSAlfred Perlstein warnx("%s couldn't register prog %u vers %u for %s", 1888360efbdSAlfred Perlstein rpc_reg_msg, (unsigned)prognum, 1898360efbdSAlfred Perlstein (unsigned)versnum, netid); 1908360efbdSAlfred Perlstein if (madenow) { 1918360efbdSAlfred Perlstein SVC_DESTROY(svcxprt); 1928360efbdSAlfred Perlstein free(xdrbuf); 1938360efbdSAlfred Perlstein free(netid); 1948360efbdSAlfred Perlstein } 1958360efbdSAlfred Perlstein continue; 1968360efbdSAlfred Perlstein } 1978360efbdSAlfred Perlstein 1988360efbdSAlfred Perlstein pl = malloc(sizeof (struct proglst)); 19999064799SGarrett Wollman if (pl == NULL) { 2008360efbdSAlfred Perlstein warnx(rpc_reg_err, rpc_reg_msg, __no_mem_str); 2018360efbdSAlfred Perlstein if (madenow) { 2028360efbdSAlfred Perlstein SVC_DESTROY(svcxprt); 2038360efbdSAlfred Perlstein free(xdrbuf); 2048360efbdSAlfred Perlstein free(netid); 2058360efbdSAlfred Perlstein } 2068360efbdSAlfred Perlstein break; 20799064799SGarrett Wollman } 20899064799SGarrett Wollman pl->p_progname = progname; 20999064799SGarrett Wollman pl->p_prognum = prognum; 2108360efbdSAlfred Perlstein pl->p_versnum = versnum; 21199064799SGarrett Wollman pl->p_procnum = procnum; 21299064799SGarrett Wollman pl->p_inproc = inproc; 21399064799SGarrett Wollman pl->p_outproc = outproc; 2148360efbdSAlfred Perlstein pl->p_transp = svcxprt; 2158360efbdSAlfred Perlstein pl->p_xdrbuf = xdrbuf; 2168360efbdSAlfred Perlstein pl->p_recvsz = recvsz; 2178360efbdSAlfred Perlstein pl->p_netid = netid; 21899064799SGarrett Wollman pl->p_nxt = proglst; 21999064799SGarrett Wollman proglst = pl; 2208360efbdSAlfred Perlstein done = TRUE; 2218360efbdSAlfred Perlstein } 2228360efbdSAlfred Perlstein __rpc_endconf(handle); 2238360efbdSAlfred Perlstein mutex_unlock(&proglst_lock); 2248360efbdSAlfred Perlstein 2258360efbdSAlfred Perlstein if (done == FALSE) { 2268360efbdSAlfred Perlstein warnx("%s cant find suitable transport for %s", 2278360efbdSAlfred Perlstein rpc_reg_msg, nettype); 2288360efbdSAlfred Perlstein return (-1); 2298360efbdSAlfred Perlstein } 23099064799SGarrett Wollman return (0); 23199064799SGarrett Wollman } 23299064799SGarrett Wollman 2338360efbdSAlfred Perlstein /* 2348360efbdSAlfred Perlstein * The universal handler for the services registered using registerrpc. 2358360efbdSAlfred Perlstein * It handles both the connectionless and the connection oriented cases. 2368360efbdSAlfred Perlstein */ 2378360efbdSAlfred Perlstein 23899064799SGarrett Wollman static void 23999064799SGarrett Wollman universal(rqstp, transp) 24099064799SGarrett Wollman struct svc_req *rqstp; 24199064799SGarrett Wollman SVCXPRT *transp; 24299064799SGarrett Wollman { 2438360efbdSAlfred Perlstein rpcprog_t prog; 2448360efbdSAlfred Perlstein rpcvers_t vers; 2458360efbdSAlfred Perlstein rpcproc_t proc; 24699064799SGarrett Wollman char *outdata; 2478360efbdSAlfred Perlstein char *xdrbuf; 24899064799SGarrett Wollman struct proglst *pl; 2498360efbdSAlfred Perlstein extern mutex_t proglst_lock; 25099064799SGarrett Wollman 25199064799SGarrett Wollman /* 25299064799SGarrett Wollman * enforce "procnum 0 is echo" convention 25399064799SGarrett Wollman */ 25499064799SGarrett Wollman if (rqstp->rq_proc == NULLPROC) { 2558360efbdSAlfred Perlstein if (svc_sendreply(transp, (xdrproc_t) xdr_void, NULL) == 2568360efbdSAlfred Perlstein FALSE) { 2578360efbdSAlfred Perlstein warnx("svc_sendreply failed"); 25899064799SGarrett Wollman } 25999064799SGarrett Wollman return; 26099064799SGarrett Wollman } 26199064799SGarrett Wollman prog = rqstp->rq_prog; 2628360efbdSAlfred Perlstein vers = rqstp->rq_vers; 26399064799SGarrett Wollman proc = rqstp->rq_proc; 2648360efbdSAlfred Perlstein mutex_lock(&proglst_lock); 2658360efbdSAlfred Perlstein for (pl = proglst; pl; pl = pl->p_nxt) 2668360efbdSAlfred Perlstein if (pl->p_prognum == prog && pl->p_procnum == proc && 2678360efbdSAlfred Perlstein pl->p_versnum == vers && 2688360efbdSAlfred Perlstein (strcmp(pl->p_netid, transp->xp_netid) == 0)) { 26999064799SGarrett Wollman /* decode arguments into a CLEAN buffer */ 2708360efbdSAlfred Perlstein xdrbuf = pl->p_xdrbuf; 2718360efbdSAlfred Perlstein /* Zero the arguments: reqd ! */ 2728360efbdSAlfred Perlstein (void) memset(xdrbuf, 0, sizeof (pl->p_recvsz)); 2738360efbdSAlfred Perlstein /* 2748360efbdSAlfred Perlstein * Assuming that sizeof (xdrbuf) would be enough 2758360efbdSAlfred Perlstein * for the arguments; if not then the program 2768360efbdSAlfred Perlstein * may bomb. BEWARE! 2778360efbdSAlfred Perlstein */ 27899064799SGarrett Wollman if (!svc_getargs(transp, pl->p_inproc, xdrbuf)) { 27999064799SGarrett Wollman svcerr_decode(transp); 2808360efbdSAlfred Perlstein mutex_unlock(&proglst_lock); 28199064799SGarrett Wollman return; 28299064799SGarrett Wollman } 28399064799SGarrett Wollman outdata = (*(pl->p_progname))(xdrbuf); 2848360efbdSAlfred Perlstein if (outdata == NULL && 2858360efbdSAlfred Perlstein pl->p_outproc != (xdrproc_t) xdr_void){ 28699064799SGarrett Wollman /* there was an error */ 2878360efbdSAlfred Perlstein mutex_unlock(&proglst_lock); 28899064799SGarrett Wollman return; 2898360efbdSAlfred Perlstein } 29099064799SGarrett Wollman if (!svc_sendreply(transp, pl->p_outproc, outdata)) { 2918360efbdSAlfred Perlstein warnx( 2928360efbdSAlfred Perlstein "rpc: rpc_reg trouble replying to prog %u vers %u", 2938360efbdSAlfred Perlstein (unsigned)prog, (unsigned)vers); 2948360efbdSAlfred Perlstein mutex_unlock(&proglst_lock); 2958360efbdSAlfred Perlstein return; 29699064799SGarrett Wollman } 29799064799SGarrett Wollman /* free the decoded arguments */ 29899064799SGarrett Wollman (void)svc_freeargs(transp, pl->p_inproc, xdrbuf); 2998360efbdSAlfred Perlstein mutex_unlock(&proglst_lock); 30099064799SGarrett Wollman return; 30199064799SGarrett Wollman } 3028360efbdSAlfred Perlstein mutex_unlock(&proglst_lock); 3038360efbdSAlfred Perlstein /* This should never happen */ 3048360efbdSAlfred Perlstein warnx("rpc: rpc_reg: never registered prog %u vers %u", 3058360efbdSAlfred Perlstein (unsigned)prog, (unsigned)vers); 3068360efbdSAlfred Perlstein return; 30799064799SGarrett Wollman } 308