xref: /netbsd-src/lib/libc/rpc/clnt_simple.c (revision 26ba80487baf540a03edf0f75a16a427b5c4c9ab)
1*26ba8048Schristos /*	$NetBSD: clnt_simple.c,v 1.33 2015/01/20 18:31:25 christos Exp $	*/
29e15c989Scgd 
363d7b677Scgd /*
447c0e0c3Stron  * Copyright (c) 2010, Oracle America, Inc.
563d7b677Scgd  *
647c0e0c3Stron  * Redistribution and use in source and binary forms, with or without
747c0e0c3Stron  * modification, are permitted provided that the following conditions are
847c0e0c3Stron  * met:
963d7b677Scgd  *
1047c0e0c3Stron  *     * Redistributions of source code must retain the above copyright
1147c0e0c3Stron  *       notice, this list of conditions and the following disclaimer.
1247c0e0c3Stron  *     * Redistributions in binary form must reproduce the above
1347c0e0c3Stron  *       copyright notice, this list of conditions and the following
1447c0e0c3Stron  *       disclaimer in the documentation and/or other materials
1547c0e0c3Stron  *       provided with the distribution.
1647c0e0c3Stron  *     * Neither the name of the "Oracle America, Inc." nor the names of its
1747c0e0c3Stron  *       contributors may be used to endorse or promote products derived
1847c0e0c3Stron  *       from this software without specific prior written permission.
1963d7b677Scgd  *
2047c0e0c3Stron  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2147c0e0c3Stron  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2247c0e0c3Stron  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2347c0e0c3Stron  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2447c0e0c3Stron  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
2547c0e0c3Stron  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2647c0e0c3Stron  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
2747c0e0c3Stron  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2847c0e0c3Stron  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2947c0e0c3Stron  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3047c0e0c3Stron  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3147c0e0c3Stron  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3263d7b677Scgd  */
337df0ccbaSfvdl /*
347df0ccbaSfvdl  * Copyright (c) 1986-1991 by Sun Microsystems Inc.
357df0ccbaSfvdl  */
3663d7b677Scgd 
377df0ccbaSfvdl /* #ident	"@(#)clnt_simple.c	1.17	94/04/24 SMI" */
387df0ccbaSfvdl 
395c945215Sitojun #include <sys/cdefs.h>
405c945215Sitojun #if defined(LIBC_SCCS) && !defined(lint)
41c63c52b2Schristos #if 0
427df0ccbaSfvdl static char sccsid[] = "@(#)clnt_simple.c 1.49 89/01/31 Copyr 1984 Sun Micro";
435c945215Sitojun #else
44*26ba8048Schristos __RCSID("$NetBSD: clnt_simple.c,v 1.33 2015/01/20 18:31:25 christos Exp $");
45c63c52b2Schristos #endif
4663d7b677Scgd #endif
4763d7b677Scgd 
4863d7b677Scgd /*
4963d7b677Scgd  * clnt_simple.c
507df0ccbaSfvdl  * Simplified front end to client rpc.
5163d7b677Scgd  *
5263d7b677Scgd  */
5363d7b677Scgd 
5443fa6fe3Sjtc #include "namespace.h"
557df0ccbaSfvdl #include "reentrant.h"
567df0ccbaSfvdl #include <sys/param.h>
5763d7b677Scgd #include <stdio.h>
580e8cfd8fSlukem #include <assert.h>
597df0ccbaSfvdl #include <errno.h>
607df0ccbaSfvdl #include <rpc/rpc.h>
6163d7b677Scgd #include <string.h>
627df0ccbaSfvdl #include <stdlib.h>
637df0ccbaSfvdl #include <fcntl.h>
64c63c52b2Schristos #include <unistd.h>
6546e6c5e8Slukem 
6643fa6fe3Sjtc #ifdef __weak_alias
677df0ccbaSfvdl __weak_alias(rpc_call,_rpc_call)
6843fa6fe3Sjtc #endif
6943fa6fe3Sjtc 
707df0ccbaSfvdl #ifndef MAXHOSTNAMELEN
717df0ccbaSfvdl #define	MAXHOSTNAMELEN 64
727df0ccbaSfvdl #endif
7363d7b677Scgd 
747df0ccbaSfvdl #ifndef NETIDLEN
757df0ccbaSfvdl #define	NETIDLEN 32
767df0ccbaSfvdl #endif
777df0ccbaSfvdl 
787df0ccbaSfvdl struct rpc_call_private {
797df0ccbaSfvdl 	int	valid;			/* Is this entry valid ? */
807df0ccbaSfvdl 	CLIENT	*client;		/* Client handle */
817df0ccbaSfvdl 	pid_t	pid;			/* process-id at moment of creation */
827df0ccbaSfvdl 	rpcprog_t prognum;		/* Program */
837df0ccbaSfvdl 	rpcvers_t versnum;		/* Version */
847df0ccbaSfvdl 	char	host[MAXHOSTNAMELEN];	/* Servers host */
857df0ccbaSfvdl 	char	nettype[NETIDLEN];	/* Network type */
867df0ccbaSfvdl };
877df0ccbaSfvdl static struct rpc_call_private *rpc_call_private_main;
887df0ccbaSfvdl 
893fdac2b8Sthorpej #ifdef _REENTRANT
90adb74221Smatt static void rpc_call_destroy(void *);
917df0ccbaSfvdl 
927df0ccbaSfvdl static void
rpc_call_destroy(void * vp)937df0ccbaSfvdl rpc_call_destroy(void *vp)
9463d7b677Scgd {
95deb154d2Schristos 	struct rpc_call_private *rcp = (struct rpc_call_private *)vp;
967df0ccbaSfvdl 
977df0ccbaSfvdl 	if (rcp) {
987df0ccbaSfvdl 		if (rcp->client)
997df0ccbaSfvdl 			CLNT_DESTROY(rcp->client);
1007df0ccbaSfvdl 		free(rcp);
1017df0ccbaSfvdl 	}
1027df0ccbaSfvdl }
1033fdac2b8Sthorpej static thread_key_t rpc_call_key;
1043fdac2b8Sthorpej static once_t rpc_call_once = ONCE_INITIALIZER;
1053fdac2b8Sthorpej 
1063fdac2b8Sthorpej static void
rpc_call_setup(void)1073fdac2b8Sthorpej rpc_call_setup(void)
1083fdac2b8Sthorpej {
1093fdac2b8Sthorpej 
1103fdac2b8Sthorpej 	thr_keycreate(&rpc_call_key, rpc_call_destroy);
1113fdac2b8Sthorpej }
1127df0ccbaSfvdl #endif
1137df0ccbaSfvdl 
1143fdac2b8Sthorpej 
1157df0ccbaSfvdl /*
1167df0ccbaSfvdl  * This is the simplified interface to the client rpc layer.
1177df0ccbaSfvdl  * The client handle is not destroyed here and is reused for
1187df0ccbaSfvdl  * the future calls to same prog, vers, host and nettype combination.
1197df0ccbaSfvdl  *
1207df0ccbaSfvdl  * The total time available is 25 seconds.
1217df0ccbaSfvdl  */
1227df0ccbaSfvdl enum clnt_stat
rpc_call(const char * host,rpcprog_t prognum,rpcvers_t versnum,rpcproc_t procnum,xdrproc_t inproc,const char * in,xdrproc_t outproc,char * out,const char * nettype)123adb74221Smatt rpc_call(
124adb74221Smatt 	const char *	host,		/* host name */
125adb74221Smatt 	rpcprog_t	prognum,	/* program number */
126adb74221Smatt 	rpcvers_t	versnum,	/* version number */
127adb74221Smatt 	rpcproc_t	procnum,	/* procedure number */
128adb74221Smatt 	xdrproc_t	inproc,		/* in XDR procedures */
129adb74221Smatt 	const char *	in,		/* recv data */
130adb74221Smatt 	xdrproc_t	outproc,	/* out XDR procedures */
131adb74221Smatt 	char *		out,		/* send data */
132adb74221Smatt 	const char *	nettype)	/* nettype */
1337df0ccbaSfvdl {
1347df0ccbaSfvdl 	struct rpc_call_private *rcp = (struct rpc_call_private *) 0;
13563d7b677Scgd 	enum clnt_stat clnt_stat;
13663d7b677Scgd 	struct timeval timeout, tottimeout;
13763d7b677Scgd 
1380e8cfd8fSlukem 	_DIAGASSERT(host != NULL);
1390e8cfd8fSlukem 	/* XXX: in may be NULL ??? */
1400e8cfd8fSlukem 	/* XXX: out may be NULL ??? */
1410e8cfd8fSlukem 	/* XXX: nettype may be NULL ??? */
1420e8cfd8fSlukem 
1433fdac2b8Sthorpej #ifdef _REENTRANT
144*26ba8048Schristos 	if (__isthreaded) {
1453fdac2b8Sthorpej 		thr_once(&rpc_call_once, rpc_call_setup);
1463fdac2b8Sthorpej 		rcp = thr_getspecific(rpc_call_key);
147*26ba8048Schristos 	} else
1487df0ccbaSfvdl #endif
149*26ba8048Schristos 		rcp = rpc_call_private_main;
150deb154d2Schristos 	if (rcp == NULL) {
151deb154d2Schristos 		rcp = malloc(sizeof (*rcp));
152deb154d2Schristos 		if (rcp == NULL) {
1537df0ccbaSfvdl 			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
1547df0ccbaSfvdl 			rpc_createerr.cf_error.re_errno = errno;
1557df0ccbaSfvdl 			return (rpc_createerr.cf_stat);
1567df0ccbaSfvdl 		}
157*26ba8048Schristos #ifdef _REENTRANT
158*26ba8048Schristos 		if (__isthreaded)
1597df0ccbaSfvdl 			thr_setspecific(rpc_call_key, (void *) rcp);
160*26ba8048Schristos 		else
161*26ba8048Schristos #endif
162*26ba8048Schristos 			rpc_call_private_main = rcp;
1637df0ccbaSfvdl 		rcp->valid = 0;
1647df0ccbaSfvdl 		rcp->client = NULL;
1657df0ccbaSfvdl 	}
16639d7a2e3Sfvdl 	if ((nettype == NULL) || (nettype[0] == 0))
1677df0ccbaSfvdl 		nettype = "netpath";
1687df0ccbaSfvdl 	if (!(rcp->valid && rcp->pid == getpid() &&
1697df0ccbaSfvdl 		(rcp->prognum == prognum) &&
1707df0ccbaSfvdl 		(rcp->versnum == versnum) &&
1717df0ccbaSfvdl 		(!strcmp(rcp->host, host)) &&
1727df0ccbaSfvdl 		(!strcmp(rcp->nettype, nettype)))) {
1737df0ccbaSfvdl 		int fd;
1747df0ccbaSfvdl 
1757df0ccbaSfvdl 		rcp->valid = 0;
1767df0ccbaSfvdl 		if (rcp->client)
1777df0ccbaSfvdl 			CLNT_DESTROY(rcp->client);
1787df0ccbaSfvdl 		/*
1797df0ccbaSfvdl 		 * Using the first successful transport for that type
1807df0ccbaSfvdl 		 */
1817df0ccbaSfvdl 		rcp->client = clnt_create(host, prognum, versnum, nettype);
1827df0ccbaSfvdl 		rcp->pid = getpid();
183deb154d2Schristos 		if (rcp->client == NULL) {
1847df0ccbaSfvdl 			return (rpc_createerr.cf_stat);
1857df0ccbaSfvdl 		}
1867df0ccbaSfvdl 		/*
1877df0ccbaSfvdl 		 * Set time outs for connectionless case.  Do it
1887df0ccbaSfvdl 		 * unconditionally.  Faster than doing a t_getinfo()
1897df0ccbaSfvdl 		 * and then doing the right thing.
1907df0ccbaSfvdl 		 */
19163d7b677Scgd 		timeout.tv_usec = 0;
19263d7b677Scgd 		timeout.tv_sec = 5;
1937df0ccbaSfvdl 		(void) CLNT_CONTROL(rcp->client,
194deb154d2Schristos 				CLSET_RETRY_TIMEOUT, (char *)(void *)&timeout);
195deb154d2Schristos 		if (CLNT_CONTROL(rcp->client, CLGET_FD, (char *)(void *)&fd))
19667657e2fSchristos 			(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
1977df0ccbaSfvdl 		rcp->prognum = prognum;
1987df0ccbaSfvdl 		rcp->versnum = versnum;
1997df0ccbaSfvdl 		if ((strlen(host) < (size_t)MAXHOSTNAMELEN) &&
2007df0ccbaSfvdl 		    (strlen(nettype) < (size_t)NETIDLEN)) {
2017df0ccbaSfvdl 			(void) strcpy(rcp->host, host);
2027df0ccbaSfvdl 			(void) strcpy(rcp->nettype, nettype);
2037df0ccbaSfvdl 			rcp->valid = 1;
2047df0ccbaSfvdl 		} else {
2057df0ccbaSfvdl 			rcp->valid = 0;
20663d7b677Scgd 		}
2077df0ccbaSfvdl 	} /* else reuse old client */
20863d7b677Scgd 	tottimeout.tv_sec = 25;
20963d7b677Scgd 	tottimeout.tv_usec = 0;
210347f995cSyamt 	clnt_stat = CLNT_CALL(rcp->client, procnum, inproc, in,
211deb154d2Schristos 	    outproc, out, tottimeout);
21263d7b677Scgd 	/*
21363d7b677Scgd 	 * if call failed, empty cache
21463d7b677Scgd 	 */
21563d7b677Scgd 	if (clnt_stat != RPC_SUCCESS)
2167df0ccbaSfvdl 		rcp->valid = 0;
2177df0ccbaSfvdl 	return (clnt_stat);
21863d7b677Scgd }
219