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 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 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 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 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 * 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 * 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 * 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 * 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 * 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 4410Sstevel@tonic-gate metarpcclose(CLIENT *clntp) 4420Sstevel@tonic-gate { 4430Sstevel@tonic-gate } 4440Sstevel@tonic-gate 4450Sstevel@tonic-gate void 4460Sstevel@tonic-gate metarpccloseall(void) 4470Sstevel@tonic-gate { 4480Sstevel@tonic-gate cc_destroy(&client_header); 4490Sstevel@tonic-gate } 450