18360efbdSAlfred Perlstein /* $NetBSD: clnt_simple.c,v 1.21 2000/07/06 03:10:34 christos Exp $ */ 28360efbdSAlfred Perlstein 32e322d37SHiroki Sato /*- 4*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 5*8a16b7a1SPedro F. Giffuni * 62e322d37SHiroki Sato * Copyright (c) 2009, Sun Microsystems, Inc. 72e322d37SHiroki Sato * All rights reserved. 899064799SGarrett Wollman * 92e322d37SHiroki Sato * Redistribution and use in source and binary forms, with or without 102e322d37SHiroki Sato * modification, are permitted provided that the following conditions are met: 112e322d37SHiroki Sato * - Redistributions of source code must retain the above copyright notice, 122e322d37SHiroki Sato * this list of conditions and the following disclaimer. 132e322d37SHiroki Sato * - Redistributions in binary form must reproduce the above copyright notice, 142e322d37SHiroki Sato * this list of conditions and the following disclaimer in the documentation 152e322d37SHiroki Sato * and/or other materials provided with the distribution. 162e322d37SHiroki Sato * - Neither the name of Sun Microsystems, Inc. nor the names of its 172e322d37SHiroki Sato * contributors may be used to endorse or promote products derived 182e322d37SHiroki Sato * from this software without specific prior written permission. 1999064799SGarrett Wollman * 202e322d37SHiroki Sato * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 212e322d37SHiroki Sato * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 222e322d37SHiroki Sato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 232e322d37SHiroki Sato * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 242e322d37SHiroki Sato * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 252e322d37SHiroki Sato * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 262e322d37SHiroki Sato * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 272e322d37SHiroki Sato * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 282e322d37SHiroki Sato * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 292e322d37SHiroki Sato * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 302e322d37SHiroki Sato * POSSIBILITY OF SUCH DAMAGE. 3199064799SGarrett Wollman */ 328360efbdSAlfred Perlstein /* 338360efbdSAlfred Perlstein * Copyright (c) 1986-1991 by Sun Microsystems Inc. 348360efbdSAlfred Perlstein */ 3599064799SGarrett Wollman 3699064799SGarrett Wollman #if defined(LIBC_SCCS) && !defined(lint) 37a986ef57SDavid E. O'Brien static char *sccsid2 = "from: @(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro"; 38d3d20c82SDavid E. O'Brien static char *sccsid = "from: @(#)clnt_simple.c 2.2 88/08/01 4.0 RPCSRC"; 3999064799SGarrett Wollman #endif 40d3d20c82SDavid E. O'Brien #include <sys/cdefs.h> 41d3d20c82SDavid E. O'Brien __FBSDID("$FreeBSD$"); 4299064799SGarrett Wollman 4399064799SGarrett Wollman /* 4499064799SGarrett Wollman * clnt_simple.c 458360efbdSAlfred Perlstein * Simplified front end to client rpc. 4699064799SGarrett Wollman * 4799064799SGarrett Wollman */ 4899064799SGarrett Wollman 49d201fe46SDaniel Eischen #include "namespace.h" 509f5afc13SIan Dowse #include "reentrant.h" 510ab74c6fSPeter Wemm #include <sys/param.h> 5299064799SGarrett Wollman #include <stdio.h> 538360efbdSAlfred Perlstein #include <errno.h> 5499064799SGarrett Wollman #include <rpc/rpc.h> 558360efbdSAlfred Perlstein #include <string.h> 568360efbdSAlfred Perlstein #include <stdlib.h> 578360efbdSAlfred Perlstein #include <fcntl.h> 588360efbdSAlfred Perlstein #include <unistd.h> 59d201fe46SDaniel Eischen #include "un-namespace.h" 60235baf26SDaniel Eischen #include "mt_misc.h" 6199064799SGarrett Wollman 628360efbdSAlfred Perlstein #ifndef MAXHOSTNAMELEN 638360efbdSAlfred Perlstein #define MAXHOSTNAMELEN 64 648360efbdSAlfred Perlstein #endif 6599064799SGarrett Wollman 668360efbdSAlfred Perlstein #ifndef NETIDLEN 678360efbdSAlfred Perlstein #define NETIDLEN 32 688360efbdSAlfred Perlstein #endif 698360efbdSAlfred Perlstein 708360efbdSAlfred Perlstein struct rpc_call_private { 718360efbdSAlfred Perlstein int valid; /* Is this entry valid ? */ 728360efbdSAlfred Perlstein CLIENT *client; /* Client handle */ 738360efbdSAlfred Perlstein pid_t pid; /* process-id at moment of creation */ 748360efbdSAlfred Perlstein rpcprog_t prognum; /* Program */ 758360efbdSAlfred Perlstein rpcvers_t versnum; /* Version */ 768360efbdSAlfred Perlstein char host[MAXHOSTNAMELEN]; /* Servers host */ 778360efbdSAlfred Perlstein char nettype[NETIDLEN]; /* Network type */ 788360efbdSAlfred Perlstein }; 798360efbdSAlfred Perlstein static struct rpc_call_private *rpc_call_private_main; 806f88d2a8SJohn Baldwin static thread_key_t rpc_call_key; 816f88d2a8SJohn Baldwin static once_t rpc_call_once = ONCE_INITIALIZER; 826f88d2a8SJohn Baldwin static int rpc_call_key_error; 838360efbdSAlfred Perlstein 846f88d2a8SJohn Baldwin static void rpc_call_key_init(void); 85c05ac53bSDavid E. O'Brien static void rpc_call_destroy(void *); 868360efbdSAlfred Perlstein 878360efbdSAlfred Perlstein static void 888360efbdSAlfred Perlstein rpc_call_destroy(void *vp) 8999064799SGarrett Wollman { 908360efbdSAlfred Perlstein struct rpc_call_private *rcp = (struct rpc_call_private *)vp; 9199064799SGarrett Wollman 928360efbdSAlfred Perlstein if (rcp) { 938360efbdSAlfred Perlstein if (rcp->client) 948360efbdSAlfred Perlstein CLNT_DESTROY(rcp->client); 958360efbdSAlfred Perlstein free(rcp); 9699064799SGarrett Wollman } 9799064799SGarrett Wollman } 988360efbdSAlfred Perlstein 996f88d2a8SJohn Baldwin static void 1006f88d2a8SJohn Baldwin rpc_call_key_init(void) 1016f88d2a8SJohn Baldwin { 1026f88d2a8SJohn Baldwin 1036f88d2a8SJohn Baldwin rpc_call_key_error = thr_keycreate(&rpc_call_key, rpc_call_destroy); 1046f88d2a8SJohn Baldwin } 1056f88d2a8SJohn Baldwin 1068360efbdSAlfred Perlstein /* 1078360efbdSAlfred Perlstein * This is the simplified interface to the client rpc layer. 1088360efbdSAlfred Perlstein * The client handle is not destroyed here and is reused for 1098360efbdSAlfred Perlstein * the future calls to same prog, vers, host and nettype combination. 1108360efbdSAlfred Perlstein * 1118360efbdSAlfred Perlstein * The total time available is 25 seconds. 112587cf682SCraig Rodrigues * 113587cf682SCraig Rodrigues * host - host name 114587cf682SCraig Rodrigues * prognum - program number 115587cf682SCraig Rodrigues * versnum - version number 116587cf682SCraig Rodrigues * procnum - procedure number 117587cf682SCraig Rodrigues * inproc, outproc - in/out XDR procedures 118587cf682SCraig Rodrigues * in, out - recv/send data 119587cf682SCraig Rodrigues * nettype - nettype 1208360efbdSAlfred Perlstein */ 1218360efbdSAlfred Perlstein enum clnt_stat 122587cf682SCraig Rodrigues rpc_call(const char *host, const rpcprog_t prognum, const rpcvers_t versnum, 123587cf682SCraig Rodrigues const rpcproc_t procnum, const xdrproc_t inproc, const char *in, 124587cf682SCraig Rodrigues const xdrproc_t outproc, char *out, const char *nettype) 1258360efbdSAlfred Perlstein { 1268360efbdSAlfred Perlstein struct rpc_call_private *rcp = (struct rpc_call_private *) 0; 1278360efbdSAlfred Perlstein enum clnt_stat clnt_stat; 1288360efbdSAlfred Perlstein struct timeval timeout, tottimeout; 1298360efbdSAlfred Perlstein int main_thread = 1; 1308360efbdSAlfred Perlstein 1318360efbdSAlfred Perlstein if ((main_thread = thr_main())) { 1328360efbdSAlfred Perlstein rcp = rpc_call_private_main; 13399064799SGarrett Wollman } else { 1346f88d2a8SJohn Baldwin if (thr_once(&rpc_call_once, rpc_call_key_init) != 0 || 1356f88d2a8SJohn Baldwin rpc_call_key_error != 0) { 1366f88d2a8SJohn Baldwin rpc_createerr.cf_stat = RPC_SYSTEMERROR; 1376f88d2a8SJohn Baldwin rpc_createerr.cf_error.re_errno = rpc_call_key_error; 1386f88d2a8SJohn Baldwin return (rpc_createerr.cf_stat); 13999064799SGarrett Wollman } 1408360efbdSAlfred Perlstein rcp = (struct rpc_call_private *)thr_getspecific(rpc_call_key); 1418360efbdSAlfred Perlstein } 1428360efbdSAlfred Perlstein if (rcp == NULL) { 1438360efbdSAlfred Perlstein rcp = malloc(sizeof (*rcp)); 1448360efbdSAlfred Perlstein if (rcp == NULL) { 1458360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_SYSTEMERROR; 1468360efbdSAlfred Perlstein rpc_createerr.cf_error.re_errno = errno; 1478360efbdSAlfred Perlstein return (rpc_createerr.cf_stat); 1488360efbdSAlfred Perlstein } 1498360efbdSAlfred Perlstein if (main_thread) 1508360efbdSAlfred Perlstein rpc_call_private_main = rcp; 1518360efbdSAlfred Perlstein else 1528360efbdSAlfred Perlstein thr_setspecific(rpc_call_key, (void *) rcp); 1538360efbdSAlfred Perlstein rcp->valid = 0; 1548360efbdSAlfred Perlstein rcp->client = NULL; 1558360efbdSAlfred Perlstein } 1562ad99b72SMartin Blapp if ((nettype == NULL) || (nettype[0] == 0)) 1578360efbdSAlfred Perlstein nettype = "netpath"; 1588360efbdSAlfred Perlstein if (!(rcp->valid && rcp->pid == getpid() && 1598360efbdSAlfred Perlstein (rcp->prognum == prognum) && 1608360efbdSAlfred Perlstein (rcp->versnum == versnum) && 1618360efbdSAlfred Perlstein (!strcmp(rcp->host, host)) && 1628360efbdSAlfred Perlstein (!strcmp(rcp->nettype, nettype)))) { 1638360efbdSAlfred Perlstein int fd; 1648360efbdSAlfred Perlstein 1658360efbdSAlfred Perlstein rcp->valid = 0; 1668360efbdSAlfred Perlstein if (rcp->client) 1678360efbdSAlfred Perlstein CLNT_DESTROY(rcp->client); 1688360efbdSAlfred Perlstein /* 1698360efbdSAlfred Perlstein * Using the first successful transport for that type 1708360efbdSAlfred Perlstein */ 1718360efbdSAlfred Perlstein rcp->client = clnt_create(host, prognum, versnum, nettype); 1728360efbdSAlfred Perlstein rcp->pid = getpid(); 1738360efbdSAlfred Perlstein if (rcp->client == NULL) { 1748360efbdSAlfred Perlstein return (rpc_createerr.cf_stat); 1758360efbdSAlfred Perlstein } 1768360efbdSAlfred Perlstein /* 1778360efbdSAlfred Perlstein * Set time outs for connectionless case. Do it 1788360efbdSAlfred Perlstein * unconditionally. Faster than doing a t_getinfo() 1798360efbdSAlfred Perlstein * and then doing the right thing. 1808360efbdSAlfred Perlstein */ 18199064799SGarrett Wollman timeout.tv_usec = 0; 18299064799SGarrett Wollman timeout.tv_sec = 5; 1838360efbdSAlfred Perlstein (void) CLNT_CONTROL(rcp->client, 1848360efbdSAlfred Perlstein CLSET_RETRY_TIMEOUT, (char *)(void *)&timeout); 1858360efbdSAlfred Perlstein if (CLNT_CONTROL(rcp->client, CLGET_FD, (char *)(void *)&fd)) 1868360efbdSAlfred Perlstein _fcntl(fd, F_SETFD, 1); /* make it "close on exec" */ 1878360efbdSAlfred Perlstein rcp->prognum = prognum; 1888360efbdSAlfred Perlstein rcp->versnum = versnum; 1898360efbdSAlfred Perlstein if ((strlen(host) < (size_t)MAXHOSTNAMELEN) && 1908360efbdSAlfred Perlstein (strlen(nettype) < (size_t)NETIDLEN)) { 1918360efbdSAlfred Perlstein (void) strcpy(rcp->host, host); 1928360efbdSAlfred Perlstein (void) strcpy(rcp->nettype, nettype); 1938360efbdSAlfred Perlstein rcp->valid = 1; 1948360efbdSAlfred Perlstein } else { 1958360efbdSAlfred Perlstein rcp->valid = 0; 19699064799SGarrett Wollman } 1978360efbdSAlfred Perlstein } /* else reuse old client */ 19899064799SGarrett Wollman tottimeout.tv_sec = 25; 19999064799SGarrett Wollman tottimeout.tv_usec = 0; 2008360efbdSAlfred Perlstein /*LINTED const castaway*/ 2018360efbdSAlfred Perlstein clnt_stat = CLNT_CALL(rcp->client, procnum, inproc, (char *) in, 20299064799SGarrett Wollman outproc, out, tottimeout); 20399064799SGarrett Wollman /* 20499064799SGarrett Wollman * if call failed, empty cache 20599064799SGarrett Wollman */ 20699064799SGarrett Wollman if (clnt_stat != RPC_SUCCESS) 2078360efbdSAlfred Perlstein rcp->valid = 0; 2088360efbdSAlfred Perlstein return (clnt_stat); 20999064799SGarrett Wollman } 210