xref: /freebsd/lib/libc/rpc/clnt_simple.c (revision dc36d6f9bb1753f3808552f3afd30eda9a7b206a)
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