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 /*
3799064799SGarrett Wollman * clnt_simple.c
388360efbdSAlfred Perlstein * Simplified front end to client rpc.
3999064799SGarrett Wollman *
4099064799SGarrett Wollman */
4199064799SGarrett Wollman
42d201fe46SDaniel Eischen #include "namespace.h"
439f5afc13SIan Dowse #include "reentrant.h"
440ab74c6fSPeter Wemm #include <sys/param.h>
4599064799SGarrett Wollman #include <stdio.h>
468360efbdSAlfred Perlstein #include <errno.h>
4799064799SGarrett Wollman #include <rpc/rpc.h>
488360efbdSAlfred Perlstein #include <string.h>
498360efbdSAlfred Perlstein #include <stdlib.h>
508360efbdSAlfred Perlstein #include <fcntl.h>
518360efbdSAlfred Perlstein #include <unistd.h>
52d201fe46SDaniel Eischen #include "un-namespace.h"
53235baf26SDaniel Eischen #include "mt_misc.h"
5499064799SGarrett Wollman
558360efbdSAlfred Perlstein #ifndef MAXHOSTNAMELEN
568360efbdSAlfred Perlstein #define MAXHOSTNAMELEN 64
578360efbdSAlfred Perlstein #endif
5899064799SGarrett Wollman
598360efbdSAlfred Perlstein #ifndef NETIDLEN
608360efbdSAlfred Perlstein #define NETIDLEN 32
618360efbdSAlfred Perlstein #endif
628360efbdSAlfred Perlstein
638360efbdSAlfred Perlstein struct rpc_call_private {
648360efbdSAlfred Perlstein int valid; /* Is this entry valid ? */
658360efbdSAlfred Perlstein CLIENT *client; /* Client handle */
668360efbdSAlfred Perlstein pid_t pid; /* process-id at moment of creation */
678360efbdSAlfred Perlstein rpcprog_t prognum; /* Program */
688360efbdSAlfred Perlstein rpcvers_t versnum; /* Version */
698360efbdSAlfred Perlstein char host[MAXHOSTNAMELEN]; /* Servers host */
708360efbdSAlfred Perlstein char nettype[NETIDLEN]; /* Network type */
718360efbdSAlfred Perlstein };
728360efbdSAlfred Perlstein static struct rpc_call_private *rpc_call_private_main;
736f88d2a8SJohn Baldwin static thread_key_t rpc_call_key;
746f88d2a8SJohn Baldwin static once_t rpc_call_once = ONCE_INITIALIZER;
756f88d2a8SJohn Baldwin static int rpc_call_key_error;
768360efbdSAlfred Perlstein
776f88d2a8SJohn Baldwin static void rpc_call_key_init(void);
78c05ac53bSDavid E. O'Brien static void rpc_call_destroy(void *);
798360efbdSAlfred Perlstein
808360efbdSAlfred Perlstein static void
rpc_call_destroy(void * vp)818360efbdSAlfred Perlstein rpc_call_destroy(void *vp)
8299064799SGarrett Wollman {
838360efbdSAlfred Perlstein struct rpc_call_private *rcp = (struct rpc_call_private *)vp;
8499064799SGarrett Wollman
858360efbdSAlfred Perlstein if (rcp) {
868360efbdSAlfred Perlstein if (rcp->client)
878360efbdSAlfred Perlstein CLNT_DESTROY(rcp->client);
888360efbdSAlfred Perlstein free(rcp);
8999064799SGarrett Wollman }
9099064799SGarrett Wollman }
918360efbdSAlfred Perlstein
926f88d2a8SJohn Baldwin static void
rpc_call_key_init(void)936f88d2a8SJohn Baldwin rpc_call_key_init(void)
946f88d2a8SJohn Baldwin {
956f88d2a8SJohn Baldwin
966f88d2a8SJohn Baldwin rpc_call_key_error = thr_keycreate(&rpc_call_key, rpc_call_destroy);
976f88d2a8SJohn Baldwin }
986f88d2a8SJohn Baldwin
998360efbdSAlfred Perlstein /*
1008360efbdSAlfred Perlstein * This is the simplified interface to the client rpc layer.
1018360efbdSAlfred Perlstein * The client handle is not destroyed here and is reused for
1028360efbdSAlfred Perlstein * the future calls to same prog, vers, host and nettype combination.
1038360efbdSAlfred Perlstein *
1048360efbdSAlfred Perlstein * The total time available is 25 seconds.
105587cf682SCraig Rodrigues *
106587cf682SCraig Rodrigues * host - host name
107587cf682SCraig Rodrigues * prognum - program number
108587cf682SCraig Rodrigues * versnum - version number
109587cf682SCraig Rodrigues * procnum - procedure number
110587cf682SCraig Rodrigues * inproc, outproc - in/out XDR procedures
111587cf682SCraig Rodrigues * in, out - recv/send data
112587cf682SCraig Rodrigues * nettype - nettype
1138360efbdSAlfred Perlstein */
1148360efbdSAlfred Perlstein enum clnt_stat
rpc_call(const char * host,const rpcprog_t prognum,const rpcvers_t versnum,const rpcproc_t procnum,const xdrproc_t inproc,const char * in,const xdrproc_t outproc,char * out,const char * nettype)115587cf682SCraig Rodrigues rpc_call(const char *host, const rpcprog_t prognum, const rpcvers_t versnum,
116587cf682SCraig Rodrigues const rpcproc_t procnum, const xdrproc_t inproc, const char *in,
117587cf682SCraig Rodrigues const xdrproc_t outproc, char *out, const char *nettype)
1188360efbdSAlfred Perlstein {
1198360efbdSAlfred Perlstein struct rpc_call_private *rcp = (struct rpc_call_private *) 0;
1208360efbdSAlfred Perlstein enum clnt_stat clnt_stat;
1218360efbdSAlfred Perlstein struct timeval timeout, tottimeout;
1228360efbdSAlfred Perlstein int main_thread = 1;
1238360efbdSAlfred Perlstein
1248360efbdSAlfred Perlstein if ((main_thread = thr_main())) {
1258360efbdSAlfred Perlstein rcp = rpc_call_private_main;
12699064799SGarrett Wollman } else {
1276f88d2a8SJohn Baldwin if (thr_once(&rpc_call_once, rpc_call_key_init) != 0 ||
1286f88d2a8SJohn Baldwin rpc_call_key_error != 0) {
1296f88d2a8SJohn Baldwin rpc_createerr.cf_stat = RPC_SYSTEMERROR;
1306f88d2a8SJohn Baldwin rpc_createerr.cf_error.re_errno = rpc_call_key_error;
1316f88d2a8SJohn Baldwin return (rpc_createerr.cf_stat);
13299064799SGarrett Wollman }
1338360efbdSAlfred Perlstein rcp = (struct rpc_call_private *)thr_getspecific(rpc_call_key);
1348360efbdSAlfred Perlstein }
1358360efbdSAlfred Perlstein if (rcp == NULL) {
1368360efbdSAlfred Perlstein rcp = malloc(sizeof (*rcp));
1378360efbdSAlfred Perlstein if (rcp == NULL) {
1388360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_SYSTEMERROR;
1398360efbdSAlfred Perlstein rpc_createerr.cf_error.re_errno = errno;
1408360efbdSAlfred Perlstein return (rpc_createerr.cf_stat);
1418360efbdSAlfred Perlstein }
1428360efbdSAlfred Perlstein if (main_thread)
1438360efbdSAlfred Perlstein rpc_call_private_main = rcp;
1448360efbdSAlfred Perlstein else
1458360efbdSAlfred Perlstein thr_setspecific(rpc_call_key, (void *) rcp);
1468360efbdSAlfred Perlstein rcp->valid = 0;
1478360efbdSAlfred Perlstein rcp->client = NULL;
1488360efbdSAlfred Perlstein }
1492ad99b72SMartin Blapp if ((nettype == NULL) || (nettype[0] == 0))
1508360efbdSAlfred Perlstein nettype = "netpath";
1518360efbdSAlfred Perlstein if (!(rcp->valid && rcp->pid == getpid() &&
1528360efbdSAlfred Perlstein (rcp->prognum == prognum) &&
1538360efbdSAlfred Perlstein (rcp->versnum == versnum) &&
1548360efbdSAlfred Perlstein (!strcmp(rcp->host, host)) &&
1558360efbdSAlfred Perlstein (!strcmp(rcp->nettype, nettype)))) {
1568360efbdSAlfred Perlstein int fd;
1578360efbdSAlfred Perlstein
1588360efbdSAlfred Perlstein rcp->valid = 0;
1598360efbdSAlfred Perlstein if (rcp->client)
1608360efbdSAlfred Perlstein CLNT_DESTROY(rcp->client);
1618360efbdSAlfred Perlstein /*
1628360efbdSAlfred Perlstein * Using the first successful transport for that type
1638360efbdSAlfred Perlstein */
1648360efbdSAlfred Perlstein rcp->client = clnt_create(host, prognum, versnum, nettype);
1658360efbdSAlfred Perlstein rcp->pid = getpid();
1668360efbdSAlfred Perlstein if (rcp->client == NULL) {
1678360efbdSAlfred Perlstein return (rpc_createerr.cf_stat);
1688360efbdSAlfred Perlstein }
1698360efbdSAlfred Perlstein /*
1708360efbdSAlfred Perlstein * Set time outs for connectionless case. Do it
1718360efbdSAlfred Perlstein * unconditionally. Faster than doing a t_getinfo()
1728360efbdSAlfred Perlstein * and then doing the right thing.
1738360efbdSAlfred Perlstein */
17499064799SGarrett Wollman timeout.tv_usec = 0;
17599064799SGarrett Wollman timeout.tv_sec = 5;
1768360efbdSAlfred Perlstein (void) CLNT_CONTROL(rcp->client,
1778360efbdSAlfred Perlstein CLSET_RETRY_TIMEOUT, (char *)(void *)&timeout);
1788360efbdSAlfred Perlstein if (CLNT_CONTROL(rcp->client, CLGET_FD, (char *)(void *)&fd))
1798360efbdSAlfred Perlstein _fcntl(fd, F_SETFD, 1); /* make it "close on exec" */
1808360efbdSAlfred Perlstein rcp->prognum = prognum;
1818360efbdSAlfred Perlstein rcp->versnum = versnum;
1828360efbdSAlfred Perlstein if ((strlen(host) < (size_t)MAXHOSTNAMELEN) &&
1838360efbdSAlfred Perlstein (strlen(nettype) < (size_t)NETIDLEN)) {
1848360efbdSAlfred Perlstein (void) strcpy(rcp->host, host);
1858360efbdSAlfred Perlstein (void) strcpy(rcp->nettype, nettype);
1868360efbdSAlfred Perlstein rcp->valid = 1;
1878360efbdSAlfred Perlstein } else {
1888360efbdSAlfred Perlstein rcp->valid = 0;
18999064799SGarrett Wollman }
1908360efbdSAlfred Perlstein } /* else reuse old client */
19199064799SGarrett Wollman tottimeout.tv_sec = 25;
19299064799SGarrett Wollman tottimeout.tv_usec = 0;
1938360efbdSAlfred Perlstein /*LINTED const castaway*/
1948360efbdSAlfred Perlstein clnt_stat = CLNT_CALL(rcp->client, procnum, inproc, (char *) in,
19599064799SGarrett Wollman outproc, out, tottimeout);
19699064799SGarrett Wollman /*
19799064799SGarrett Wollman * if call failed, empty cache
19899064799SGarrett Wollman */
19999064799SGarrett Wollman if (clnt_stat != RPC_SUCCESS)
2008360efbdSAlfred Perlstein rcp->valid = 0;
2018360efbdSAlfred Perlstein return (clnt_stat);
20299064799SGarrett Wollman }
203