xref: /freebsd/lib/libc/rpc/clnt_generic.c (revision 8360efbd6c932013ffdb2f83d2f2de4278febb5e)
18360efbdSAlfred Perlstein /*	$NetBSD: clnt_generic.c,v 1.18 2000/07/06 03:10:34 christos Exp $	*/
28360efbdSAlfred Perlstein 
399064799SGarrett Wollman /*
499064799SGarrett Wollman  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
599064799SGarrett Wollman  * unrestricted use provided that this legend is included on all tape
699064799SGarrett Wollman  * media and as a part of the software program in whole or part.  Users
799064799SGarrett Wollman  * may copy or modify Sun RPC without charge, but are not authorized
899064799SGarrett Wollman  * to license or distribute it to anyone else except as part of a product or
999064799SGarrett Wollman  * program developed by the user.
1099064799SGarrett Wollman  *
1199064799SGarrett Wollman  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
1299064799SGarrett Wollman  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
1399064799SGarrett Wollman  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
1499064799SGarrett Wollman  *
1599064799SGarrett Wollman  * Sun RPC is provided with no support and without any obligation on the
1699064799SGarrett Wollman  * part of Sun Microsystems, Inc. to assist in its use, correction,
1799064799SGarrett Wollman  * modification or enhancement.
1899064799SGarrett Wollman  *
1999064799SGarrett Wollman  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
2099064799SGarrett Wollman  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
2199064799SGarrett Wollman  * OR ANY PART THEREOF.
2299064799SGarrett Wollman  *
2399064799SGarrett Wollman  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
2499064799SGarrett Wollman  * or profits or other special, indirect and consequential damages, even if
2599064799SGarrett Wollman  * Sun has been advised of the possibility of such damages.
2699064799SGarrett Wollman  *
2799064799SGarrett Wollman  * Sun Microsystems, Inc.
2899064799SGarrett Wollman  * 2550 Garcia Avenue
2999064799SGarrett Wollman  * Mountain View, California  94043
3099064799SGarrett Wollman  */
3199064799SGarrett Wollman 
328360efbdSAlfred Perlstein /* #ident	"@(#)clnt_generic.c	1.20	94/05/03 SMI" */
338360efbdSAlfred Perlstein 
3499064799SGarrett Wollman #if defined(LIBC_SCCS) && !defined(lint)
3599064799SGarrett Wollman /*static char *sccsid = "from: @(#)clnt_generic.c 1.4 87/08/11 (C) 1987 SMI";*/
3699064799SGarrett Wollman /*static char *sccsid = "from: @(#)clnt_generic.c	2.2 88/08/01 4.0 RPCSRC";*/
377f3dea24SPeter Wemm static char *rcsid = "$FreeBSD$";
3899064799SGarrett Wollman #endif
3999064799SGarrett Wollman 
4099064799SGarrett Wollman /*
418360efbdSAlfred Perlstein  * Copyright (c) 1986-1991 by Sun Microsystems Inc.
4299064799SGarrett Wollman  */
438360efbdSAlfred Perlstein #include "reentrant.h"
448360efbdSAlfred Perlstein #include "namespace.h"
458360efbdSAlfred Perlstein #include <sys/types.h>
4699064799SGarrett Wollman #include <sys/socket.h>
478360efbdSAlfred Perlstein #include <netinet/in.h>
488360efbdSAlfred Perlstein #include <netinet/tcp.h>
498360efbdSAlfred Perlstein #include <stdio.h>
50d201fe46SDaniel Eischen #include <errno.h>
5199064799SGarrett Wollman #include <netdb.h>
528360efbdSAlfred Perlstein #include <rpc/rpc.h>
538360efbdSAlfred Perlstein #include <rpc/nettype.h>
544c3af266SPoul-Henning Kamp #include <string.h>
558360efbdSAlfred Perlstein #include <stdlib.h>
568360efbdSAlfred Perlstein #include <unistd.h>
578360efbdSAlfred Perlstein #include "un-namespace.h"
588360efbdSAlfred Perlstein #include "rpc_com.h"
5999064799SGarrett Wollman 
6099064799SGarrett Wollman /*
618360efbdSAlfred Perlstein  * Generic client creation with version checking the value of
628360efbdSAlfred Perlstein  * vers_out is set to the highest server supported value
638360efbdSAlfred Perlstein  * vers_low <= vers_out <= vers_high  AND an error results
648360efbdSAlfred Perlstein  * if this can not be done.
6599064799SGarrett Wollman  */
6699064799SGarrett Wollman CLIENT *
678360efbdSAlfred Perlstein clnt_create_vers(hostname, prog, vers_out, vers_low, vers_high, nettype)
688360efbdSAlfred Perlstein 	const char *hostname;
698360efbdSAlfred Perlstein 	rpcprog_t prog;
708360efbdSAlfred Perlstein 	rpcvers_t *vers_out;
718360efbdSAlfred Perlstein 	rpcvers_t vers_low;
728360efbdSAlfred Perlstein 	rpcvers_t vers_high;
738360efbdSAlfred Perlstein 	const char *nettype;
7499064799SGarrett Wollman {
758360efbdSAlfred Perlstein 	CLIENT *clnt;
768360efbdSAlfred Perlstein 	struct timeval to;
778360efbdSAlfred Perlstein 	enum clnt_stat rpc_stat;
788360efbdSAlfred Perlstein 	struct rpc_err rpcerr;
7999064799SGarrett Wollman 
808360efbdSAlfred Perlstein 	clnt = clnt_create(hostname, prog, vers_high, nettype);
818360efbdSAlfred Perlstein 	if (clnt == NULL) {
8299064799SGarrett Wollman 		return (NULL);
8399064799SGarrett Wollman 	}
848360efbdSAlfred Perlstein 	to.tv_sec = 10;
858360efbdSAlfred Perlstein 	to.tv_usec = 0;
868360efbdSAlfred Perlstein 	rpc_stat = clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void,
878360efbdSAlfred Perlstein 			(char *) NULL, (xdrproc_t) xdr_void, (char *) NULL, to);
888360efbdSAlfred Perlstein 	if (rpc_stat == RPC_SUCCESS) {
898360efbdSAlfred Perlstein 		*vers_out = vers_high;
908360efbdSAlfred Perlstein 		return (clnt);
918360efbdSAlfred Perlstein 	}
928360efbdSAlfred Perlstein 	if (rpc_stat == RPC_PROGVERSMISMATCH) {
938360efbdSAlfred Perlstein 		unsigned long minvers, maxvers;
948360efbdSAlfred Perlstein 
958360efbdSAlfred Perlstein 		clnt_geterr(clnt, &rpcerr);
968360efbdSAlfred Perlstein 		minvers = rpcerr.re_vers.low;
978360efbdSAlfred Perlstein 		maxvers = rpcerr.re_vers.high;
988360efbdSAlfred Perlstein 		if (maxvers < vers_high)
998360efbdSAlfred Perlstein 			vers_high = (rpcvers_t)maxvers;
1008360efbdSAlfred Perlstein 		if (minvers > vers_low)
1018360efbdSAlfred Perlstein 			vers_low = (rpcvers_t)minvers;
1028360efbdSAlfred Perlstein 		if (vers_low > vers_high) {
1038360efbdSAlfred Perlstein 			goto error;
1048360efbdSAlfred Perlstein 		}
1058360efbdSAlfred Perlstein 		CLNT_CONTROL(clnt, CLSET_VERS, (char *)(void *)&vers_high);
1068360efbdSAlfred Perlstein 		rpc_stat = clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void,
1078360efbdSAlfred Perlstein 				(char *) NULL, (xdrproc_t) xdr_void,
1088360efbdSAlfred Perlstein 				(char *) NULL, to);
1098360efbdSAlfred Perlstein 		if (rpc_stat == RPC_SUCCESS) {
1108360efbdSAlfred Perlstein 			*vers_out = vers_high;
1118360efbdSAlfred Perlstein 			return (clnt);
1128360efbdSAlfred Perlstein 		}
1138360efbdSAlfred Perlstein 	}
1148360efbdSAlfred Perlstein 	clnt_geterr(clnt, &rpcerr);
1158360efbdSAlfred Perlstein 
1168360efbdSAlfred Perlstein error:
1178360efbdSAlfred Perlstein 	rpc_createerr.cf_stat = rpc_stat;
1188360efbdSAlfred Perlstein 	rpc_createerr.cf_error = rpcerr;
1198360efbdSAlfred Perlstein 	clnt_destroy(clnt);
1208360efbdSAlfred Perlstein 	return (NULL);
1218360efbdSAlfred Perlstein }
1228360efbdSAlfred Perlstein 
12399064799SGarrett Wollman /*
1248360efbdSAlfred Perlstein  * Top level client creation routine.
1258360efbdSAlfred Perlstein  * Generic client creation: takes (servers name, program-number, nettype) and
1268360efbdSAlfred Perlstein  * returns client handle. Default options are set, which the user can
1278360efbdSAlfred Perlstein  * change using the rpc equivalent of _ioctl()'s.
1288360efbdSAlfred Perlstein  *
1298360efbdSAlfred Perlstein  * It tries for all the netids in that particular class of netid until
1308360efbdSAlfred Perlstein  * it succeeds.
1318360efbdSAlfred Perlstein  * XXX The error message in the case of failure will be the one
1328360efbdSAlfred Perlstein  * pertaining to the last create error.
1338360efbdSAlfred Perlstein  *
1348360efbdSAlfred Perlstein  * It calls clnt_tp_create();
13599064799SGarrett Wollman  */
1368360efbdSAlfred Perlstein CLIENT *
1378360efbdSAlfred Perlstein clnt_create(hostname, prog, vers, nettype)
1388360efbdSAlfred Perlstein 	const char *hostname;				/* server name */
1398360efbdSAlfred Perlstein 	rpcprog_t prog;				/* program number */
1408360efbdSAlfred Perlstein 	rpcvers_t vers;				/* version number */
1418360efbdSAlfred Perlstein 	const char *nettype;				/* net type */
1428360efbdSAlfred Perlstein {
1438360efbdSAlfred Perlstein 	struct netconfig *nconf;
1448360efbdSAlfred Perlstein 	CLIENT *clnt = NULL;
1458360efbdSAlfred Perlstein 	void *handle;
1468360efbdSAlfred Perlstein 	enum clnt_stat	save_cf_stat = RPC_SUCCESS;
1478360efbdSAlfred Perlstein 	struct rpc_err	save_cf_error;
1488360efbdSAlfred Perlstein 
1498360efbdSAlfred Perlstein 
1508360efbdSAlfred Perlstein 	if ((handle = __rpc_setconf(nettype)) == NULL) {
15199064799SGarrett Wollman 		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
15299064799SGarrett Wollman 		return (NULL);
15399064799SGarrett Wollman 	}
1548360efbdSAlfred Perlstein 	rpc_createerr.cf_stat = RPC_SUCCESS;
1558360efbdSAlfred Perlstein 	while (clnt == NULL) {
1568360efbdSAlfred Perlstein 		if ((nconf = __rpc_getconf(handle)) == NULL) {
1578360efbdSAlfred Perlstein 			if (rpc_createerr.cf_stat == RPC_SUCCESS)
1588360efbdSAlfred Perlstein 				rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
15999064799SGarrett Wollman 			break;
1608360efbdSAlfred Perlstein 		}
1618360efbdSAlfred Perlstein #ifdef CLNT_DEBUG
1628360efbdSAlfred Perlstein 		printf("trying netid %s\n", nconf->nc_netid);
1638360efbdSAlfred Perlstein #endif
1648360efbdSAlfred Perlstein 		clnt = clnt_tp_create(hostname, prog, vers, nconf);
1658360efbdSAlfred Perlstein 		if (clnt)
1668360efbdSAlfred Perlstein 			break;
1678360efbdSAlfred Perlstein 		else
1688360efbdSAlfred Perlstein 			/*
1698360efbdSAlfred Perlstein 			 *	Since we didn't get a name-to-address
1708360efbdSAlfred Perlstein 			 *	translation failure here, we remember
1718360efbdSAlfred Perlstein 			 *	this particular error.  The object of
1728360efbdSAlfred Perlstein 			 *	this is to enable us to return to the
1738360efbdSAlfred Perlstein 			 *	caller a more-specific error than the
1748360efbdSAlfred Perlstein 			 *	unhelpful ``Name to address translation
1758360efbdSAlfred Perlstein 			 *	failed'' which might well occur if we
1768360efbdSAlfred Perlstein 			 *	merely returned the last error (because
1778360efbdSAlfred Perlstein 			 *	the local loopbacks are typically the
1788360efbdSAlfred Perlstein 			 *	last ones in /etc/netconfig and the most
1798360efbdSAlfred Perlstein 			 *	likely to be unable to translate a host
1808360efbdSAlfred Perlstein 			 *	name).
1818360efbdSAlfred Perlstein 			 */
1828360efbdSAlfred Perlstein 			if (rpc_createerr.cf_stat != RPC_N2AXLATEFAILURE) {
1838360efbdSAlfred Perlstein 				save_cf_stat = rpc_createerr.cf_stat;
1848360efbdSAlfred Perlstein 				save_cf_error = rpc_createerr.cf_error;
1858360efbdSAlfred Perlstein 			}
1868360efbdSAlfred Perlstein 	}
1878360efbdSAlfred Perlstein 
1888360efbdSAlfred Perlstein 	/*
1898360efbdSAlfred Perlstein 	 *	Attempt to return an error more specific than ``Name to address
1908360efbdSAlfred Perlstein 	 *	translation failed''
1918360efbdSAlfred Perlstein 	 */
1928360efbdSAlfred Perlstein 	if ((rpc_createerr.cf_stat == RPC_N2AXLATEFAILURE) &&
1938360efbdSAlfred Perlstein 		(save_cf_stat != RPC_SUCCESS)) {
1948360efbdSAlfred Perlstein 		rpc_createerr.cf_stat = save_cf_stat;
1958360efbdSAlfred Perlstein 		rpc_createerr.cf_error = save_cf_error;
1968360efbdSAlfred Perlstein 	}
1978360efbdSAlfred Perlstein 	__rpc_endconf(handle);
1988360efbdSAlfred Perlstein 	return (clnt);
1998360efbdSAlfred Perlstein }
2008360efbdSAlfred Perlstein 
2018360efbdSAlfred Perlstein /*
2028360efbdSAlfred Perlstein  * Generic client creation: takes (servers name, program-number, netconf) and
2038360efbdSAlfred Perlstein  * returns client handle. Default options are set, which the user can
2048360efbdSAlfred Perlstein  * change using the rpc equivalent of _ioctl()'s : clnt_control()
2058360efbdSAlfred Perlstein  * It finds out the server address from rpcbind and calls clnt_tli_create()
2068360efbdSAlfred Perlstein  */
2078360efbdSAlfred Perlstein CLIENT *
2088360efbdSAlfred Perlstein clnt_tp_create(hostname, prog, vers, nconf)
2098360efbdSAlfred Perlstein 	const char *hostname;			/* server name */
2108360efbdSAlfred Perlstein 	rpcprog_t prog;				/* program number */
2118360efbdSAlfred Perlstein 	rpcvers_t vers;				/* version number */
2128360efbdSAlfred Perlstein 	const struct netconfig *nconf;		/* net config struct */
2138360efbdSAlfred Perlstein {
2148360efbdSAlfred Perlstein 	struct netbuf *svcaddr;			/* servers address */
2158360efbdSAlfred Perlstein 	CLIENT *cl = NULL;			/* client handle */
2168360efbdSAlfred Perlstein 
2178360efbdSAlfred Perlstein 	if (nconf == NULL) {
2188360efbdSAlfred Perlstein 		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
21999064799SGarrett Wollman 		return (NULL);
22099064799SGarrett Wollman 	}
2218360efbdSAlfred Perlstein 
2228360efbdSAlfred Perlstein 	/*
2238360efbdSAlfred Perlstein 	 * Get the address of the server
2248360efbdSAlfred Perlstein 	 */
2258360efbdSAlfred Perlstein 	if ((svcaddr = __rpcb_findaddr(prog, vers, nconf, hostname,
2268360efbdSAlfred Perlstein 		&cl)) == NULL) {
2278360efbdSAlfred Perlstein 		/* appropriate error number is set by rpcbind libraries */
2288360efbdSAlfred Perlstein 		return (NULL);
2298360efbdSAlfred Perlstein 	}
2308360efbdSAlfred Perlstein 	if (cl == NULL) {
2318360efbdSAlfred Perlstein 		cl = clnt_tli_create(RPC_ANYFD, nconf, svcaddr,
2328360efbdSAlfred Perlstein 					prog, vers, 0, 0);
2338360efbdSAlfred Perlstein 	} else {
2348360efbdSAlfred Perlstein 		/* Reuse the CLIENT handle and change the appropriate fields */
2358360efbdSAlfred Perlstein 		if (CLNT_CONTROL(cl, CLSET_SVC_ADDR, (void *)svcaddr) == TRUE) {
2368360efbdSAlfred Perlstein 			if (cl->cl_netid == NULL)
2378360efbdSAlfred Perlstein 				cl->cl_netid = strdup(nconf->nc_netid);
2388360efbdSAlfred Perlstein 			if (cl->cl_tp == NULL)
2398360efbdSAlfred Perlstein 				cl->cl_tp = strdup(nconf->nc_device);
2408360efbdSAlfred Perlstein 			(void) CLNT_CONTROL(cl, CLSET_PROG, (void *)&prog);
2418360efbdSAlfred Perlstein 			(void) CLNT_CONTROL(cl, CLSET_VERS, (void *)&vers);
2428360efbdSAlfred Perlstein 		} else {
2438360efbdSAlfred Perlstein 			CLNT_DESTROY(cl);
2448360efbdSAlfred Perlstein 			cl = clnt_tli_create(RPC_ANYFD, nconf, svcaddr,
2458360efbdSAlfred Perlstein 					prog, vers, 0, 0);
2468360efbdSAlfred Perlstein 		}
2478360efbdSAlfred Perlstein 	}
2488360efbdSAlfred Perlstein 	free(svcaddr->buf);
2498360efbdSAlfred Perlstein 	free(svcaddr);
2508360efbdSAlfred Perlstein 	return (cl);
2518360efbdSAlfred Perlstein }
2528360efbdSAlfred Perlstein 
2538360efbdSAlfred Perlstein /*
2548360efbdSAlfred Perlstein  * Generic client creation:  returns client handle.
2558360efbdSAlfred Perlstein  * Default options are set, which the user can
2568360efbdSAlfred Perlstein  * change using the rpc equivalent of _ioctl()'s : clnt_control().
2578360efbdSAlfred Perlstein  * If fd is RPC_ANYFD, it will be opened using nconf.
2588360efbdSAlfred Perlstein  * It will be bound if not so.
2598360efbdSAlfred Perlstein  * If sizes are 0; appropriate defaults will be chosen.
2608360efbdSAlfred Perlstein  */
2618360efbdSAlfred Perlstein CLIENT *
2628360efbdSAlfred Perlstein clnt_tli_create(fd, nconf, svcaddr, prog, vers, sendsz, recvsz)
2638360efbdSAlfred Perlstein 	int fd;				/* fd */
2648360efbdSAlfred Perlstein 	const struct netconfig *nconf;	/* netconfig structure */
2658360efbdSAlfred Perlstein 	const struct netbuf *svcaddr;	/* servers address */
2668360efbdSAlfred Perlstein 	rpcprog_t prog;			/* program number */
2678360efbdSAlfred Perlstein 	rpcvers_t vers;			/* version number */
2688360efbdSAlfred Perlstein 	u_int sendsz;			/* send size */
2698360efbdSAlfred Perlstein 	u_int recvsz;			/* recv size */
2708360efbdSAlfred Perlstein {
2718360efbdSAlfred Perlstein 	CLIENT *cl;			/* client handle */
2728360efbdSAlfred Perlstein 	bool_t madefd = FALSE;		/* whether fd opened here */
2738360efbdSAlfred Perlstein 	long servtype;
2748360efbdSAlfred Perlstein 	int one = 1;
2758360efbdSAlfred Perlstein 	struct __rpc_sockinfo si;
2768360efbdSAlfred Perlstein 
2778360efbdSAlfred Perlstein 	if (fd == RPC_ANYFD) {
2788360efbdSAlfred Perlstein 		if (nconf == NULL) {
2798360efbdSAlfred Perlstein 			rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
2808360efbdSAlfred Perlstein 			return (NULL);
2818360efbdSAlfred Perlstein 		}
2828360efbdSAlfred Perlstein 
2838360efbdSAlfred Perlstein 		fd = __rpc_nconf2fd(nconf);
2848360efbdSAlfred Perlstein 
2858360efbdSAlfred Perlstein 		if (fd == -1)
2868360efbdSAlfred Perlstein 			goto err;
2878360efbdSAlfred Perlstein 
2888360efbdSAlfred Perlstein 		madefd = TRUE;
2898360efbdSAlfred Perlstein 		servtype = nconf->nc_semantics;
2908360efbdSAlfred Perlstein 		if (!__rpc_fd2sockinfo(fd, &si))
2918360efbdSAlfred Perlstein 			goto err;
2928360efbdSAlfred Perlstein 
2938360efbdSAlfred Perlstein 		bindresvport(fd, NULL);
2948360efbdSAlfred Perlstein 	} else {
2958360efbdSAlfred Perlstein 		if (!__rpc_fd2sockinfo(fd, &si))
2968360efbdSAlfred Perlstein 			goto err;
2978360efbdSAlfred Perlstein 		servtype = __rpc_socktype2seman(si.si_socktype);
2988360efbdSAlfred Perlstein 		if (servtype == -1) {
2998360efbdSAlfred Perlstein 			rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
3008360efbdSAlfred Perlstein 			return NULL;
3018360efbdSAlfred Perlstein 		}
3028360efbdSAlfred Perlstein 
3038360efbdSAlfred Perlstein 	}
3048360efbdSAlfred Perlstein 
3058360efbdSAlfred Perlstein 	if (si.si_af != ((struct sockaddr *)svcaddr->buf)->sa_family) {
3068360efbdSAlfred Perlstein 		rpc_createerr.cf_stat = RPC_UNKNOWNHOST;	/* XXX */
3078360efbdSAlfred Perlstein 		goto err1;
3088360efbdSAlfred Perlstein 	}
3098360efbdSAlfred Perlstein 
3108360efbdSAlfred Perlstein 	switch (servtype) {
3118360efbdSAlfred Perlstein 	case NC_TPI_COTS_ORD:
3128360efbdSAlfred Perlstein 		cl = clnt_vc_create(fd, svcaddr, prog, vers, sendsz, recvsz);
3138360efbdSAlfred Perlstein 		if (!nconf || !cl)
3148360efbdSAlfred Perlstein 			break;
3158360efbdSAlfred Perlstein 		/* XXX fvdl - is this useful? */
3168360efbdSAlfred Perlstein 		if (strncmp(nconf->nc_protofmly, "inet", 4) == 0)
3178360efbdSAlfred Perlstein 			_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one,
3188360efbdSAlfred Perlstein 			    sizeof (one));
3198360efbdSAlfred Perlstein 		break;
3208360efbdSAlfred Perlstein 	case NC_TPI_CLTS:
3218360efbdSAlfred Perlstein 		cl = clnt_dg_create(fd, svcaddr, prog, vers, sendsz, recvsz);
32299064799SGarrett Wollman 		break;
32399064799SGarrett Wollman 	default:
3248360efbdSAlfred Perlstein 		goto err;
32599064799SGarrett Wollman 	}
3268360efbdSAlfred Perlstein 
3278360efbdSAlfred Perlstein 	if (cl == NULL)
3288360efbdSAlfred Perlstein 		goto err1; /* borrow errors from clnt_dg/vc creates */
3298360efbdSAlfred Perlstein 	if (nconf) {
3308360efbdSAlfred Perlstein 		cl->cl_netid = strdup(nconf->nc_netid);
3318360efbdSAlfred Perlstein 		cl->cl_tp = strdup(nconf->nc_device);
3328360efbdSAlfred Perlstein 	} else {
3338360efbdSAlfred Perlstein 		cl->cl_netid = "";
3348360efbdSAlfred Perlstein 		cl->cl_tp = "";
3358360efbdSAlfred Perlstein 	}
3368360efbdSAlfred Perlstein 	if (madefd) {
3378360efbdSAlfred Perlstein 		(void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL);
3388360efbdSAlfred Perlstein /*		(void) CLNT_CONTROL(cl, CLSET_POP_TIMOD, (char *) NULL);  */
3398360efbdSAlfred Perlstein 	};
3408360efbdSAlfred Perlstein 
3418360efbdSAlfred Perlstein 	return (cl);
3428360efbdSAlfred Perlstein 
3438360efbdSAlfred Perlstein err:
3448360efbdSAlfred Perlstein 	rpc_createerr.cf_stat = RPC_SYSTEMERROR;
3458360efbdSAlfred Perlstein 	rpc_createerr.cf_error.re_errno = errno;
3468360efbdSAlfred Perlstein err1:	if (madefd)
3478360efbdSAlfred Perlstein 		(void)_close(fd);
3488360efbdSAlfred Perlstein 	return (NULL);
34999064799SGarrett Wollman }
350