17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 59acbbeafSnn35248 * Common Development and Distribution License (the "License"). 69acbbeafSnn35248 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 2161961e0fSrobinson 227c478bd9Sstevel@tonic-gate /* 23*9ff75adeSSurya Prakki * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 267c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 297c478bd9Sstevel@tonic-gate * 4.3 BSD under license from the Regents of the University of 307c478bd9Sstevel@tonic-gate * California. 317c478bd9Sstevel@tonic-gate */ 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate /* 347c478bd9Sstevel@tonic-gate * svc_simple.c 357c478bd9Sstevel@tonic-gate * Simplified front end to rpc. 367c478bd9Sstevel@tonic-gate */ 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate /* 397c478bd9Sstevel@tonic-gate * This interface creates a virtual listener for all the services 407c478bd9Sstevel@tonic-gate * started thru rpc_reg(). It listens on the same endpoint for 417c478bd9Sstevel@tonic-gate * all the services and then executes the corresponding service 427c478bd9Sstevel@tonic-gate * for the given prognum and procnum. 437c478bd9Sstevel@tonic-gate */ 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate #include "mt.h" 467c478bd9Sstevel@tonic-gate #include "rpc_mt.h" 477c478bd9Sstevel@tonic-gate #include <errno.h> 487c478bd9Sstevel@tonic-gate #include <stdio.h> 497c478bd9Sstevel@tonic-gate #include <stdlib.h> 507c478bd9Sstevel@tonic-gate #include <string.h> 517c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 527c478bd9Sstevel@tonic-gate #include <sys/types.h> 537c478bd9Sstevel@tonic-gate #include <syslog.h> 547c478bd9Sstevel@tonic-gate #include <rpc/nettype.h> 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate static struct proglst { 577c478bd9Sstevel@tonic-gate char *(*p_progname)(); 587c478bd9Sstevel@tonic-gate rpcprog_t p_prognum; 597c478bd9Sstevel@tonic-gate rpcvers_t p_versnum; 607c478bd9Sstevel@tonic-gate rpcproc_t p_procnum; 617c478bd9Sstevel@tonic-gate SVCXPRT *p_transp; 627c478bd9Sstevel@tonic-gate char *p_netid; 637c478bd9Sstevel@tonic-gate char *p_xdrbuf; 647c478bd9Sstevel@tonic-gate int p_recvsz; 657c478bd9Sstevel@tonic-gate xdrproc_t p_inproc, p_outproc; 667c478bd9Sstevel@tonic-gate struct proglst *p_nxt; 677c478bd9Sstevel@tonic-gate } *proglst; 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate static void universal(); 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate static const char rpc_reg_err[] = "%s: %s"; 727c478bd9Sstevel@tonic-gate static const char rpc_reg_msg[] = "rpc_reg: "; 737c478bd9Sstevel@tonic-gate static const char __reg_err1[] = "can't find appropriate transport"; 747c478bd9Sstevel@tonic-gate static const char __reg_err3[] = "unsupported transport size"; 757c478bd9Sstevel@tonic-gate static const char __no_mem_str[] = "out of memory"; 767c478bd9Sstevel@tonic-gate /* 777c478bd9Sstevel@tonic-gate * For simplified, easy to use kind of rpc interfaces. 787c478bd9Sstevel@tonic-gate * nettype indicates the type of transport on which the service will be 797c478bd9Sstevel@tonic-gate * listening. Used for conservation of the system resource. Only one 807c478bd9Sstevel@tonic-gate * handle is created for all the services (actually one of each netid) 817c478bd9Sstevel@tonic-gate * and same xdrbuf is used for same netid. The size of the arguments 827c478bd9Sstevel@tonic-gate * is also limited by the recvsize for that transport, even if it is 837c478bd9Sstevel@tonic-gate * a COTS transport. This may be wrong, but for cases like these, they 847c478bd9Sstevel@tonic-gate * should not use the simplified interfaces like this. 857c478bd9Sstevel@tonic-gate */ 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate int 8861961e0fSrobinson rpc_reg(const rpcprog_t prognum, const rpcvers_t versnum, 8961961e0fSrobinson const rpcproc_t procnum, char *(*progname)(), const xdrproc_t inproc, 9061961e0fSrobinson const xdrproc_t outproc, const char *nettype) 917c478bd9Sstevel@tonic-gate { 927c478bd9Sstevel@tonic-gate struct netconfig *nconf; 937c478bd9Sstevel@tonic-gate int done = FALSE; 947c478bd9Sstevel@tonic-gate void *handle; 957c478bd9Sstevel@tonic-gate extern mutex_t proglst_lock; 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate if (procnum == NULLPROC) { 987c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, (const char *) "%s: %s %d", 997c478bd9Sstevel@tonic-gate rpc_reg_msg, 1007c478bd9Sstevel@tonic-gate (const char *) "can't reassign procedure number %d", 1017c478bd9Sstevel@tonic-gate NULLPROC); 1027c478bd9Sstevel@tonic-gate return (-1); 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate if (nettype == NULL) 1067c478bd9Sstevel@tonic-gate nettype = "netpath"; /* The default behavior */ 1077c478bd9Sstevel@tonic-gate if ((handle = __rpc_setconf((char *)nettype)) == NULL) { 1087c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, rpc_reg_err, rpc_reg_msg, __reg_err1); 1097c478bd9Sstevel@tonic-gate return (-1); 1107c478bd9Sstevel@tonic-gate } 1117c478bd9Sstevel@tonic-gate /* VARIABLES PROTECTED BY proglst_lock: proglst */ 11261961e0fSrobinson (void) mutex_lock(&proglst_lock); 1137c478bd9Sstevel@tonic-gate while (nconf = __rpc_getconf(handle)) { 1147c478bd9Sstevel@tonic-gate struct proglst *pl; 1157c478bd9Sstevel@tonic-gate SVCXPRT *svcxprt; 1167c478bd9Sstevel@tonic-gate int madenow; 1177c478bd9Sstevel@tonic-gate uint_t recvsz; 1187c478bd9Sstevel@tonic-gate char *xdrbuf; 1197c478bd9Sstevel@tonic-gate char *netid; 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate madenow = FALSE; 12261961e0fSrobinson svcxprt = NULL; 1237c478bd9Sstevel@tonic-gate for (pl = proglst; pl; pl = pl->p_nxt) 1247c478bd9Sstevel@tonic-gate if (strcmp(pl->p_netid, nconf->nc_netid) == 0) { 1257c478bd9Sstevel@tonic-gate svcxprt = pl->p_transp; 1267c478bd9Sstevel@tonic-gate xdrbuf = pl->p_xdrbuf; 1277c478bd9Sstevel@tonic-gate recvsz = pl->p_recvsz; 1287c478bd9Sstevel@tonic-gate netid = pl->p_netid; 1297c478bd9Sstevel@tonic-gate break; 1307c478bd9Sstevel@tonic-gate } 1317c478bd9Sstevel@tonic-gate 13261961e0fSrobinson if (svcxprt == NULL) { 1337c478bd9Sstevel@tonic-gate struct t_info tinfo; 1347c478bd9Sstevel@tonic-gate 13561961e0fSrobinson svcxprt = svc_tli_create(RPC_ANYFD, nconf, NULL, 0, 0); 13661961e0fSrobinson if (svcxprt == NULL) 1377c478bd9Sstevel@tonic-gate continue; 1387c478bd9Sstevel@tonic-gate if (t_getinfo(svcxprt->xp_fd, &tinfo) == -1) { 1397c478bd9Sstevel@tonic-gate char errorstr[100]; 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate __tli_sys_strerror(errorstr, sizeof (errorstr), 1427c478bd9Sstevel@tonic-gate t_errno, errno); 1437c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, "%s : %s : %s", 1447c478bd9Sstevel@tonic-gate rpc_reg_msg, "t_getinfo failed", 1457c478bd9Sstevel@tonic-gate errorstr); 1467c478bd9Sstevel@tonic-gate SVC_DESTROY(svcxprt); 1477c478bd9Sstevel@tonic-gate continue; 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate if ((recvsz = __rpc_get_t_size(0, tinfo.tsdu)) == 0) { 1507c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, rpc_reg_err, rpc_reg_msg, 1517c478bd9Sstevel@tonic-gate __reg_err3); 1527c478bd9Sstevel@tonic-gate SVC_DESTROY(svcxprt); 1537c478bd9Sstevel@tonic-gate continue; 1547c478bd9Sstevel@tonic-gate } 1557c478bd9Sstevel@tonic-gate if (((xdrbuf = malloc((unsigned)recvsz)) == NULL) || 1567c478bd9Sstevel@tonic-gate ((netid = strdup(nconf->nc_netid)) == NULL)) { 1577c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, rpc_reg_err, rpc_reg_msg, 1587c478bd9Sstevel@tonic-gate __no_mem_str); 1597c478bd9Sstevel@tonic-gate SVC_DESTROY(svcxprt); 1607c478bd9Sstevel@tonic-gate break; 1617c478bd9Sstevel@tonic-gate } 1627c478bd9Sstevel@tonic-gate madenow = TRUE; 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate /* 1657c478bd9Sstevel@tonic-gate * Check if this (program, version, netid) had already been 1667c478bd9Sstevel@tonic-gate * registered. The check may save a few RPC calls to rpcbind 1677c478bd9Sstevel@tonic-gate */ 1687c478bd9Sstevel@tonic-gate for (pl = proglst; pl; pl = pl->p_nxt) 1697c478bd9Sstevel@tonic-gate if ((pl->p_prognum == prognum) && 1707c478bd9Sstevel@tonic-gate (pl->p_versnum == versnum) && 1717c478bd9Sstevel@tonic-gate (strcmp(pl->p_netid, netid) == 0)) 1727c478bd9Sstevel@tonic-gate break; 1737c478bd9Sstevel@tonic-gate if (pl == NULL) { /* Not yet */ 1747c478bd9Sstevel@tonic-gate (void) rpcb_unset(prognum, versnum, nconf); 1757c478bd9Sstevel@tonic-gate } else { 1767c478bd9Sstevel@tonic-gate /* so that svc_reg does not call rpcb_set() */ 1777c478bd9Sstevel@tonic-gate nconf = NULL; 1787c478bd9Sstevel@tonic-gate } 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate if (!svc_reg(svcxprt, prognum, versnum, universal, nconf)) { 1817c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, 1827c478bd9Sstevel@tonic-gate "%s couldn't register prog %d vers %d for %s", 1837c478bd9Sstevel@tonic-gate rpc_reg_msg, prognum, versnum, netid); 1847c478bd9Sstevel@tonic-gate if (madenow) { 1857c478bd9Sstevel@tonic-gate SVC_DESTROY(svcxprt); 1867c478bd9Sstevel@tonic-gate free(xdrbuf); 1877c478bd9Sstevel@tonic-gate free(netid); 1887c478bd9Sstevel@tonic-gate } 1897c478bd9Sstevel@tonic-gate continue; 1907c478bd9Sstevel@tonic-gate } 1917c478bd9Sstevel@tonic-gate 19261961e0fSrobinson pl = malloc(sizeof (struct proglst)); 19361961e0fSrobinson if (pl == NULL) { 1947c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, rpc_reg_err, rpc_reg_msg, 1957c478bd9Sstevel@tonic-gate __no_mem_str); 1967c478bd9Sstevel@tonic-gate if (madenow) { 1977c478bd9Sstevel@tonic-gate SVC_DESTROY(svcxprt); 1987c478bd9Sstevel@tonic-gate free(xdrbuf); 1997c478bd9Sstevel@tonic-gate free(netid); 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate break; 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate pl->p_progname = progname; 2047c478bd9Sstevel@tonic-gate pl->p_prognum = prognum; 2057c478bd9Sstevel@tonic-gate pl->p_versnum = versnum; 2067c478bd9Sstevel@tonic-gate pl->p_procnum = procnum; 2077c478bd9Sstevel@tonic-gate pl->p_inproc = inproc; 2087c478bd9Sstevel@tonic-gate pl->p_outproc = outproc; 2097c478bd9Sstevel@tonic-gate pl->p_transp = svcxprt; 2107c478bd9Sstevel@tonic-gate pl->p_xdrbuf = xdrbuf; 2117c478bd9Sstevel@tonic-gate pl->p_recvsz = recvsz; 2127c478bd9Sstevel@tonic-gate pl->p_netid = netid; 2137c478bd9Sstevel@tonic-gate pl->p_nxt = proglst; 2147c478bd9Sstevel@tonic-gate proglst = pl; 2157c478bd9Sstevel@tonic-gate done = TRUE; 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate __rpc_endconf(handle); 21861961e0fSrobinson (void) mutex_unlock(&proglst_lock); 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate if (done == FALSE) { 2217c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, 2227c478bd9Sstevel@tonic-gate (const char *) "%s cant find suitable transport for %s", 2237c478bd9Sstevel@tonic-gate rpc_reg_msg, nettype); 2247c478bd9Sstevel@tonic-gate return (-1); 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate return (0); 2277c478bd9Sstevel@tonic-gate } 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate /* 2307c478bd9Sstevel@tonic-gate * The universal handler for the services registered using registerrpc. 2317c478bd9Sstevel@tonic-gate * It handles both the connectionless and the connection oriented cases. 2327c478bd9Sstevel@tonic-gate */ 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate static void 23561961e0fSrobinson universal(struct svc_req *rqstp, SVCXPRT *transp) 2367c478bd9Sstevel@tonic-gate { 2377c478bd9Sstevel@tonic-gate rpcprog_t prog; 2387c478bd9Sstevel@tonic-gate rpcvers_t vers; 2397c478bd9Sstevel@tonic-gate rpcproc_t proc; 2407c478bd9Sstevel@tonic-gate char *outdata; 2417c478bd9Sstevel@tonic-gate char *xdrbuf; 2427c478bd9Sstevel@tonic-gate struct proglst *pl; 2437c478bd9Sstevel@tonic-gate extern mutex_t proglst_lock; 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate /* 2467c478bd9Sstevel@tonic-gate * enforce "procnum 0 is echo" convention 2477c478bd9Sstevel@tonic-gate */ 2487c478bd9Sstevel@tonic-gate if (rqstp->rq_proc == NULLPROC) { 24961961e0fSrobinson if (svc_sendreply(transp, (xdrproc_t)xdr_void, NULL) == FALSE) { 2507c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, 2517c478bd9Sstevel@tonic-gate (const char *) "svc_sendreply failed"); 2527c478bd9Sstevel@tonic-gate } 2537c478bd9Sstevel@tonic-gate return; 2547c478bd9Sstevel@tonic-gate } 2557c478bd9Sstevel@tonic-gate prog = rqstp->rq_prog; 2567c478bd9Sstevel@tonic-gate vers = rqstp->rq_vers; 2577c478bd9Sstevel@tonic-gate proc = rqstp->rq_proc; 25861961e0fSrobinson (void) mutex_lock(&proglst_lock); 25961961e0fSrobinson for (pl = proglst; pl; pl = pl->p_nxt) { 2607c478bd9Sstevel@tonic-gate if (pl->p_prognum == prog && pl->p_procnum == proc && 2617c478bd9Sstevel@tonic-gate pl->p_versnum == vers && 2627c478bd9Sstevel@tonic-gate (strcmp(pl->p_netid, transp->xp_netid) == 0)) { 2637c478bd9Sstevel@tonic-gate /* decode arguments into a CLEAN buffer */ 2647c478bd9Sstevel@tonic-gate xdrbuf = pl->p_xdrbuf; 2657c478bd9Sstevel@tonic-gate /* Zero the arguments: reqd ! */ 2667c478bd9Sstevel@tonic-gate (void) memset(xdrbuf, 0, pl->p_recvsz); 2677c478bd9Sstevel@tonic-gate /* 2687c478bd9Sstevel@tonic-gate * Assuming that sizeof (xdrbuf) would be enough 2697c478bd9Sstevel@tonic-gate * for the arguments; if not then the program 2707c478bd9Sstevel@tonic-gate * may bomb. BEWARE! 2717c478bd9Sstevel@tonic-gate */ 2727c478bd9Sstevel@tonic-gate if (!svc_getargs(transp, pl->p_inproc, xdrbuf)) { 2737c478bd9Sstevel@tonic-gate svcerr_decode(transp); 27461961e0fSrobinson (void) mutex_unlock(&proglst_lock); 2757c478bd9Sstevel@tonic-gate return; 2767c478bd9Sstevel@tonic-gate } 2777c478bd9Sstevel@tonic-gate outdata = (*(pl->p_progname))(xdrbuf); 2787c478bd9Sstevel@tonic-gate if (outdata == NULL && 2797c478bd9Sstevel@tonic-gate pl->p_outproc != (xdrproc_t)xdr_void) { 2807c478bd9Sstevel@tonic-gate /* there was an error */ 28161961e0fSrobinson (void) mutex_unlock(&proglst_lock); 2827c478bd9Sstevel@tonic-gate return; 2837c478bd9Sstevel@tonic-gate } 2847c478bd9Sstevel@tonic-gate if (!svc_sendreply(transp, pl->p_outproc, outdata)) { 2857c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, (const char *) 2867c478bd9Sstevel@tonic-gate "rpc: rpc_reg trouble replying to prog %d vers %d", 2877c478bd9Sstevel@tonic-gate prog, vers); 28861961e0fSrobinson (void) mutex_unlock(&proglst_lock); 2897c478bd9Sstevel@tonic-gate return; 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate /* free the decoded arguments */ 2927c478bd9Sstevel@tonic-gate (void) svc_freeargs(transp, pl->p_inproc, xdrbuf); 29361961e0fSrobinson (void) mutex_unlock(&proglst_lock); 2947c478bd9Sstevel@tonic-gate return; 2957c478bd9Sstevel@tonic-gate } 29661961e0fSrobinson } 29761961e0fSrobinson (void) mutex_unlock(&proglst_lock); 2987c478bd9Sstevel@tonic-gate /* This should never happen */ 2997c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, (const char *) 3007c478bd9Sstevel@tonic-gate "rpc: rpc_reg: never registered prog %d vers %d", 3017c478bd9Sstevel@tonic-gate prog, vers); 3027c478bd9Sstevel@tonic-gate } 303