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 5*3073Sjkennedy * Common Development and Distribution License (the "License"). 6*3073Sjkennedy * 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*3073Sjkennedy * Copyright 2006 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> 380Sstevel@tonic-gate 390Sstevel@tonic-gate #define CC_TTL_MAX 20 400Sstevel@tonic-gate 410Sstevel@tonic-gate typedef struct { 420Sstevel@tonic-gate char *cc_node; 430Sstevel@tonic-gate struct timeval cc_ttl; 440Sstevel@tonic-gate CLIENT *cc_clp; 450Sstevel@tonic-gate } client_cache_t; 460Sstevel@tonic-gate 470Sstevel@tonic-gate typedef struct client_header { 480Sstevel@tonic-gate client_cache_t **ch_cache; /* array of clients. */ 490Sstevel@tonic-gate mutex_t ch_mutex; /* lock access to ch_cache */ 500Sstevel@tonic-gate } client_header_t; 510Sstevel@tonic-gate 520Sstevel@tonic-gate /* 530Sstevel@tonic-gate * This structure is used to pass data from meta_client_create to 540Sstevel@tonic-gate * client_create_helper via meta_client_create_retry. 550Sstevel@tonic-gate */ 560Sstevel@tonic-gate typedef struct clnt_data { 570Sstevel@tonic-gate rpcprog_t cd_prognum; /* RPC program number */ 580Sstevel@tonic-gate rpcvers_t cd_version; /* Desired interface version */ 590Sstevel@tonic-gate char *cd_nettype; /* Type of network to use */ 600Sstevel@tonic-gate } clnt_data_t; 610Sstevel@tonic-gate 620Sstevel@tonic-gate #define MALLOC_BLK_SIZE 10 630Sstevel@tonic-gate static client_header_t client_header = {(client_cache_t **)NULL, DEFAULTMUTEX}; 640Sstevel@tonic-gate 650Sstevel@tonic-gate static void 660Sstevel@tonic-gate cc_add( 670Sstevel@tonic-gate client_header_t *header, 680Sstevel@tonic-gate char *node, 690Sstevel@tonic-gate CLIENT *clntp, 700Sstevel@tonic-gate md_error_t *ep 710Sstevel@tonic-gate ) 720Sstevel@tonic-gate { 730Sstevel@tonic-gate client_cache_t ***cachep = &header->ch_cache; 740Sstevel@tonic-gate struct timeval now; 750Sstevel@tonic-gate int i; 760Sstevel@tonic-gate int j = 0; 770Sstevel@tonic-gate 780Sstevel@tonic-gate if (gettimeofday(&now, NULL) == -1) { 790Sstevel@tonic-gate (void) mdsyserror(ep, errno, "gettimeofday()"); 800Sstevel@tonic-gate return; 810Sstevel@tonic-gate } 820Sstevel@tonic-gate 830Sstevel@tonic-gate (void) mutex_lock(&header->ch_mutex); 840Sstevel@tonic-gate if (*cachep) { 850Sstevel@tonic-gate for (i = 0; (*cachep)[i] != NULL; i++) 860Sstevel@tonic-gate if (strcmp((*cachep)[i]->cc_node, node) == 0 && 870Sstevel@tonic-gate (*cachep)[i]->cc_clp == NULL) { 880Sstevel@tonic-gate (*cachep)[i]->cc_clp = clntp; 890Sstevel@tonic-gate (*cachep)[i]->cc_ttl = now; 900Sstevel@tonic-gate (void) mutex_unlock(&header->ch_mutex); 910Sstevel@tonic-gate return; 920Sstevel@tonic-gate } 930Sstevel@tonic-gate } else { 940Sstevel@tonic-gate *cachep = Calloc(MALLOC_BLK_SIZE, sizeof (**cachep)); 950Sstevel@tonic-gate i = 0; 960Sstevel@tonic-gate } 970Sstevel@tonic-gate 980Sstevel@tonic-gate (*cachep)[i] = Zalloc(sizeof (***cachep)); 990Sstevel@tonic-gate (*cachep)[i]->cc_node = Strdup(node); 1000Sstevel@tonic-gate (*cachep)[i]->cc_clp = clntp; 1010Sstevel@tonic-gate (*cachep)[i]->cc_ttl = now; 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate if ((++i % MALLOC_BLK_SIZE) == 0) { 1040Sstevel@tonic-gate *cachep = Realloc(*cachep, 1050Sstevel@tonic-gate (i + MALLOC_BLK_SIZE) * sizeof (**cachep)); 1060Sstevel@tonic-gate for (j = i; j < (i + MALLOC_BLK_SIZE); j++) 1070Sstevel@tonic-gate (*cachep)[j] = NULL; 1080Sstevel@tonic-gate } 1090Sstevel@tonic-gate (void) mutex_unlock(&header->ch_mutex); 1100Sstevel@tonic-gate } 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate static void 1130Sstevel@tonic-gate rel_clntp(client_cache_t *cachep) 1140Sstevel@tonic-gate { 1150Sstevel@tonic-gate CLIENT *clntp = cachep->cc_clp; 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate if (clntp != NULL) { 1180Sstevel@tonic-gate auth_destroy(clntp->cl_auth); 1190Sstevel@tonic-gate clnt_destroy(clntp); 1200Sstevel@tonic-gate } 1210Sstevel@tonic-gate cachep->cc_clp = NULL; 1220Sstevel@tonic-gate } 1230Sstevel@tonic-gate 1240Sstevel@tonic-gate static void 1250Sstevel@tonic-gate cc_destroy(client_header_t *header) 1260Sstevel@tonic-gate { 1270Sstevel@tonic-gate client_cache_t ***cachep = &header->ch_cache; 1280Sstevel@tonic-gate int i; 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate (void) mutex_lock(&header->ch_mutex); 1310Sstevel@tonic-gate if (*cachep) { 1320Sstevel@tonic-gate for (i = 0; ((*cachep)[i] != NULL); i++) { 1330Sstevel@tonic-gate client_cache_t *p = (*cachep)[i]; 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate Free(p->cc_node); 1360Sstevel@tonic-gate rel_clntp(p); 1370Sstevel@tonic-gate Free(p); 1380Sstevel@tonic-gate } 1390Sstevel@tonic-gate Free(*cachep); 1400Sstevel@tonic-gate *cachep = NULL; 1410Sstevel@tonic-gate } 1420Sstevel@tonic-gate (void) mutex_unlock(&header->ch_mutex); 1430Sstevel@tonic-gate } 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate /* 1460Sstevel@tonic-gate * Set the timeout value for this client handle. 1470Sstevel@tonic-gate */ 148*3073Sjkennedy int 1490Sstevel@tonic-gate cl_sto( 1500Sstevel@tonic-gate CLIENT *clntp, 1510Sstevel@tonic-gate char *hostname, 1520Sstevel@tonic-gate long time_out, 1530Sstevel@tonic-gate md_error_t *ep 1540Sstevel@tonic-gate ) 1550Sstevel@tonic-gate { 1560Sstevel@tonic-gate struct timeval nto; 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate (void) memset(&nto, '\0', sizeof (nto)); 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate nto.tv_sec = time_out; 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate if (clnt_control(clntp, CLSET_TIMEOUT, (char *)&nto) != TRUE) 1630Sstevel@tonic-gate return (mdrpcerror(ep, clntp, hostname, 1640Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "metad client set timeout"))); 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate return (0); 1670Sstevel@tonic-gate } 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate /* 1700Sstevel@tonic-gate * client_create_vers_retry is the helper function to be passed to 1710Sstevel@tonic-gate * meta_client_create_retry to do the actual work of creating the client 1720Sstevel@tonic-gate * when version selection is necessary. 1730Sstevel@tonic-gate */ 1740Sstevel@tonic-gate 1750Sstevel@tonic-gate /* ARGSUSED */ 1760Sstevel@tonic-gate static CLIENT * 1770Sstevel@tonic-gate client_create_vers_retry(char *hostname, 1780Sstevel@tonic-gate void *ignore, 1790Sstevel@tonic-gate struct timeval *tout 1800Sstevel@tonic-gate ) 1810Sstevel@tonic-gate { 1820Sstevel@tonic-gate rpcvers_t vers; /* Version # not needed. */ 1830Sstevel@tonic-gate 1840Sstevel@tonic-gate return (clnt_create_vers_timed(hostname, METAD, &vers, 1850Sstevel@tonic-gate METAD_VERSION, METAD_VERSION_DEVID, "tcp", tout)); 1860Sstevel@tonic-gate } 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate /* 1890Sstevel@tonic-gate * client_create_helper is the helper function to be passed to 1900Sstevel@tonic-gate * meta_client_create_retry when plain vanilla client create is desired. 1910Sstevel@tonic-gate */ 1920Sstevel@tonic-gate static CLIENT * 1930Sstevel@tonic-gate client_create_helper(char *hostname, void *private, struct timeval *time_out) 1940Sstevel@tonic-gate { 1950Sstevel@tonic-gate clnt_data_t *cd = (clnt_data_t *)private; 1960Sstevel@tonic-gate 1970Sstevel@tonic-gate return (clnt_create_timed(hostname, cd->cd_prognum, cd->cd_version, 1980Sstevel@tonic-gate cd->cd_nettype, time_out)); 1990Sstevel@tonic-gate } 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate /* 2020Sstevel@tonic-gate * meta_client_create_retry is a general function to assist in creating RPC 2030Sstevel@tonic-gate * clients. This function handles retrying if the attempt to create a 2040Sstevel@tonic-gate * client fails. meta_client_create_retry itself does not actually create 2050Sstevel@tonic-gate * the client. Instead it calls the helper function, func, to do that job. 2060Sstevel@tonic-gate * 2070Sstevel@tonic-gate * With the help of func, meta_client_create_retry will create an RPC 2080Sstevel@tonic-gate * connection allowing up to tout seconds to complete the task. If the 2090Sstevel@tonic-gate * connection creation fails for RPC_RPCBFAILURE, RPC_CANTRECV or 2100Sstevel@tonic-gate * RPC_PROGNOTREGISTERED and tout seconds have not passed, 2110Sstevel@tonic-gate * meta_client_create_retry will try again. The reason retries are 2120Sstevel@tonic-gate * important is that when the inet daemon is being refreshed, it can take 2130Sstevel@tonic-gate * 15-20 seconds for it to start responding again. 2140Sstevel@tonic-gate * 2150Sstevel@tonic-gate * Arguments: 2160Sstevel@tonic-gate * 2170Sstevel@tonic-gate * hostname - Name of remote host 2180Sstevel@tonic-gate * 2190Sstevel@tonic-gate * func - Pointer to the helper function, that will 2200Sstevel@tonic-gate * actually try to create the client. 2210Sstevel@tonic-gate * 2220Sstevel@tonic-gate * data - Private data to be passed on to func. 2230Sstevel@tonic-gate * meta_client_create_retry treats this as an opaque 2240Sstevel@tonic-gate * pointer. 2250Sstevel@tonic-gate * 2260Sstevel@tonic-gate * tout - Number of seconds to allow for the connection 2270Sstevel@tonic-gate * attempt. 2280Sstevel@tonic-gate * 2290Sstevel@tonic-gate * ep - Standard SVM error pointer. May be NULL. 2300Sstevel@tonic-gate */ 2310Sstevel@tonic-gate CLIENT * 2320Sstevel@tonic-gate meta_client_create_retry( 2330Sstevel@tonic-gate char *hostname, 2340Sstevel@tonic-gate clnt_create_func_t func, 2350Sstevel@tonic-gate void *data, 2360Sstevel@tonic-gate time_t tout, 2370Sstevel@tonic-gate md_error_t *ep 2380Sstevel@tonic-gate ) 2390Sstevel@tonic-gate { 2400Sstevel@tonic-gate static int debug; /* print debugging info */ 2410Sstevel@tonic-gate static int debug_set = 0; 2420Sstevel@tonic-gate 2430Sstevel@tonic-gate CLIENT *clnt = (CLIENT *) NULL; 2440Sstevel@tonic-gate struct timeval curtime; 2450Sstevel@tonic-gate char *d; 2460Sstevel@tonic-gate struct timeval start; 2470Sstevel@tonic-gate struct timeval timeout; 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate if (debug_set == 0) { 2500Sstevel@tonic-gate d = getenv("MD_DEBUG"); 2510Sstevel@tonic-gate if (d == NULL) { 2520Sstevel@tonic-gate debug = 0; 2530Sstevel@tonic-gate } else { 2540Sstevel@tonic-gate debug = (strstr(d, "RPC") == NULL) ? 0 : 1; 2550Sstevel@tonic-gate } 2560Sstevel@tonic-gate debug_set = 1; 2570Sstevel@tonic-gate } 2580Sstevel@tonic-gate timeout.tv_usec = 0; 2590Sstevel@tonic-gate if (gettimeofday(&start, NULL) == -1) { 2600Sstevel@tonic-gate if (ep != (md_error_t *)NULL) { 2610Sstevel@tonic-gate (void) mdsyserror(ep, errno, "gettimeofday()"); 2620Sstevel@tonic-gate } 2630Sstevel@tonic-gate return (clnt); 2640Sstevel@tonic-gate } 2650Sstevel@tonic-gate curtime = start; 2660Sstevel@tonic-gate while ((curtime.tv_sec - start.tv_sec) < tout) { 2670Sstevel@tonic-gate /* Use remaining time as the timeout value. */ 2680Sstevel@tonic-gate timeout.tv_sec = tout - (curtime.tv_sec - start.tv_sec); 2690Sstevel@tonic-gate clnt = (*func)(hostname, data, &timeout); 2700Sstevel@tonic-gate if (clnt != (CLIENT *) NULL) 2710Sstevel@tonic-gate break; 2720Sstevel@tonic-gate if ((rpc_createerr.cf_stat == RPC_RPCBFAILURE) || 2730Sstevel@tonic-gate (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED) || 2740Sstevel@tonic-gate (rpc_createerr.cf_stat == RPC_CANTRECV)) { 2750Sstevel@tonic-gate if (debug) { 2760Sstevel@tonic-gate clnt_pcreateerror("meta_client_create_retry"); 2770Sstevel@tonic-gate } 2780Sstevel@tonic-gate /* If error might be fixed in time, sleep & try again */ 2790Sstevel@tonic-gate (void) sleep(2); 2800Sstevel@tonic-gate if (gettimeofday(&curtime, NULL) == -1) { 2810Sstevel@tonic-gate if (ep != (md_error_t *)NULL) { 2820Sstevel@tonic-gate (void) mdsyserror(ep, errno, 2830Sstevel@tonic-gate "gettimeofday()"); 2840Sstevel@tonic-gate } 2850Sstevel@tonic-gate return (clnt); 2860Sstevel@tonic-gate } 2870Sstevel@tonic-gate } else { 2880Sstevel@tonic-gate /* Not a recoverable error. */ 2890Sstevel@tonic-gate break; 2900Sstevel@tonic-gate } 2910Sstevel@tonic-gate } 2920Sstevel@tonic-gate if ((clnt == (CLIENT *) NULL) && (ep != (md_error_t *)NULL)) { 2930Sstevel@tonic-gate (void) mdrpccreateerror(ep, hostname, 2940Sstevel@tonic-gate "meta_client_create_retry"); 2950Sstevel@tonic-gate } 2960Sstevel@tonic-gate return (clnt); 2970Sstevel@tonic-gate } 2980Sstevel@tonic-gate 2990Sstevel@tonic-gate /* 3000Sstevel@tonic-gate * meta_client_create is intended to be used within SVM as a replacement 3010Sstevel@tonic-gate * for calls to clnt_create. meta_client_create invokes the retry 3020Sstevel@tonic-gate * mechanism of meta_client_create_retry. 3030Sstevel@tonic-gate */ 3040Sstevel@tonic-gate CLIENT * 3050Sstevel@tonic-gate meta_client_create(char *host, rpcprog_t prognum, rpcvers_t version, 3060Sstevel@tonic-gate char *nettype) 3070Sstevel@tonic-gate { 3080Sstevel@tonic-gate clnt_data_t cd; 3090Sstevel@tonic-gate 3100Sstevel@tonic-gate cd.cd_prognum = prognum; 3110Sstevel@tonic-gate cd.cd_version = version; 3120Sstevel@tonic-gate cd.cd_nettype = nettype; 3130Sstevel@tonic-gate return (meta_client_create_retry(host, client_create_helper, 3140Sstevel@tonic-gate (void *)&cd, MD_CLNT_CREATE_TOUT, (md_error_t *)NULL)); 3150Sstevel@tonic-gate } 3160Sstevel@tonic-gate 3170Sstevel@tonic-gate /* 3180Sstevel@tonic-gate * create and return RPC connection 3190Sstevel@tonic-gate */ 3200Sstevel@tonic-gate CLIENT * 3210Sstevel@tonic-gate metarpcopen( 3220Sstevel@tonic-gate char *hostname, 3230Sstevel@tonic-gate long time_out, 3240Sstevel@tonic-gate md_error_t *ep 3250Sstevel@tonic-gate ) 3260Sstevel@tonic-gate { 3270Sstevel@tonic-gate CLIENT *clntp = NULL; 3280Sstevel@tonic-gate client_cache_t ***cachep = &client_header.ch_cache; 3290Sstevel@tonic-gate int i; 3300Sstevel@tonic-gate long delta; 3310Sstevel@tonic-gate struct timeval now; 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate if (gettimeofday(&now, NULL) == -1) { 3340Sstevel@tonic-gate (void) mdsyserror(ep, errno, "gettimeofday()"); 3350Sstevel@tonic-gate return (NULL); 3360Sstevel@tonic-gate } 3370Sstevel@tonic-gate 3380Sstevel@tonic-gate /* 3390Sstevel@tonic-gate * Before trying to create the client, make sure that the core SVM 3400Sstevel@tonic-gate * services are enabled by the Service Management Facility. We 3410Sstevel@tonic-gate * don't want to suffer the 60 second timeout if the services are 3420Sstevel@tonic-gate * not even enabled. This call actually only verifies that they 3430Sstevel@tonic-gate * are enabled on this host no matter which host the caller wants 3440Sstevel@tonic-gate * to connect to. Nonetheless, if the services are not enabled on 3450Sstevel@tonic-gate * the local host, our RPC stuff is not going to work as expected. 3460Sstevel@tonic-gate */ 3470Sstevel@tonic-gate if (meta_smf_isonline(META_SMF_CORE, ep) == 0) { 3480Sstevel@tonic-gate return (NULL); 3490Sstevel@tonic-gate } 3500Sstevel@tonic-gate 3510Sstevel@tonic-gate (void) mutex_lock(&client_header.ch_mutex); 3520Sstevel@tonic-gate if (client_header.ch_cache) { 3530Sstevel@tonic-gate for (i = 0; (*cachep)[i] != NULL; i++) { 3540Sstevel@tonic-gate if (strcmp((*cachep)[i]->cc_node, hostname) == 0) { 3550Sstevel@tonic-gate clntp = (*cachep)[i]->cc_clp; 3560Sstevel@tonic-gate if (clntp == NULL) 3570Sstevel@tonic-gate continue; 3580Sstevel@tonic-gate delta = now.tv_sec - 3590Sstevel@tonic-gate (*cachep)[i]->cc_ttl.tv_sec; 3600Sstevel@tonic-gate if (delta > CC_TTL_MAX) { 3610Sstevel@tonic-gate rel_clntp((*cachep)[i]); 3620Sstevel@tonic-gate continue; 3630Sstevel@tonic-gate } 3640Sstevel@tonic-gate if (cl_sto(clntp, hostname, time_out, 3650Sstevel@tonic-gate ep) != 0) { 3660Sstevel@tonic-gate (void) mutex_unlock( 3670Sstevel@tonic-gate &client_header.ch_mutex); 3680Sstevel@tonic-gate return (NULL); 3690Sstevel@tonic-gate } 3700Sstevel@tonic-gate (void) mutex_unlock(&client_header.ch_mutex); 3710Sstevel@tonic-gate return (clntp); 3720Sstevel@tonic-gate } 3730Sstevel@tonic-gate } 3740Sstevel@tonic-gate } 3750Sstevel@tonic-gate (void) mutex_unlock(&client_header.ch_mutex); 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate /* 3780Sstevel@tonic-gate * Try to create a version 2 client handle by default. 3790Sstevel@tonic-gate * If this fails (i.e. client is version 1), try to 3800Sstevel@tonic-gate * create a version 1 client handle. 3810Sstevel@tonic-gate */ 3820Sstevel@tonic-gate clntp = meta_client_create_retry(hostname, client_create_vers_retry, 3830Sstevel@tonic-gate (void *)NULL, MD_CLNT_CREATE_TOUT, ep); 3840Sstevel@tonic-gate 3850Sstevel@tonic-gate /* open connection */ 3860Sstevel@tonic-gate if (clntp == NULL) { 3870Sstevel@tonic-gate (void) mdrpccreateerror(ep, hostname, 3880Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "metad client create")); 3890Sstevel@tonic-gate cc_add(&client_header, hostname, NULL, ep); 3900Sstevel@tonic-gate return (NULL); 3910Sstevel@tonic-gate } else { 3920Sstevel@tonic-gate auth_destroy(clntp->cl_auth); 3930Sstevel@tonic-gate clntp->cl_auth = authsys_create_default(); 3940Sstevel@tonic-gate assert(clntp->cl_auth != NULL); 3950Sstevel@tonic-gate } 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate cc_add(&client_header, hostname, clntp, ep); 3980Sstevel@tonic-gate 3990Sstevel@tonic-gate if (cl_sto(clntp, hostname, time_out, ep) != 0) 4000Sstevel@tonic-gate return (NULL); 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate return (clntp); 4030Sstevel@tonic-gate } 4040Sstevel@tonic-gate 4050Sstevel@tonic-gate /* 4060Sstevel@tonic-gate * metarpcclose - is a place holder so that when using 4070Sstevel@tonic-gate * metarpcopen, it does not appear that 4080Sstevel@tonic-gate * we have dangling opens. We can at some 4090Sstevel@tonic-gate * later decrement open counts here too, if needed. 4100Sstevel@tonic-gate */ 4110Sstevel@tonic-gate /*ARGSUSED*/ 4120Sstevel@tonic-gate void 4130Sstevel@tonic-gate metarpcclose(CLIENT *clntp) 4140Sstevel@tonic-gate { 4150Sstevel@tonic-gate } 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate void 4180Sstevel@tonic-gate metarpccloseall(void) 4190Sstevel@tonic-gate { 4200Sstevel@tonic-gate cc_destroy(&client_header); 4210Sstevel@tonic-gate } 422