18360efbdSAlfred Perlstein /* $NetBSD: svc_simple.c,v 1.20 2000/07/06 03:10:35 christos Exp $ */ 28360efbdSAlfred Perlstein 399064799SGarrett Wollman /* 499064799SGarrett Wollman * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 599064799SGarrett Wollman * unrestricted use provided that this legend is included on all tape 699064799SGarrett Wollman * media and as a part of the software program in whole or part. Users 799064799SGarrett Wollman * may copy or modify Sun RPC without charge, but are not authorized 899064799SGarrett Wollman * to license or distribute it to anyone else except as part of a product or 999064799SGarrett Wollman * program developed by the user. 1099064799SGarrett Wollman * 1199064799SGarrett Wollman * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 1299064799SGarrett Wollman * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 1399064799SGarrett Wollman * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 1499064799SGarrett Wollman * 1599064799SGarrett Wollman * Sun RPC is provided with no support and without any obligation on the 1699064799SGarrett Wollman * part of Sun Microsystems, Inc. to assist in its use, correction, 1799064799SGarrett Wollman * modification or enhancement. 1899064799SGarrett Wollman * 1999064799SGarrett Wollman * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 2099064799SGarrett Wollman * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 2199064799SGarrett Wollman * OR ANY PART THEREOF. 2299064799SGarrett Wollman * 2399064799SGarrett Wollman * In no event will Sun Microsystems, Inc. be liable for any lost revenue 2499064799SGarrett Wollman * or profits or other special, indirect and consequential damages, even if 2599064799SGarrett Wollman * Sun has been advised of the possibility of such damages. 2699064799SGarrett Wollman * 2799064799SGarrett Wollman * Sun Microsystems, Inc. 2899064799SGarrett Wollman * 2550 Garcia Avenue 2999064799SGarrett Wollman * Mountain View, California 94043 3099064799SGarrett Wollman */ 318360efbdSAlfred Perlstein /* 328360efbdSAlfred Perlstein * Copyright (c) 1986-1991 by Sun Microsystems Inc. 338360efbdSAlfred Perlstein */ 3499064799SGarrett Wollman 358360efbdSAlfred Perlstein /* #pragma ident "@(#)svc_simple.c 1.18 94/04/24 SMI" */ 36d3d20c82SDavid E. O'Brien #include <sys/cdefs.h> 37d3d20c82SDavid E. O'Brien __FBSDID("$FreeBSD$"); 3899064799SGarrett Wollman 3999064799SGarrett Wollman /* 4099064799SGarrett Wollman * svc_simple.c 4199064799SGarrett Wollman * Simplified front end to rpc. 4299064799SGarrett Wollman */ 4399064799SGarrett Wollman 448360efbdSAlfred Perlstein /* 458360efbdSAlfred Perlstein * This interface creates a virtual listener for all the services 468360efbdSAlfred Perlstein * started thru rpc_reg(). It listens on the same endpoint for 478360efbdSAlfred Perlstein * all the services and then executes the corresponding service 488360efbdSAlfred Perlstein * for the given prognum and procnum. 498360efbdSAlfred Perlstein */ 508360efbdSAlfred Perlstein 518360efbdSAlfred Perlstein #include "namespace.h" 529f5afc13SIan Dowse #include "reentrant.h" 538360efbdSAlfred Perlstein #include <sys/types.h> 548360efbdSAlfred Perlstein #include <rpc/rpc.h> 558360efbdSAlfred Perlstein #include <rpc/nettype.h> 5699064799SGarrett Wollman #include <stdio.h> 574c3af266SPoul-Henning Kamp #include <stdlib.h> 584c3af266SPoul-Henning Kamp #include <string.h> 598360efbdSAlfred Perlstein #include <err.h> 608360efbdSAlfred Perlstein #include "un-namespace.h" 618360efbdSAlfred Perlstein 628360efbdSAlfred Perlstein #include "rpc_com.h" 63235baf26SDaniel Eischen #include "mt_misc.h" 648360efbdSAlfred Perlstein 65c05ac53bSDavid E. O'Brien static void universal(struct svc_req *, SVCXPRT *); 6699064799SGarrett Wollman 6799064799SGarrett Wollman static struct proglst { 68c05ac53bSDavid E. O'Brien char *(*p_progname)(char *); 698360efbdSAlfred Perlstein rpcprog_t p_prognum; 708360efbdSAlfred Perlstein rpcvers_t p_versnum; 718360efbdSAlfred Perlstein rpcproc_t p_procnum; 728360efbdSAlfred Perlstein SVCXPRT *p_transp; 738360efbdSAlfred Perlstein char *p_netid; 748360efbdSAlfred Perlstein char *p_xdrbuf; 758360efbdSAlfred Perlstein int p_recvsz; 7699064799SGarrett Wollman xdrproc_t p_inproc, p_outproc; 7799064799SGarrett Wollman struct proglst *p_nxt; 7899064799SGarrett Wollman } *proglst; 798360efbdSAlfred Perlstein 808360efbdSAlfred Perlstein static const char rpc_reg_err[] = "%s: %s"; 818360efbdSAlfred Perlstein static const char rpc_reg_msg[] = "rpc_reg: "; 828360efbdSAlfred Perlstein static const char __reg_err1[] = "can't find appropriate transport"; 838360efbdSAlfred Perlstein static const char __reg_err2[] = "can't get protocol info"; 848360efbdSAlfred Perlstein static const char __reg_err3[] = "unsupported transport size"; 858360efbdSAlfred Perlstein static const char __no_mem_str[] = "out of memory"; 868360efbdSAlfred Perlstein 878360efbdSAlfred Perlstein /* 888360efbdSAlfred Perlstein * For simplified, easy to use kind of rpc interfaces. 898360efbdSAlfred Perlstein * nettype indicates the type of transport on which the service will be 908360efbdSAlfred Perlstein * listening. Used for conservation of the system resource. Only one 918360efbdSAlfred Perlstein * handle is created for all the services (actually one of each netid) 928360efbdSAlfred Perlstein * and same xdrbuf is used for same netid. The size of the arguments 938360efbdSAlfred Perlstein * is also limited by the recvsize for that transport, even if it is 948360efbdSAlfred Perlstein * a COTS transport. This may be wrong, but for cases like these, they 958360efbdSAlfred Perlstein * should not use the simplified interfaces like this. 968360efbdSAlfred Perlstein */ 9799064799SGarrett Wollman 9875a98e21SPeter Wemm int 998360efbdSAlfred Perlstein rpc_reg(prognum, versnum, procnum, progname, inproc, outproc, nettype) 1008360efbdSAlfred Perlstein rpcprog_t prognum; /* program number */ 1018360efbdSAlfred Perlstein rpcvers_t versnum; /* version number */ 1028360efbdSAlfred Perlstein rpcproc_t procnum; /* procedure number */ 103c05ac53bSDavid E. O'Brien char *(*progname)(char *); /* Server routine */ 1048360efbdSAlfred Perlstein xdrproc_t inproc, outproc; /* in/out XDR procedures */ 1058360efbdSAlfred Perlstein char *nettype; /* nettype */ 10699064799SGarrett Wollman { 1078360efbdSAlfred Perlstein struct netconfig *nconf; 1088360efbdSAlfred Perlstein int done = FALSE; 1098360efbdSAlfred Perlstein void *handle; 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; 1368d630135SAlfred Perlstein recvsz = 0; 1378d630135SAlfred Perlstein xdrbuf = netid = NULL; 1388d630135SAlfred Perlstein for (pl = proglst; pl; pl = pl->p_nxt) { 1398360efbdSAlfred Perlstein if (strcmp(pl->p_netid, nconf->nc_netid) == 0) { 1408360efbdSAlfred Perlstein svcxprt = pl->p_transp; 1418360efbdSAlfred Perlstein xdrbuf = pl->p_xdrbuf; 1428360efbdSAlfred Perlstein recvsz = pl->p_recvsz; 1438360efbdSAlfred Perlstein netid = pl->p_netid; 1448360efbdSAlfred Perlstein break; 14599064799SGarrett Wollman } 1468d630135SAlfred Perlstein } 1478360efbdSAlfred Perlstein 1488360efbdSAlfred Perlstein if (svcxprt == NULL) { 1498360efbdSAlfred Perlstein struct __rpc_sockinfo si; 1508360efbdSAlfred Perlstein 1518360efbdSAlfred Perlstein svcxprt = svc_tli_create(RPC_ANYFD, nconf, NULL, 0, 0); 1528360efbdSAlfred Perlstein if (svcxprt == NULL) 1538360efbdSAlfred Perlstein continue; 1548360efbdSAlfred Perlstein if (!__rpc_fd2sockinfo(svcxprt->xp_fd, &si)) { 1558360efbdSAlfred Perlstein warnx(rpc_reg_err, rpc_reg_msg, __reg_err2); 1568360efbdSAlfred Perlstein SVC_DESTROY(svcxprt); 1578360efbdSAlfred Perlstein continue; 15899064799SGarrett Wollman } 1598360efbdSAlfred Perlstein recvsz = __rpc_get_t_size(si.si_af, si.si_proto, 0); 1608360efbdSAlfred Perlstein if (recvsz == 0) { 1618360efbdSAlfred Perlstein warnx(rpc_reg_err, rpc_reg_msg, __reg_err3); 1628360efbdSAlfred Perlstein SVC_DESTROY(svcxprt); 1638360efbdSAlfred Perlstein continue; 1648360efbdSAlfred Perlstein } 1658360efbdSAlfred Perlstein if (((xdrbuf = malloc((unsigned)recvsz)) == NULL) || 1668360efbdSAlfred Perlstein ((netid = strdup(nconf->nc_netid)) == NULL)) { 1678360efbdSAlfred Perlstein warnx(rpc_reg_err, rpc_reg_msg, __no_mem_str); 1688360efbdSAlfred Perlstein SVC_DESTROY(svcxprt); 1698360efbdSAlfred Perlstein break; 1708360efbdSAlfred Perlstein } 1718360efbdSAlfred Perlstein madenow = TRUE; 1728360efbdSAlfred Perlstein } 1738360efbdSAlfred Perlstein /* 1748360efbdSAlfred Perlstein * Check if this (program, version, netid) had already been 1758360efbdSAlfred Perlstein * registered. The check may save a few RPC calls to rpcbind 1768360efbdSAlfred Perlstein */ 1778360efbdSAlfred Perlstein for (pl = proglst; pl; pl = pl->p_nxt) 1788360efbdSAlfred Perlstein if ((pl->p_prognum == prognum) && 1798360efbdSAlfred Perlstein (pl->p_versnum == versnum) && 1808360efbdSAlfred Perlstein (strcmp(pl->p_netid, netid) == 0)) 1818360efbdSAlfred Perlstein break; 1828360efbdSAlfred Perlstein if (pl == NULL) { /* Not yet */ 1838360efbdSAlfred Perlstein (void) rpcb_unset(prognum, versnum, nconf); 1848360efbdSAlfred Perlstein } else { 1858360efbdSAlfred Perlstein /* so that svc_reg does not call rpcb_set() */ 1868360efbdSAlfred Perlstein nconf = NULL; 1878360efbdSAlfred Perlstein } 1888360efbdSAlfred Perlstein 1898360efbdSAlfred Perlstein if (!svc_reg(svcxprt, prognum, versnum, universal, nconf)) { 1908360efbdSAlfred Perlstein warnx("%s couldn't register prog %u vers %u for %s", 1918360efbdSAlfred Perlstein rpc_reg_msg, (unsigned)prognum, 1928360efbdSAlfred Perlstein (unsigned)versnum, netid); 1938360efbdSAlfred Perlstein if (madenow) { 1948360efbdSAlfred Perlstein SVC_DESTROY(svcxprt); 1958360efbdSAlfred Perlstein free(xdrbuf); 1968360efbdSAlfred Perlstein free(netid); 1978360efbdSAlfred Perlstein } 1988360efbdSAlfred Perlstein continue; 1998360efbdSAlfred Perlstein } 2008360efbdSAlfred Perlstein 2018360efbdSAlfred Perlstein pl = malloc(sizeof (struct proglst)); 20299064799SGarrett Wollman if (pl == NULL) { 2038360efbdSAlfred Perlstein warnx(rpc_reg_err, rpc_reg_msg, __no_mem_str); 2048360efbdSAlfred Perlstein if (madenow) { 2058360efbdSAlfred Perlstein SVC_DESTROY(svcxprt); 2068360efbdSAlfred Perlstein free(xdrbuf); 2078360efbdSAlfred Perlstein free(netid); 2088360efbdSAlfred Perlstein } 2098360efbdSAlfred Perlstein break; 21099064799SGarrett Wollman } 21199064799SGarrett Wollman pl->p_progname = progname; 21299064799SGarrett Wollman pl->p_prognum = prognum; 2138360efbdSAlfred Perlstein pl->p_versnum = versnum; 21499064799SGarrett Wollman pl->p_procnum = procnum; 21599064799SGarrett Wollman pl->p_inproc = inproc; 21699064799SGarrett Wollman pl->p_outproc = outproc; 2178360efbdSAlfred Perlstein pl->p_transp = svcxprt; 2188360efbdSAlfred Perlstein pl->p_xdrbuf = xdrbuf; 2198360efbdSAlfred Perlstein pl->p_recvsz = recvsz; 2208360efbdSAlfred Perlstein pl->p_netid = netid; 22199064799SGarrett Wollman pl->p_nxt = proglst; 22299064799SGarrett Wollman proglst = pl; 2238360efbdSAlfred Perlstein done = TRUE; 2248360efbdSAlfred Perlstein } 2258360efbdSAlfred Perlstein __rpc_endconf(handle); 2268360efbdSAlfred Perlstein mutex_unlock(&proglst_lock); 2278360efbdSAlfred Perlstein 2288360efbdSAlfred Perlstein if (done == FALSE) { 2298360efbdSAlfred Perlstein warnx("%s cant find suitable transport for %s", 2308360efbdSAlfred Perlstein rpc_reg_msg, nettype); 2318360efbdSAlfred Perlstein return (-1); 2328360efbdSAlfred Perlstein } 23399064799SGarrett Wollman return (0); 23499064799SGarrett Wollman } 23599064799SGarrett Wollman 2368360efbdSAlfred Perlstein /* 2378360efbdSAlfred Perlstein * The universal handler for the services registered using registerrpc. 2388360efbdSAlfred Perlstein * It handles both the connectionless and the connection oriented cases. 2398360efbdSAlfred Perlstein */ 2408360efbdSAlfred Perlstein 24199064799SGarrett Wollman static void 24299064799SGarrett Wollman universal(rqstp, transp) 24399064799SGarrett Wollman struct svc_req *rqstp; 24499064799SGarrett Wollman SVCXPRT *transp; 24599064799SGarrett Wollman { 2468360efbdSAlfred Perlstein rpcprog_t prog; 2478360efbdSAlfred Perlstein rpcvers_t vers; 2488360efbdSAlfred Perlstein rpcproc_t proc; 24999064799SGarrett Wollman char *outdata; 2508360efbdSAlfred Perlstein char *xdrbuf; 25199064799SGarrett Wollman struct proglst *pl; 25299064799SGarrett Wollman 25399064799SGarrett Wollman /* 25499064799SGarrett Wollman * enforce "procnum 0 is echo" convention 25599064799SGarrett Wollman */ 25699064799SGarrett Wollman if (rqstp->rq_proc == NULLPROC) { 2578360efbdSAlfred Perlstein if (svc_sendreply(transp, (xdrproc_t) xdr_void, NULL) == 2588360efbdSAlfred Perlstein FALSE) { 2598360efbdSAlfred Perlstein warnx("svc_sendreply failed"); 26099064799SGarrett Wollman } 26199064799SGarrett Wollman return; 26299064799SGarrett Wollman } 26399064799SGarrett Wollman prog = rqstp->rq_prog; 2648360efbdSAlfred Perlstein vers = rqstp->rq_vers; 26599064799SGarrett Wollman proc = rqstp->rq_proc; 2668360efbdSAlfred Perlstein mutex_lock(&proglst_lock); 2678360efbdSAlfred Perlstein for (pl = proglst; pl; pl = pl->p_nxt) 2688360efbdSAlfred Perlstein if (pl->p_prognum == prog && pl->p_procnum == proc && 2698360efbdSAlfred Perlstein pl->p_versnum == vers && 2708360efbdSAlfred Perlstein (strcmp(pl->p_netid, transp->xp_netid) == 0)) { 27199064799SGarrett Wollman /* decode arguments into a CLEAN buffer */ 2728360efbdSAlfred Perlstein xdrbuf = pl->p_xdrbuf; 2738360efbdSAlfred Perlstein /* Zero the arguments: reqd ! */ 2748360efbdSAlfred Perlstein (void) memset(xdrbuf, 0, sizeof (pl->p_recvsz)); 2758360efbdSAlfred Perlstein /* 2768360efbdSAlfred Perlstein * Assuming that sizeof (xdrbuf) would be enough 2778360efbdSAlfred Perlstein * for the arguments; if not then the program 2788360efbdSAlfred Perlstein * may bomb. BEWARE! 2798360efbdSAlfred Perlstein */ 28099064799SGarrett Wollman if (!svc_getargs(transp, pl->p_inproc, xdrbuf)) { 28199064799SGarrett Wollman svcerr_decode(transp); 2828360efbdSAlfred Perlstein mutex_unlock(&proglst_lock); 28399064799SGarrett Wollman return; 28499064799SGarrett Wollman } 28599064799SGarrett Wollman outdata = (*(pl->p_progname))(xdrbuf); 2868360efbdSAlfred Perlstein if (outdata == NULL && 2878360efbdSAlfred Perlstein pl->p_outproc != (xdrproc_t) xdr_void){ 28899064799SGarrett Wollman /* there was an error */ 2898360efbdSAlfred Perlstein mutex_unlock(&proglst_lock); 29099064799SGarrett Wollman return; 2918360efbdSAlfred Perlstein } 29299064799SGarrett Wollman if (!svc_sendreply(transp, pl->p_outproc, outdata)) { 2938360efbdSAlfred Perlstein warnx( 2948360efbdSAlfred Perlstein "rpc: rpc_reg trouble replying to prog %u vers %u", 2958360efbdSAlfred Perlstein (unsigned)prog, (unsigned)vers); 2968360efbdSAlfred Perlstein mutex_unlock(&proglst_lock); 2978360efbdSAlfred Perlstein return; 29899064799SGarrett Wollman } 29999064799SGarrett Wollman /* free the decoded arguments */ 30099064799SGarrett Wollman (void)svc_freeargs(transp, pl->p_inproc, xdrbuf); 3018360efbdSAlfred Perlstein mutex_unlock(&proglst_lock); 30299064799SGarrett Wollman return; 30399064799SGarrett Wollman } 3048360efbdSAlfred Perlstein mutex_unlock(&proglst_lock); 3058360efbdSAlfred Perlstein /* This should never happen */ 3068360efbdSAlfred Perlstein warnx("rpc: rpc_reg: never registered prog %u vers %u", 3078360efbdSAlfred Perlstein (unsigned)prog, (unsigned)vers); 3088360efbdSAlfred Perlstein return; 30999064799SGarrett Wollman } 310