10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
53073Sjkennedy * Common Development and Distribution License (the "License").
63073Sjkennedy * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*5229Svk154806 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
270Sstevel@tonic-gate
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate * Just in case we're not in a build environment, make sure that
300Sstevel@tonic-gate * TEXT_DOMAIN gets set to something.
310Sstevel@tonic-gate */
320Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
330Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
340Sstevel@tonic-gate #endif
350Sstevel@tonic-gate
360Sstevel@tonic-gate #include <meta.h>
370Sstevel@tonic-gate #include <metad.h>
38*5229Svk154806 #include <sdssc.h>
39*5229Svk154806 #include <sys/types.h>
40*5229Svk154806 #include <sys/socket.h>
41*5229Svk154806 #include <netinet/in.h>
42*5229Svk154806 #include <arpa/inet.h>
430Sstevel@tonic-gate
440Sstevel@tonic-gate #define CC_TTL_MAX 20
450Sstevel@tonic-gate
460Sstevel@tonic-gate typedef struct {
470Sstevel@tonic-gate char *cc_node;
480Sstevel@tonic-gate struct timeval cc_ttl;
490Sstevel@tonic-gate CLIENT *cc_clp;
500Sstevel@tonic-gate } client_cache_t;
510Sstevel@tonic-gate
520Sstevel@tonic-gate typedef struct client_header {
530Sstevel@tonic-gate client_cache_t **ch_cache; /* array of clients. */
540Sstevel@tonic-gate mutex_t ch_mutex; /* lock access to ch_cache */
550Sstevel@tonic-gate } client_header_t;
560Sstevel@tonic-gate
570Sstevel@tonic-gate /*
580Sstevel@tonic-gate * This structure is used to pass data from meta_client_create to
590Sstevel@tonic-gate * client_create_helper via meta_client_create_retry.
600Sstevel@tonic-gate */
610Sstevel@tonic-gate typedef struct clnt_data {
620Sstevel@tonic-gate rpcprog_t cd_prognum; /* RPC program number */
630Sstevel@tonic-gate rpcvers_t cd_version; /* Desired interface version */
640Sstevel@tonic-gate char *cd_nettype; /* Type of network to use */
650Sstevel@tonic-gate } clnt_data_t;
660Sstevel@tonic-gate
670Sstevel@tonic-gate #define MALLOC_BLK_SIZE 10
680Sstevel@tonic-gate static client_header_t client_header = {(client_cache_t **)NULL, DEFAULTMUTEX};
690Sstevel@tonic-gate
700Sstevel@tonic-gate static void
cc_add(client_header_t * header,char * node,CLIENT * clntp,md_error_t * ep)710Sstevel@tonic-gate cc_add(
720Sstevel@tonic-gate client_header_t *header,
730Sstevel@tonic-gate char *node,
740Sstevel@tonic-gate CLIENT *clntp,
750Sstevel@tonic-gate md_error_t *ep
760Sstevel@tonic-gate )
770Sstevel@tonic-gate {
780Sstevel@tonic-gate client_cache_t ***cachep = &header->ch_cache;
790Sstevel@tonic-gate struct timeval now;
800Sstevel@tonic-gate int i;
810Sstevel@tonic-gate int j = 0;
820Sstevel@tonic-gate
830Sstevel@tonic-gate if (gettimeofday(&now, NULL) == -1) {
840Sstevel@tonic-gate (void) mdsyserror(ep, errno, "gettimeofday()");
850Sstevel@tonic-gate return;
860Sstevel@tonic-gate }
870Sstevel@tonic-gate
880Sstevel@tonic-gate (void) mutex_lock(&header->ch_mutex);
890Sstevel@tonic-gate if (*cachep) {
900Sstevel@tonic-gate for (i = 0; (*cachep)[i] != NULL; i++)
910Sstevel@tonic-gate if (strcmp((*cachep)[i]->cc_node, node) == 0 &&
920Sstevel@tonic-gate (*cachep)[i]->cc_clp == NULL) {
930Sstevel@tonic-gate (*cachep)[i]->cc_clp = clntp;
940Sstevel@tonic-gate (*cachep)[i]->cc_ttl = now;
950Sstevel@tonic-gate (void) mutex_unlock(&header->ch_mutex);
960Sstevel@tonic-gate return;
970Sstevel@tonic-gate }
980Sstevel@tonic-gate } else {
990Sstevel@tonic-gate *cachep = Calloc(MALLOC_BLK_SIZE, sizeof (**cachep));
1000Sstevel@tonic-gate i = 0;
1010Sstevel@tonic-gate }
1020Sstevel@tonic-gate
1030Sstevel@tonic-gate (*cachep)[i] = Zalloc(sizeof (***cachep));
1040Sstevel@tonic-gate (*cachep)[i]->cc_node = Strdup(node);
1050Sstevel@tonic-gate (*cachep)[i]->cc_clp = clntp;
1060Sstevel@tonic-gate (*cachep)[i]->cc_ttl = now;
1070Sstevel@tonic-gate
1080Sstevel@tonic-gate if ((++i % MALLOC_BLK_SIZE) == 0) {
1090Sstevel@tonic-gate *cachep = Realloc(*cachep,
1100Sstevel@tonic-gate (i + MALLOC_BLK_SIZE) * sizeof (**cachep));
1110Sstevel@tonic-gate for (j = i; j < (i + MALLOC_BLK_SIZE); j++)
1120Sstevel@tonic-gate (*cachep)[j] = NULL;
1130Sstevel@tonic-gate }
1140Sstevel@tonic-gate (void) mutex_unlock(&header->ch_mutex);
1150Sstevel@tonic-gate }
1160Sstevel@tonic-gate
1170Sstevel@tonic-gate static void
rel_clntp(client_cache_t * cachep)1180Sstevel@tonic-gate rel_clntp(client_cache_t *cachep)
1190Sstevel@tonic-gate {
1200Sstevel@tonic-gate CLIENT *clntp = cachep->cc_clp;
1210Sstevel@tonic-gate
1220Sstevel@tonic-gate if (clntp != NULL) {
1230Sstevel@tonic-gate auth_destroy(clntp->cl_auth);
1240Sstevel@tonic-gate clnt_destroy(clntp);
1250Sstevel@tonic-gate }
1260Sstevel@tonic-gate cachep->cc_clp = NULL;
1270Sstevel@tonic-gate }
1280Sstevel@tonic-gate
1290Sstevel@tonic-gate static void
cc_destroy(client_header_t * header)1300Sstevel@tonic-gate cc_destroy(client_header_t *header)
1310Sstevel@tonic-gate {
1320Sstevel@tonic-gate client_cache_t ***cachep = &header->ch_cache;
1330Sstevel@tonic-gate int i;
1340Sstevel@tonic-gate
1350Sstevel@tonic-gate (void) mutex_lock(&header->ch_mutex);
1360Sstevel@tonic-gate if (*cachep) {
1370Sstevel@tonic-gate for (i = 0; ((*cachep)[i] != NULL); i++) {
1380Sstevel@tonic-gate client_cache_t *p = (*cachep)[i];
1390Sstevel@tonic-gate
1400Sstevel@tonic-gate Free(p->cc_node);
1410Sstevel@tonic-gate rel_clntp(p);
1420Sstevel@tonic-gate Free(p);
1430Sstevel@tonic-gate }
1440Sstevel@tonic-gate Free(*cachep);
1450Sstevel@tonic-gate *cachep = NULL;
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate (void) mutex_unlock(&header->ch_mutex);
1480Sstevel@tonic-gate }
1490Sstevel@tonic-gate
1500Sstevel@tonic-gate /*
1510Sstevel@tonic-gate * Set the timeout value for this client handle.
1520Sstevel@tonic-gate */
1533073Sjkennedy int
cl_sto(CLIENT * clntp,char * hostname,long time_out,md_error_t * ep)1540Sstevel@tonic-gate cl_sto(
1550Sstevel@tonic-gate CLIENT *clntp,
1560Sstevel@tonic-gate char *hostname,
1570Sstevel@tonic-gate long time_out,
1580Sstevel@tonic-gate md_error_t *ep
1590Sstevel@tonic-gate )
1600Sstevel@tonic-gate {
1610Sstevel@tonic-gate struct timeval nto;
1620Sstevel@tonic-gate
1630Sstevel@tonic-gate (void) memset(&nto, '\0', sizeof (nto));
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate nto.tv_sec = time_out;
1660Sstevel@tonic-gate
1670Sstevel@tonic-gate if (clnt_control(clntp, CLSET_TIMEOUT, (char *)&nto) != TRUE)
1680Sstevel@tonic-gate return (mdrpcerror(ep, clntp, hostname,
1690Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "metad client set timeout")));
1700Sstevel@tonic-gate
1710Sstevel@tonic-gate return (0);
1720Sstevel@tonic-gate }
1730Sstevel@tonic-gate
1740Sstevel@tonic-gate /*
1750Sstevel@tonic-gate * client_create_vers_retry is the helper function to be passed to
1760Sstevel@tonic-gate * meta_client_create_retry to do the actual work of creating the client
1770Sstevel@tonic-gate * when version selection is necessary.
1780Sstevel@tonic-gate */
1790Sstevel@tonic-gate
1800Sstevel@tonic-gate /* ARGSUSED */
1810Sstevel@tonic-gate static CLIENT *
client_create_vers_retry(char * hostname,void * ignore,struct timeval * tout)1820Sstevel@tonic-gate client_create_vers_retry(char *hostname,
1830Sstevel@tonic-gate void *ignore,
1840Sstevel@tonic-gate struct timeval *tout
1850Sstevel@tonic-gate )
1860Sstevel@tonic-gate {
1870Sstevel@tonic-gate rpcvers_t vers; /* Version # not needed. */
1880Sstevel@tonic-gate
1890Sstevel@tonic-gate return (clnt_create_vers_timed(hostname, METAD, &vers,
190*5229Svk154806 METAD_VERSION, METAD_VERSION_DEVID, "tcp", tout));
1910Sstevel@tonic-gate }
1920Sstevel@tonic-gate
1930Sstevel@tonic-gate /*
1940Sstevel@tonic-gate * client_create_helper is the helper function to be passed to
1950Sstevel@tonic-gate * meta_client_create_retry when plain vanilla client create is desired.
1960Sstevel@tonic-gate */
1970Sstevel@tonic-gate static CLIENT *
client_create_helper(char * hostname,void * private,struct timeval * time_out)1980Sstevel@tonic-gate client_create_helper(char *hostname, void *private, struct timeval *time_out)
1990Sstevel@tonic-gate {
2000Sstevel@tonic-gate clnt_data_t *cd = (clnt_data_t *)private;
2010Sstevel@tonic-gate
2020Sstevel@tonic-gate return (clnt_create_timed(hostname, cd->cd_prognum, cd->cd_version,
203*5229Svk154806 cd->cd_nettype, time_out));
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate /*
2070Sstevel@tonic-gate * meta_client_create_retry is a general function to assist in creating RPC
2080Sstevel@tonic-gate * clients. This function handles retrying if the attempt to create a
2090Sstevel@tonic-gate * client fails. meta_client_create_retry itself does not actually create
2100Sstevel@tonic-gate * the client. Instead it calls the helper function, func, to do that job.
2110Sstevel@tonic-gate *
2120Sstevel@tonic-gate * With the help of func, meta_client_create_retry will create an RPC
2130Sstevel@tonic-gate * connection allowing up to tout seconds to complete the task. If the
2140Sstevel@tonic-gate * connection creation fails for RPC_RPCBFAILURE, RPC_CANTRECV or
2150Sstevel@tonic-gate * RPC_PROGNOTREGISTERED and tout seconds have not passed,
2160Sstevel@tonic-gate * meta_client_create_retry will try again. The reason retries are
2170Sstevel@tonic-gate * important is that when the inet daemon is being refreshed, it can take
2180Sstevel@tonic-gate * 15-20 seconds for it to start responding again.
2190Sstevel@tonic-gate *
2200Sstevel@tonic-gate * Arguments:
2210Sstevel@tonic-gate *
2220Sstevel@tonic-gate * hostname - Name of remote host
2230Sstevel@tonic-gate *
2240Sstevel@tonic-gate * func - Pointer to the helper function, that will
2250Sstevel@tonic-gate * actually try to create the client.
2260Sstevel@tonic-gate *
2270Sstevel@tonic-gate * data - Private data to be passed on to func.
2280Sstevel@tonic-gate * meta_client_create_retry treats this as an opaque
2290Sstevel@tonic-gate * pointer.
2300Sstevel@tonic-gate *
2310Sstevel@tonic-gate * tout - Number of seconds to allow for the connection
2320Sstevel@tonic-gate * attempt.
2330Sstevel@tonic-gate *
2340Sstevel@tonic-gate * ep - Standard SVM error pointer. May be NULL.
2350Sstevel@tonic-gate */
2360Sstevel@tonic-gate CLIENT *
meta_client_create_retry(char * hostname,clnt_create_func_t func,void * data,time_t tout,md_error_t * ep)2370Sstevel@tonic-gate meta_client_create_retry(
2380Sstevel@tonic-gate char *hostname,
2390Sstevel@tonic-gate clnt_create_func_t func,
2400Sstevel@tonic-gate void *data,
2410Sstevel@tonic-gate time_t tout,
2420Sstevel@tonic-gate md_error_t *ep
2430Sstevel@tonic-gate )
2440Sstevel@tonic-gate {
2450Sstevel@tonic-gate static int debug; /* print debugging info */
2460Sstevel@tonic-gate static int debug_set = 0;
2470Sstevel@tonic-gate
2480Sstevel@tonic-gate CLIENT *clnt = (CLIENT *) NULL;
2490Sstevel@tonic-gate struct timeval curtime;
2500Sstevel@tonic-gate char *d;
2510Sstevel@tonic-gate struct timeval start;
2520Sstevel@tonic-gate struct timeval timeout;
2530Sstevel@tonic-gate
2540Sstevel@tonic-gate if (debug_set == 0) {
2550Sstevel@tonic-gate d = getenv("MD_DEBUG");
2560Sstevel@tonic-gate if (d == NULL) {
2570Sstevel@tonic-gate debug = 0;
2580Sstevel@tonic-gate } else {
2590Sstevel@tonic-gate debug = (strstr(d, "RPC") == NULL) ? 0 : 1;
2600Sstevel@tonic-gate }
2610Sstevel@tonic-gate debug_set = 1;
2620Sstevel@tonic-gate }
2630Sstevel@tonic-gate timeout.tv_usec = 0;
2640Sstevel@tonic-gate if (gettimeofday(&start, NULL) == -1) {
2650Sstevel@tonic-gate if (ep != (md_error_t *)NULL) {
2660Sstevel@tonic-gate (void) mdsyserror(ep, errno, "gettimeofday()");
2670Sstevel@tonic-gate }
2680Sstevel@tonic-gate return (clnt);
2690Sstevel@tonic-gate }
2700Sstevel@tonic-gate curtime = start;
2710Sstevel@tonic-gate while ((curtime.tv_sec - start.tv_sec) < tout) {
2720Sstevel@tonic-gate /* Use remaining time as the timeout value. */
2730Sstevel@tonic-gate timeout.tv_sec = tout - (curtime.tv_sec - start.tv_sec);
2740Sstevel@tonic-gate clnt = (*func)(hostname, data, &timeout);
2750Sstevel@tonic-gate if (clnt != (CLIENT *) NULL)
2760Sstevel@tonic-gate break;
2770Sstevel@tonic-gate if ((rpc_createerr.cf_stat == RPC_RPCBFAILURE) ||
278*5229Svk154806 (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED) ||
279*5229Svk154806 (rpc_createerr.cf_stat == RPC_CANTRECV)) {
2800Sstevel@tonic-gate if (debug) {
2810Sstevel@tonic-gate clnt_pcreateerror("meta_client_create_retry");
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate /* If error might be fixed in time, sleep & try again */
2840Sstevel@tonic-gate (void) sleep(2);
2850Sstevel@tonic-gate if (gettimeofday(&curtime, NULL) == -1) {
2860Sstevel@tonic-gate if (ep != (md_error_t *)NULL) {
2870Sstevel@tonic-gate (void) mdsyserror(ep, errno,
288*5229Svk154806 "gettimeofday()");
2890Sstevel@tonic-gate }
2900Sstevel@tonic-gate return (clnt);
2910Sstevel@tonic-gate }
2920Sstevel@tonic-gate } else {
2930Sstevel@tonic-gate /* Not a recoverable error. */
2940Sstevel@tonic-gate break;
2950Sstevel@tonic-gate }
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate if ((clnt == (CLIENT *) NULL) && (ep != (md_error_t *)NULL)) {
2980Sstevel@tonic-gate (void) mdrpccreateerror(ep, hostname,
299*5229Svk154806 "meta_client_create_retry");
3000Sstevel@tonic-gate }
3010Sstevel@tonic-gate return (clnt);
3020Sstevel@tonic-gate }
3030Sstevel@tonic-gate
3040Sstevel@tonic-gate /*
3050Sstevel@tonic-gate * meta_client_create is intended to be used within SVM as a replacement
3060Sstevel@tonic-gate * for calls to clnt_create. meta_client_create invokes the retry
3070Sstevel@tonic-gate * mechanism of meta_client_create_retry.
3080Sstevel@tonic-gate */
3090Sstevel@tonic-gate CLIENT *
meta_client_create(char * host,rpcprog_t prognum,rpcvers_t version,char * nettype)3100Sstevel@tonic-gate meta_client_create(char *host, rpcprog_t prognum, rpcvers_t version,
3110Sstevel@tonic-gate char *nettype)
3120Sstevel@tonic-gate {
3130Sstevel@tonic-gate clnt_data_t cd;
3140Sstevel@tonic-gate
3150Sstevel@tonic-gate cd.cd_prognum = prognum;
3160Sstevel@tonic-gate cd.cd_version = version;
3170Sstevel@tonic-gate cd.cd_nettype = nettype;
3180Sstevel@tonic-gate return (meta_client_create_retry(host, client_create_helper,
319*5229Svk154806 (void *)&cd, MD_CLNT_CREATE_TOUT, (md_error_t *)NULL));
3200Sstevel@tonic-gate }
3210Sstevel@tonic-gate
3220Sstevel@tonic-gate /*
3230Sstevel@tonic-gate * create and return RPC connection
3240Sstevel@tonic-gate */
3250Sstevel@tonic-gate CLIENT *
metarpcopen(char * hostname,long time_out,md_error_t * ep)3260Sstevel@tonic-gate metarpcopen(
3270Sstevel@tonic-gate char *hostname,
3280Sstevel@tonic-gate long time_out,
3290Sstevel@tonic-gate md_error_t *ep
3300Sstevel@tonic-gate )
3310Sstevel@tonic-gate {
3320Sstevel@tonic-gate CLIENT *clntp = NULL;
3330Sstevel@tonic-gate client_cache_t ***cachep = &client_header.ch_cache;
3340Sstevel@tonic-gate int i;
3350Sstevel@tonic-gate long delta;
3360Sstevel@tonic-gate struct timeval now;
337*5229Svk154806 struct in_addr p_ip;
338*5229Svk154806 char *host_sc = NULL;
339*5229Svk154806 char host_priv[18];
340*5229Svk154806
341*5229Svk154806 /*
342*5229Svk154806 * If we are in cluster mode, lets use the private interconnect
343*5229Svk154806 * hostnames to establish the rpc connections.
344*5229Svk154806 */
345*5229Svk154806 if (sdssc_bind_library() != SDSSC_NOT_BOUND)
346*5229Svk154806 if (sdssc_get_priv_ipaddr(hostname, &p_ip) == SDSSC_OKAY) {
347*5229Svk154806 /*
348*5229Svk154806 * inet_ntoa() returns pointer to a string in the
349*5229Svk154806 * base 256 notation d.d.d.d (IPv4) and so
350*5229Svk154806 * host_priv[18] should be sufficient enough to
351*5229Svk154806 * hold it.
352*5229Svk154806 */
353*5229Svk154806 host_sc = inet_ntoa(p_ip);
354*5229Svk154806 if (host_sc != NULL) {
355*5229Svk154806 int size = sizeof (host_priv);
356*5229Svk154806 if (strlcpy(host_priv, host_sc, size) < size)
357*5229Svk154806 hostname = host_priv;
358*5229Svk154806 }
359*5229Svk154806 }
3600Sstevel@tonic-gate
3610Sstevel@tonic-gate if (gettimeofday(&now, NULL) == -1) {
3620Sstevel@tonic-gate (void) mdsyserror(ep, errno, "gettimeofday()");
3630Sstevel@tonic-gate return (NULL);
3640Sstevel@tonic-gate }
3650Sstevel@tonic-gate
3660Sstevel@tonic-gate /*
3670Sstevel@tonic-gate * Before trying to create the client, make sure that the core SVM
3680Sstevel@tonic-gate * services are enabled by the Service Management Facility. We
3690Sstevel@tonic-gate * don't want to suffer the 60 second timeout if the services are
3700Sstevel@tonic-gate * not even enabled. This call actually only verifies that they
3710Sstevel@tonic-gate * are enabled on this host no matter which host the caller wants
3720Sstevel@tonic-gate * to connect to. Nonetheless, if the services are not enabled on
3730Sstevel@tonic-gate * the local host, our RPC stuff is not going to work as expected.
3740Sstevel@tonic-gate */
3750Sstevel@tonic-gate if (meta_smf_isonline(META_SMF_CORE, ep) == 0) {
3760Sstevel@tonic-gate return (NULL);
3770Sstevel@tonic-gate }
3780Sstevel@tonic-gate
3790Sstevel@tonic-gate (void) mutex_lock(&client_header.ch_mutex);
3800Sstevel@tonic-gate if (client_header.ch_cache) {
3810Sstevel@tonic-gate for (i = 0; (*cachep)[i] != NULL; i++) {
3820Sstevel@tonic-gate if (strcmp((*cachep)[i]->cc_node, hostname) == 0) {
3830Sstevel@tonic-gate clntp = (*cachep)[i]->cc_clp;
3840Sstevel@tonic-gate if (clntp == NULL)
3850Sstevel@tonic-gate continue;
3860Sstevel@tonic-gate delta = now.tv_sec -
3870Sstevel@tonic-gate (*cachep)[i]->cc_ttl.tv_sec;
3880Sstevel@tonic-gate if (delta > CC_TTL_MAX) {
3890Sstevel@tonic-gate rel_clntp((*cachep)[i]);
3900Sstevel@tonic-gate continue;
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate if (cl_sto(clntp, hostname, time_out,
393*5229Svk154806 ep) != 0) {
3940Sstevel@tonic-gate (void) mutex_unlock(
395*5229Svk154806 &client_header.ch_mutex);
3960Sstevel@tonic-gate return (NULL);
3970Sstevel@tonic-gate }
3980Sstevel@tonic-gate (void) mutex_unlock(&client_header.ch_mutex);
3990Sstevel@tonic-gate return (clntp);
4000Sstevel@tonic-gate }
4010Sstevel@tonic-gate }
4020Sstevel@tonic-gate }
4030Sstevel@tonic-gate (void) mutex_unlock(&client_header.ch_mutex);
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate /*
4060Sstevel@tonic-gate * Try to create a version 2 client handle by default.
4070Sstevel@tonic-gate * If this fails (i.e. client is version 1), try to
4080Sstevel@tonic-gate * create a version 1 client handle.
4090Sstevel@tonic-gate */
4100Sstevel@tonic-gate clntp = meta_client_create_retry(hostname, client_create_vers_retry,
411*5229Svk154806 (void *)NULL, MD_CLNT_CREATE_TOUT, ep);
4120Sstevel@tonic-gate
4130Sstevel@tonic-gate /* open connection */
4140Sstevel@tonic-gate if (clntp == NULL) {
4150Sstevel@tonic-gate (void) mdrpccreateerror(ep, hostname,
4160Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "metad client create"));
4170Sstevel@tonic-gate cc_add(&client_header, hostname, NULL, ep);
4180Sstevel@tonic-gate return (NULL);
4190Sstevel@tonic-gate } else {
4200Sstevel@tonic-gate auth_destroy(clntp->cl_auth);
4210Sstevel@tonic-gate clntp->cl_auth = authsys_create_default();
4220Sstevel@tonic-gate assert(clntp->cl_auth != NULL);
4230Sstevel@tonic-gate }
4240Sstevel@tonic-gate
4250Sstevel@tonic-gate cc_add(&client_header, hostname, clntp, ep);
4260Sstevel@tonic-gate
4270Sstevel@tonic-gate if (cl_sto(clntp, hostname, time_out, ep) != 0)
4280Sstevel@tonic-gate return (NULL);
4290Sstevel@tonic-gate
4300Sstevel@tonic-gate return (clntp);
4310Sstevel@tonic-gate }
4320Sstevel@tonic-gate
4330Sstevel@tonic-gate /*
4340Sstevel@tonic-gate * metarpcclose - is a place holder so that when using
4350Sstevel@tonic-gate * metarpcopen, it does not appear that
4360Sstevel@tonic-gate * we have dangling opens. We can at some
4370Sstevel@tonic-gate * later decrement open counts here too, if needed.
4380Sstevel@tonic-gate */
4390Sstevel@tonic-gate /*ARGSUSED*/
4400Sstevel@tonic-gate void
metarpcclose(CLIENT * clntp)4410Sstevel@tonic-gate metarpcclose(CLIENT *clntp)
4420Sstevel@tonic-gate {
4430Sstevel@tonic-gate }
4440Sstevel@tonic-gate
4450Sstevel@tonic-gate void
metarpccloseall(void)4460Sstevel@tonic-gate metarpccloseall(void)
4470Sstevel@tonic-gate {
4480Sstevel@tonic-gate cc_destroy(&client_header);
4490Sstevel@tonic-gate }
450