Exemplo n.º 1
0
static int lpm_clnt_create (void)
{
	struct sockaddr_in saddr;
#if 0
	struct timeval tv;
#endif

	if (!*MyHname)
		gethostname (MyHname, sizeof MyHname - 1);

	if (lpm_cl)
		clnt_destroy (lpm_cl);

	lpm_cl = clnt_create (MyHname, LPMPROG, LPMVERS, "udp");
	if (!lpm_cl)
	{
		strcpy (lpm_errmsg, clnt_spcreateerror (MyHname));
		return 0;
	}

#if 0
	tv.tv_sec = 5;
	tv.tv_usec = 0;

	clnt_control (lpm_cl, CLSET_TIMEOUT, (char *)&tv);
	clnt_control (lpm_cl, CLSET_RETRY_TIMEOUT, (char *)&tv);
#endif
	clnt_control (lpm_cl, CLGET_SERVER_ADDR, (char *)&saddr);
	MyHaddr = ntohl (saddr.sin_addr.s_addr);

	errno = 0;
	return 1;
}
Exemplo n.º 2
0
static int
check_rdev(struct key_call_private *kcp)
{
	struct stat stbuf;

	if (kcp->fd == -1)
		return (1);    /* can't check it, assume it is okay */

	if (fstat(kcp->fd, &stbuf) == -1) {
		syslog(LOG_DEBUG, "keyserv_client:  can't stat %d", kcp->fd);
		/* could be because file descriptor was closed */
		/* it's not our file descriptor, so don't try to close it */
		clnt_control(kcp->client, CLSET_FD_NCLOSE, NULL);

		return (0);
	}
	if (kcp->rdev != stbuf.st_rdev) {
		syslog(LOG_DEBUG,
		    "keyserv_client:  fd %d changed, old=0x%x, new=0x%x",
		    kcp->fd, kcp->rdev, stbuf.st_rdev);
		/* it's not our file descriptor, so don't try to close it */
		clnt_control(kcp->client, CLSET_FD_NCLOSE, NULL);
		return (0);
	}
	return (1);    /* fd is okay */
}
Exemplo n.º 3
0
static int rpc_ping_proto(const char *host,
			  unsigned long nfs_version,
			  const char *proto,
			  long seconds, long micros)
{
	struct conn_info info;
	CLIENT *client;
	enum clnt_stat stat;
	struct protoent *prot;

	prot = getprotobyname(proto);
	if (!prot)
		return 1;

	info.host = host;
	info.program = NFS_PROGRAM;
	info.version = nfs_version;
	info.proto = prot;
	info.send_sz = 0;
	info.recv_sz = 0;
	info.timeout.tv_sec = seconds;
	info.timeout.tv_usec = micros;

	info.port = portmap_getport(&info);
	if (!info.port)
		return 0;

	if (prot->p_proto == IPPROTO_UDP) {
		info.send_sz = UDPMSGSIZE;
		info.recv_sz = UDPMSGSIZE;
		client = create_udp_client(&info);
	} else
		client = create_tcp_client(&info);

	if (!client)
		return 0;

	clnt_control(client, CLSET_TIMEOUT, (char *) &info.timeout);
	clnt_control(client, CLSET_RETRY_TIMEOUT, (char *) &info.timeout);

	stat = clnt_call(client, NFSPROC_NULL,
			 (xdrproc_t) xdr_void, 0, (xdrproc_t) xdr_void, 0,
			 info.timeout);

	clnt_destroy(client);

	if (stat != RPC_SUCCESS)
		return 0;

	return 1;
}
Exemplo n.º 4
0
/*
 * Keep the handle cached.  This call may be made quite often.
 */
static CLIENT *
getkeyserv_handle(int vers, int stale)
{
	struct key_call_private	*kcp = NULL;
	int _update_did();

	kcp = thr_get_storage(&key_call_key, sizeof (*kcp), key_call_destroy);
	if (kcp == NULL) {
		syslog(LOG_CRIT, "getkeyserv_handle: out of memory");
		return (NULL);
	}

	/*
	 * if pid has changed, destroy client and rebuild
	 * or if stale is '1' then destroy client and rebuild
	 */
	if (kcp->client &&
	    (!check_rdev(kcp) || kcp->pid != getpid() || stale)) {
		clnt_destroy(kcp->client);
		kcp->client = NULL;
	}
	if (kcp->client) {
		int	fd;
		/*
		 * Change the version number to the new one.
		 */
		clnt_control(kcp->client, CLSET_VERS, (void *)&vers);
		if (!_update_did(kcp->client, vers)) {
			if (rpc_createerr.cf_stat == RPC_SYSTEMERROR)
				syslog(LOG_DEBUG, "getkeyserv_handle: "
						"out of memory!");
			return (NULL);
		}
		/* Update fd in kcp because it was reopened in _update_did */
		if (clnt_control(kcp->client, CLGET_FD, (void *)&fd) &&
		    (fd >= 0))
			(void) fcntl(fd, F_SETFD, FD_CLOEXEC); /* close exec */
		kcp->fd = fd;
		return (kcp->client);
	}

	if ((kcp->client = clnt_door_create(KEY_PROG, vers, 0)) == NULL)
		return (NULL);

	kcp->pid = getpid();
	set_rdev(kcp);
	(void) fcntl(kcp->fd, F_SETFD, FD_CLOEXEC);	/* close on exec */

	return (kcp->client);
}
Exemplo n.º 5
0
/*
 * Generic client creation: takes (hostname, program-number, protocol) and
 * returns client handle. Default options are set, which the user can
 * change using the rpc equivalent of ioctl()'s.
 */
CLIENT *clnt_create (const char *hostname, const unsigned long prog,
				 const unsigned long vers, const char *proto)
{
	int sock;
	struct hostent *h;
	struct sockaddr_in sin;
	struct timeval tv;
	CLIENT *client;

	h = gethostbyname(hostname);
	if (h == NULL) {
	    fprintf(stderr, "rpc : unknown host\n");
		return (NULL);
	}
	if (h->h_addrtype != AF_INET) {
	    fprintf(stderr, "rpc : unknow inet\n");
		return (NULL);
	}
	memset((char*)&sin,0,sizeof(sin));
	sin.sin_family = h->h_addrtype;
	sin.sin_port = 0;
	memmove((char *) &sin.sin_addr, h->h_addr, h->h_length);

	sock = -1;
	if (strcmp(proto, "udp") == 0)
	{
		tv.tv_sec = 5;
		tv.tv_usec = 0;
		client = clntudp_create(&sin, prog, vers, tv, &sock);
		if (client == NULL) return NULL;
		clnt_control(client, CLSET_TIMEOUT, (char*)&tv);
	} 
	else if (strcmp(proto, "tcp") == 0) 
	{
	    client = clnttcp_create(&sin, prog, vers, &sock, TCPMSGSIZE, TCPMSGSIZE); /* sylixos and TCPMSGSIZE */
		if (client == NULL) {
			return (NULL);
		}
		tv.tv_sec = 25;
		tv.tv_usec = 0;
		clnt_control(client, CLSET_TIMEOUT, &tv);
	}
	else
	{
	    fprintf(stderr, "rpc : unknow protocol\n");
		return NULL;
	}

	return (client);
}
Exemplo n.º 6
0
int main(int argn, char *argc[])
{
	//Program parameters : argc[1] : HostName or Host IP
	//					   argc[2] : Server Program Number
	//					   other arguments depend on test case

	//run_mode can switch into stand alone program or program launch by shell script
	//1 : stand alone, debug mode, more screen information
	//0 : launch by shell script as test case, only one printf -> result status
	int run_mode = 0;
	int test_status = 1; //Default test result set to FAILED
	int progNum = atoi(argc[2]);
	char proto[8] = "udp";
	CLIENT *clnt = NULL;
	int fd;

	//First of all, create a client
	clnt = clnt_create(argc[1], progNum, VERSNUM, proto);

	if (run_mode == 1)
	{
		printf("CLIENT : %d\n", clnt);
	}

	//If we are here, macro call was successful
	test_status = !clnt_control(clnt, CLGET_FD, (char *)&fd);

	//This last printf gives the result status to the tests suite
	//normally should be 0: test has passed or 1: test has failed
	printf("%d\n", test_status);

	return test_status;
}
Exemplo n.º 7
0
int
_update_did(CLIENT *cl, int vers)
{
/* LINTED pointer alignment */
	struct cu_data	*cu = (struct cu_data *)cl->cl_private;
	rpcprog_t prog;
	char rendezvous[64];

	if (cu->cu_fd >= 0)
		(void) close(cu->cu_fd);
/* Make sure that the right door id is used in door_call. */
	clnt_control(cl, CLGET_PROG, (void *)&prog);
	(void) sprintf(rendezvous, RPC_DOOR_RENDEZVOUS, (int)prog, vers);
	if ((cu->cu_fd = open(rendezvous, O_RDONLY, 0)) < 0) {
		rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
		rpc_createerr.cf_error.re_errno = errno;
		rpc_createerr.cf_error.re_terrno = 0;
		return (0);
	}
	free(cl->cl_tp);
	cl->cl_tp = strdup(rendezvous);
	if (cl->cl_tp == NULL) {
		syslog(LOG_ERR, "_update_did: strdup failed");
		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
		rpc_createerr.cf_error.re_errno = errno;
		rpc_createerr.cf_error.re_terrno = 0;
		return (0);
	}
	return (1);
}
Exemplo n.º 8
0
int
main(int argc, char **argv)
{
	CLIENT		*cl;
	square_in	in;
	square_out	*outp;
	struct timeval	tv;

	if (argc != 4)
		err_quit("usage: client <hostname> <integer-value> <protocol>");

	cl = Clnt_create(argv[1], SQUARE_PROG, SQUARE_VERS, argv[3]);

	Clnt_control(cl, CLGET_TIMEOUT, (char *) &tv);
	printf("timeout = %ld sec, %ld usec\n", tv.tv_sec, tv.tv_usec);
	if (clnt_control(cl, CLGET_RETRY_TIMEOUT, (char *) &tv) == TRUE)
		printf("retry timeout = %ld sec, %ld usec\n", tv.tv_sec, tv.tv_usec);

	in.arg1 = atol(argv[2]);
	if ( (outp = squareproc_1(&in, cl)) == NULL)
		err_quit("%s", clnt_sperror(cl, argv[1]));

	printf("result: %ld\n", outp->res1);
	exit(0);
}
Exemplo n.º 9
0
/* protocol can be PMAP_IPPROTO_TCP or PMAP_IPPROTO_UDP */
uint16_t get_rpc_port(CLIENT *client, long unsigned prognum, long unsigned version, long unsigned protocol) {
    u_long *res = NULL;
    uint16_t port = 0;
    pmap pmap_args = {
        .pm_prog = prognum,
        .pm_vers = version,
        .pm_prot = protocol,
    };
    /* for printing error messages */
    struct sockaddr_in clnt_info;
    char ip_address[INET_ADDRSTRLEN];

    if (client) {
        res = pmapproc_getport_2(&pmap_args, client);

        if (res) {
            /* convert to network byte order */
            port = htons(*res);
            /* RPC succeeded, but program isn't registered */
            if (port == 0) {
                /* get the server address out of the client */
                clnt_control(client, CLGET_SERVER_ADDR, (char *)&clnt_info);
                inet_ntop(AF_INET, &(((struct sockaddr_in *)&clnt_info)->sin_addr), ip_address, INET_ADDRSTRLEN);
                fprintf(stderr, "get_rpc_port(%s:%lu): program not registered!\n", ip_address, prognum);
            }
        /* Portmapper RPC failure */
        } else {
            clnt_perror(client, "pmapproc_getport_2");
        }
    }

    return port;
}
Exemplo n.º 10
0
int main(int argc, char **argv)
{
        struct timeval          stvTimeout;
	char *tp = "udp";
	char *host;
	char opt;
	
	host = getenv("BAYONNE_HOST");
	if(!host)
		host = "localhost";

        stvTimeout.tv_sec =  23;
        stvTimeout.tv_usec = 0;

	while((opt = getopt(argc, argv, "t:h:p:")) != -1)
		switch(opt)
		{
		case 't':
			stvTimeout.tv_sec = atoi(optarg);
			break;
		case 'h':
			host = optarg;
			break;
		case 'p':
			tp = optarg;
			break;
		default:
			goto use;
		}

	rpc = clnt_create(host, BAYONNE_PROGRAM, BAYONNE_VERSION, tp);

        if (!rpc)
        {
                printf( "CLNT_CREATE %s\n", clnt_spcreateerror( "" ) );
                exit( 1 );
        }

        if(!clnt_control(rpc, CLSET_TIMEOUT,( char *) &stvTimeout ) )
        {
                printf( "CLNT_CONTROL: %s\n",clnt_sperror(rpc, "" ) );
                clnt_destroy(rpc);
                exit( 1 );
        }

	if(optind >= argc)
		uptime();

use:
	fprintf(stderr, "use: bts_uptime [-h host] [-p proto] [-t timeout]\n");

	exit(-1);

}
Exemplo n.º 11
0
EXTERNAL void
icbinn_clnt_destroy (ICBINN * icb)
{
  if (!icb)
    return;
  if (icb->c)
    {
      clnt_control (icb->c, CLSET_FD_CLOSE, NULL);
      clnt_destroy (icb->c);
    }
  free (icb);
}
Exemplo n.º 12
0
int main(int argn, char *argc[])
{
	//Program parameters : argc[1] : HostName or Host IP
	//                                         argc[2] : Server Program Number
	//                                         other arguments depend on test case

	//run_mode can switch into stand alone program or program launch by shell script
	//1 : stand alone, debug mode, more screen information
	//0 : launch by shell script as test case, only one printf -> result status
	int run_mode = 0;
	int test_status = 1;	//Default test result set to FAILED
	int progNum = atoi(argc[2]);
	CLIENT *client = NULL;
	struct netconfig *nconf = NULL;
	struct timeval tv;
	bool_t rslt = 0;
	int fd = 0;

	//First, test initialization
	nconf = getnetconfigent("udp");

	if ((struct netconfig *)nconf == NULL) {
		//Test failed
		printf("1\n");
		return 1;
	}

	tv.tv_sec = 1;
	tv.tv_usec = 1;

	client = clnt_tp_create_timed(argc[1], progNum,
				      VERSNUM, (struct netconfig *)nconf, &tv);

	//Call routine
	rslt = clnt_control(client, CLGET_FD, (int *)&fd);
	if (run_mode) {
		printf("client : %p\n", client);
		printf("nconf : %p\n", nconf);
		printf("F. Desc. : %d\n", fd);
	}

	test_status = (rslt == 1) ? 0 : 1;

	//This last printf gives the result status to the tests suite
	//normally should be 0: test has passed or 1: test has failed
	printf("%d\n", test_status);

	//clnt_destroy(client);

	return test_status;
}
Exemplo n.º 13
0
/*
 * Create a UDP RPC client
 */
static CLIENT* create_udp_client(struct conn_info *info)
{
	int fd;
	CLIENT *client;
	struct sockaddr_in laddr, raddr;
	struct hostent *hp;

	if (info->proto->p_proto != IPPROTO_UDP)
		return NULL;

	memset(&laddr, 0, sizeof(laddr));
	memset(&raddr, 0, sizeof(raddr));

	hp = gethostbyname(info->host);
	if (!hp)
		return NULL;

	raddr.sin_family = AF_INET;
	raddr.sin_port = htons(info->port);
	memcpy(&raddr.sin_addr.s_addr, hp->h_addr, hp->h_length);

	/*
	 * bind to any unused port.  If we left this up to the rpc
	 * layer, it would bind to a reserved port, which has been shown
	 * to exhaust the reserved port range in some situations.
	 */
	fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (fd < 0)
		return NULL;
	laddr.sin_family = AF_INET;
	laddr.sin_port = 0;
	laddr.sin_addr.s_addr = htonl(INADDR_ANY);

	if (bind(fd, (struct sockaddr *)&laddr, 
		 sizeof(struct sockaddr_in)) < 0) {
		close(fd);
		fd = RPC_ANYSOCK;
		/* FALLTHROUGH */
	}

	client = clntudp_bufcreate(&raddr,
				   info->program, info->version,
				   info->timeout, &fd,
				   info->send_sz, info->recv_sz);
	if (client)
		clnt_control(client, CLSET_FD_CLOSE, NULL);

	return client;
}
Exemplo n.º 14
0
static void
set_rdev(struct key_call_private *kcp)
{
	int fd;
	struct stat stbuf;

	if (clnt_control(kcp->client, CLGET_FD, (char *)&fd) != TRUE ||
	    fstat(fd, &stbuf) == -1) {
		syslog(LOG_DEBUG, "keyserv_client:  can't get info");
		kcp->fd = -1;
		return;
	}
	kcp->fd = fd;
	kcp->rdev = stbuf.st_rdev;
}
Exemplo n.º 15
0
void rpcConnect(void)
{
    int i;

    for (i = 0; i < giga_options_t.num_servers; i++) {
        if (rpc_host_connect(&rpc_clnts[i], giga_options_t.serverlist[i]) < 0)
            LOG_ERR("CONN_ERROR: -> s[%d]", i);
        else {
            struct timeval to;
            to.tv_sec = 180;
            to.tv_usec = 0;
            clnt_control(rpc_clnts[i], CLSET_TIMEOUT, (char*)&to);
            LOG_ERR("CONN_SETUP: -> s[%d]", i);
        }
    }
}
Exemplo n.º 16
0
/*
 * Create a TCP RPC client using non-blocking connect
 */
static CLIENT* create_tcp_client(struct conn_info *info)
{
	int fd;
	CLIENT *client;
	struct sockaddr_in addr;
	struct hostent *hp;
	int ret;

	if (info->proto->p_proto != IPPROTO_TCP)
		return NULL;

	memset(&addr, 0, sizeof(addr));

	hp = gethostbyname(info->host);
	if (!hp)
		return NULL;

	addr.sin_family = AF_INET;
	addr.sin_port = htons(info->port);
	memcpy(&addr.sin_addr.s_addr, hp->h_addr, hp->h_length);

	fd = socket(PF_INET, SOCK_STREAM, info->proto->p_proto);
	if (fd < 0)
		return NULL;

	ret = connect_nb(fd, &addr, &info->timeout);
	if (ret < 0)
		goto out_close;

	client = clnttcp_create(&addr,
				info->program, info->version, &fd,
				info->send_sz, info->recv_sz);
	if (!client)
		goto out_close;

	/* Close socket fd on destroy, as is default for rpcowned fds */
	if  (!clnt_control(client, CLSET_FD_CLOSE, NULL)) {
		clnt_destroy(client);
		goto out_close;
	}

	return client;

out_close:
	close(fd);
	return NULL;
}
Exemplo n.º 17
0
CLIENT *getConnection(int srv_id)
{
    assert(srv_id >= 0 && srv_id < giga_options_t.num_servers);

    if (rpc_clnts[srv_id] == NULL) {
        LOG_ERR("Trying connection for server[%d] ...", srv_id);
        if (rpc_host_connect(&rpc_clnts[srv_id],
                             giga_options_t.serverlist[srv_id]) < 0) {
            LOG_ERR("ERROR connecting to server [%d]", srv_id);
            return NULL;
        }
        struct timeval to;
        to.tv_sec = 180;
        to.tv_usec = 0;
        clnt_control(rpc_clnts[srv_id], CLSET_TIMEOUT, (char*)&to);
    }

    return rpc_clnts[srv_id];
}
Exemplo n.º 18
0
int main(int argc, char **argv)
{
	int ret;
	const char *host;
	int udp_retry_timeout;
	CLIENT *clnt;
	struct qcsapi_output output;

	output = qcsapi_output_stdio_adapter();

	host = client_qcsapi_find_host_addr(&argc, &argv);
	if (!host) {
		client_qcsapi_find_host_errmsg(argv[0]);
		exit(1);
	}

	udp_retry_timeout = client_qcsapi_get_udp_retry_timeout(&argc, &argv);

	clnt = clnt_create(host, QCSAPI_PROG, QCSAPI_VERS, "udp");
	if (clnt == NULL) {
		clnt = clnt_create(host, QCSAPI_PROG, QCSAPI_VERS, "tcp");
	} else {
		if (udp_retry_timeout>0) {
			struct timeval value;
			value.tv_sec = (time_t)udp_retry_timeout;
			value.tv_usec = (suseconds_t)0;
			clnt_control(clnt, CLSET_RETRY_TIMEOUT, (char *)&value);
		}
	}

	if (clnt == NULL) {
		clnt_pcreateerror(host);
		exit(1);
	}

	client_qcsapi_set_rpcclient(clnt);

	ret = qcsapi_main(&output, argc, argv);

	clnt_destroy(clnt);

	return ret;
}
Exemplo n.º 19
0
int rpc_connect(void)
{
    int i;

    rpc_clients = malloc(sizeof(CLIENT *)*skye_options.servercount);
    if (!rpc_clients)
        return -ENOMEM;

    for (i = 0; i < skye_options.servercount; i++){
        int ret = rpc_host_connect(&rpc_clients[i], skye_options.serverlist[i]);
        if (ret < 0)
            return ret;
    }
    for (i = 0; i < skye_options.servercount; i++){
	struct timeval to;
        to.tv_sec = 60;
        to.tv_usec = 0;
	clnt_control(rpc_clients[i], CLSET_TIMEOUT, (char*)&to);
    }
    
    return 0;
}
Exemplo n.º 20
0
void
initialize(iter_t iterations, void* cookie)
{
	struct	timeval tv;
	state_t *state = (state_t*)cookie;

	if (iterations) return;

	state->cl = clnt_create(state->server, XACT_PROG, XACT_VERS, 
				state->protocol);
	if (!state->cl) {
		clnt_pcreateerror(state->server);
		exit(1);
	}
	if (strcasecmp(state->protocol, proto[1]) == 0) {
		tv.tv_sec = 0;
		tv.tv_usec = 2500;
		if (!clnt_control(state->cl, CLSET_RETRY_TIMEOUT, (char *)&tv)) {
			clnt_perror(state->cl, "setting timeout");
			exit(1);
		}
	}
}
Exemplo n.º 21
0
void
benchmark(char *server, char* protocol)
{
	CLIENT *cl;
	char	buf[256];
	struct	timeval tv;

	cl = clnt_create(server, XACT_PROG, XACT_VERS, protocol);
	if (!cl) {
		clnt_pcreateerror(server);
		exit(1);
	}
	if (strcasecmp(protocol, proto[1]) == 0) {
		tv.tv_sec = 0;
		tv.tv_usec = 2500;
		if (!clnt_control(cl, CLSET_RETRY_TIMEOUT, (char *)&tv)) {
			clnt_perror(cl, "setting timeout");
			exit(1);
		}
	}
	BENCH(doit(cl, server, protocol), MEDIUM);
	sprintf(buf, "RPC/%s latency using %s", protocol, server);
	micro(buf, get_n());
}
Exemplo n.º 22
0
/* returns an initialised client, or NULL on error */
CLIENT *create_rpc_client(struct sockaddr_in *client_sock, struct addrinfo *hints, unsigned long prognum, unsigned long version, struct timeval timeout, struct sockaddr_in src_ip) {
    CLIENT *client = NULL;
    int sock;
    long unsigned protocol; /* for portmapper */
    char src[INET_ADDRSTRLEN];
    char dst[INET_ADDRSTRLEN];
    struct sockaddr_in getaddr; /* for getsockname */
    socklen_t len = sizeof(getaddr);

    /* Even if you specify a source address the portmapper will use the default one */
    /* this applies to pmap_getport or clnt*_create */
    /* so use our own get_rpc_port */

    /* check if we need to use the portmapper, 0 = yes */
    if (client_sock->sin_port == 0) {
        client_sock->sin_port = htons(PMAPPORT); /* 111 */

        sock = socket(AF_INET, hints->ai_socktype, 0);
        if (sock < 0) {
            perror("create_rpc_client(socket)");
            return NULL;
        }

        /* set the source address if specified */
        if (src_ip.sin_addr.s_addr) {
            /* portmapper doesn't need a reserved port */
            src_ip.sin_port = 0;

            if (bind(sock, (struct sockaddr *) &src_ip, sizeof(src_ip)) == -1) {
                perror("create_rpc_client(bind)");
                return NULL;
            }
        }

        if (connect(sock, (struct sockaddr *)client_sock, sizeof(struct sockaddr)) == 0) {
            /* TCP */
            if (hints->ai_socktype == SOCK_STREAM) {
                protocol = PMAP_IPPROTO_TCP;
                    client = clnttcp_create(client_sock, PMAPPROG, PMAPVERS, &sock, 0, 0);
                    if (client == NULL) {
                        clnt_pcreateerror("clnttcp_create");
                    }
            /* UDP */
            } else {
                protocol = PMAP_IPPROTO_UDP;
                client = clntudp_create(client_sock, PMAPPROG, PMAPVERS, timeout, &sock);
                if (client == NULL) {
                    clnt_pcreateerror("clntudp_create");
                }
            }
        } else {
            perror("create_rpc_client(connect)");
            return NULL;
        }

        if (verbose) {
            if (getsockname(sock, (struct sockaddr *)&getaddr, &len) == -1) {
                perror("create_rpc_client(getsockname)");
                /* this is just verbose output so don't return an error */
            } else {
                inet_ntop(AF_INET, (struct sockaddr_in *)&getaddr.sin_addr, src, INET_ADDRSTRLEN);
                //inet_ntop(AF_INET, &(((struct sockaddr_in *)&client_sock)->sin_addr), dst, INET_ADDRSTRLEN);
                inet_ntop(AF_INET, &(client_sock->sin_addr), dst, INET_ADDRSTRLEN);
                debug("portmap request = %s:%u -> %s:%u\n", src, ntohs(getaddr.sin_port), dst, ntohs(client_sock->sin_port));
            }
        }

        /* query the portmapper */
        client_sock->sin_port = get_rpc_port(client, prognum, version, protocol);

        /* close the portmapper connection */
        client = destroy_rpc_client(client);

        /* by this point we should know which port we're talking to */
        debug("portmapper = %s:%u\n", dst, ntohs(client_sock->sin_port));
    }

    /* now make the client connection */

    /* by now we should have a port defined unless the program isn't registered */
    if (client_sock->sin_port) {
        /* Make sure and make new sockets for each new connection */
        /* clnttcp_create will happily reuse open sockets */
        sock = socket(AF_INET, hints->ai_socktype, 0);
        if (sock < 0) {
            perror("create_rpc_client(socket)");
            return NULL;
        }

        /* always try and bind to a low port first */
        /* could check for root here but there are other mechanisms for allowing processes to bind to low ports */
        if (bindresvport(sock, &src_ip) == -1) {
            /* permission denied, ie we aren't root */
            if (errno == EACCES) {
                /* try an ephemeral port */
                src_ip.sin_port = htons(0);
            } else {
                perror("create_rpc_client(bindresvport)");
                return NULL;
            }
        }

        /* now we're bound to a local socket, try and connect to the server */
        if (connect(sock, (struct sockaddr *)client_sock, sizeof(struct sockaddr)) == 0) {
            /* TCP */
            if (hints->ai_socktype == SOCK_STREAM) {
                    /* TODO set recvsz and sendsz to the NFS blocksize */
                    client = clnttcp_create(client_sock, prognum, version, &sock, 0, 0);
                    if (client == NULL) {
                        clnt_pcreateerror("clnttcp_create");
                    }
            /* UDP */
            } else {
                client = clntudp_create(client_sock, prognum, version, timeout, &sock);
                if (client == NULL) {
                    clnt_pcreateerror("clntudp_create");
                }
            }
        } else {
            perror("create_rpc_client(connect)");
            return NULL;
        }

        if (verbose) {
            if (getsockname(sock, (struct sockaddr *)&getaddr, &len) == -1) {
                perror("create_rpc_client(getsockname)");
                /* this is just verbose output so don't return an error */
            } else {
                inet_ntop(AF_INET, (struct sockaddr_in *)&getaddr.sin_addr, src, INET_ADDRSTRLEN);
                inet_ntop(AF_INET, &(client_sock->sin_addr), dst, INET_ADDRSTRLEN);
                debug("Connected = %s:%u -> %s:%u\n", src, ntohs(getaddr.sin_port), dst, ntohs(client_sock->sin_port));
            }
        }
    }

    if (client) {
        /* TODO check return values */
        /* use AUTH_NONE authentication by default */
        client->cl_auth = authnone_create();
        /* set the RPC timeout */
        clnt_control(client, CLSET_TIMEOUT, (char *)&timeout);
        /* set the socket to close when the client is destroyed */
        clnt_control(client, CLSET_FD_CLOSE, NULL);
    }

    return client;
}
Exemplo n.º 23
0
/*
 * return list of all drives
 */
int
meta_list_drives(
	char			*hostname,
	char			*path,
	mhd_did_flags_t		flags,
	mhd_drive_info_list_t	*listp,
	md_error_t		*ep
)
{
	mhd_list_args_t		args;
	mhd_list_res_t		results;
	mhd_error_t		*mhep = &results.status;
	mhd_handle_t		*hp = NULL;
	int			rval = -1;

	/* if not doing ioctls */
	if (! do_mhioctl())
		return (0);

	/* initialize */
	(void) memset(&args, 0, sizeof (args));
	(void) memset(&results, 0, sizeof (results));

	/* build arguments */
	if (path == NULL)
		path = getenv("MD_DRIVE_ROOT");
	if ((path != NULL) && (*path != '\0'))
		args.path = Strdup(path);
	args.flags = flags;

	/* open connection */
	if ((hp = open_metamhd(hostname, ep)) == NULL)
		return (-1);
	clnt_control(hp->clientp, CLSET_TIMEOUT, (char *)&tk_own_timeout);

	/* get list */
	if (mhd_list_1(&args, &results, hp->clientp) != RPC_SUCCESS) {
		(void) mdrpcerror(ep, hp->clientp, hp->hostname,
		    dgettext(TEXT_DOMAIN, "metamhd list"));
		goto out;
	} else if (mhstealerror(mhep, ep) != 0) {
		goto out;
	}

	/* sort list */
	sort_drives(&results.results);

	/* steal list */
	*listp = results.results;
	results.results.mhd_drive_info_list_t_len = 0;
	results.results.mhd_drive_info_list_t_val = NULL;
	rval = listp->mhd_drive_info_list_t_len;	/* success */

	/* cleanup, return success */
out:
	xdr_free(xdr_mhd_list_args_t, (char *)&args);
	xdr_free(xdr_mhd_list_res_t, (char *)&results);
	if (hp != NULL)
		close_metamhd(hp);
	return (rval);
}
Exemplo n.º 24
0
/*
 * get status of drives
 */
int
meta_status_own(
	char			*sname,
	md_disk_status_list_t	*dslp,
	int			partial_set,
	md_error_t		*ep
)
{
	md_disk_status_list_t	*p;
	uint_t			ndev = 0;
	mhd_status_args_t	args;
	mhd_status_res_t	results;
	mhd_error_t		*mhep = &results.status;
	mhd_set_t		*mhsp = &args.set;
	uint_t			i;
	char			*e;
	mhd_handle_t		*hp = NULL;
	int			rval = -1;

	/* if not doing ioctls */
	if (! do_mhioctl())
		return (0);

	/* count drives, get set */
	for (p = dslp; (p != NULL); p = p->next)
		++ndev;
	if (ndev == 0)
		return (0);

	/* initialize */
	(void) memset(&args, 0, sizeof (args));
	(void) memset(&results, 0, sizeof (results));

	/* build arguments */
	mhsp->setname = Strdup(sname);
	mhsp->drives.drives_len = ndev;
	mhsp->drives.drives_val
	    = Calloc(ndev, sizeof (*mhsp->drives.drives_val));
	for (p = dslp, i = 0; (i < ndev); p = p->next, ++i) {
		mhsp->drives.drives_val[i] = Strdup(p->drivenamep->rname);
	}
	if (partial_set)
		args.options |= MHD_PARTIAL_SET;
	if (((e = getenv("MD_DEBUG")) != NULL) &&
	    (strstr(e, "NOTHREAD") != NULL)) {
		args.options |= MHD_SERIAL;
	}

	/* open connection */
	if ((hp = open_metamhd(NULL, ep)) == NULL)
		return (-1);
	clnt_control(hp->clientp, CLSET_TIMEOUT, (char *)&tk_own_timeout);

	/* get status */
	if (mhd_status_1(&args, &results, hp->clientp) != RPC_SUCCESS) {
		(void) mdrpcerror(ep, hp->clientp, hp->hostname,
		    dgettext(TEXT_DOMAIN, "metamhd status"));
		goto out;
	} else if (mhstealerror(mhep, ep) != 0) {
		goto out;
	}

	/* do something with it */
	assert(results.results.results_len == ndev);
	for (p = dslp, i = 0; (i < ndev); p = p->next, ++i) {
		mhd_drive_status_t	*resp = &results.results.results_val[i];
		mddrivename_t		*dp = p->drivenamep;
		mhd_error_t		mherror;

		/* make sure we have the right drive */
		assert(strcmp(dp->rname, resp->drive) == 0);

		/* copy status */
		if (resp->errnum != 0) {
			(void) memset(&mherror, 0, sizeof (mherror));
			mherror.errnum = resp->errnum;
			mherror.name = Strdup(resp->drive);
			(void) mhstealerror(&mherror, &p->status);
		}
	}
	rval = 0;		/* success */

	/* cleanup, return success */
out:
	xdr_free(xdr_mhd_status_args_t, (char *)&args);
	xdr_free(xdr_mhd_status_res_t, (char *)&results);
	if (hp != NULL)
		close_metamhd(hp);
	return (rval);
}
Exemplo n.º 25
0
/*
 * release ownership of drives
 */
int
meta_rel_own(
	char			*sname,
	mddrivenamelist_t	*dnlp,
	int			partial_set,
	md_error_t		*ep
)
{
	mddrivenamelist_t	*p;
	uint_t			ndev = 0;
	mhd_relown_args_t	args;
	mhd_error_t		mherror;
	mhd_set_t		*mhsp = &args.set;
	uint_t			i;
	char			*e;
	mhd_handle_t		*hp = NULL;
	int			rval = -1;

	/*
	 * RFE 4126509.  Check the runtime parameters to see if
	 * they're set to disable MHIOCRELEASE and MHIOCENFAILFAST
	 * ioctl() operations on the disks.  If so, return
	 * immediately without performing the operations.
	 */

	if (do_owner_ioctls() == B_FALSE) {
		return (0);
	}

	/*
	 * if not doing ioctls (HK 98/10/28: the following code tests
	 * an environment variable, and was apparently inserted to
	 * make testing easier.)
	 */

	if (! do_mhioctl())
		return (0);

	/* count drives, get set */
	for (p = dnlp; (p != NULL); p = p->next)
		++ndev;
	if (ndev == 0)
		return (0);

	/* initialize */
	(void) memset(&args, 0, sizeof (args));
	(void) memset(&mherror, 0, sizeof (mherror));

	/* build arguments */
	mhsp->setname = Strdup(sname);
	mhsp->drives.drives_len = ndev;
	mhsp->drives.drives_val
	    = Calloc(ndev, sizeof (*mhsp->drives.drives_val));
	for (p = dnlp, i = 0; (i < ndev); p = p->next, ++i) {
		mhsp->drives.drives_val[i] = Strdup(p->drivenamep->rname);
	}
	if (partial_set)
		args.options |= MHD_PARTIAL_SET;
	if (((e = getenv("MD_DEBUG")) != NULL) &&
	    (strstr(e, "NOTHREAD") != NULL)) {
		args.options |= MHD_SERIAL;
	}

	/* open connection */
	if ((hp = open_metamhd(NULL, ep)) == NULL)
		return (-1);
	clnt_control(hp->clientp, CLSET_TIMEOUT, (char *)&rel_own_timeout);

	/* take ownership */
	if (mhd_relown_1(&args, &mherror, hp->clientp) != RPC_SUCCESS) {
		(void) mdrpcerror(ep, hp->clientp, hp->hostname,
		    "metamhd relown");
	} else if (mhstealerror(&mherror, ep) == 0) {
		rval = 0;	/* success */
	}

	/* cleanup, return success */
out:
	xdr_free(xdr_mhd_relown_args_t, (char *)&args);
	xdr_free(xdr_mhd_error_t, (char *)&mherror);
	if (hp != NULL)
		close_metamhd(hp);
	return (rval);
}
Exemplo n.º 26
0
/*
 * take ownership of drives
 */
int
meta_take_own(
	char			*sname,
	mddrivenamelist_t	*dnlp,
	mhd_mhiargs_t		*mhiargsp,
	int			partial_set,
	md_error_t		*ep
)
{
	mddrivenamelist_t	*p;
	uint_t			ndev = 0;
	mhd_tkown_args_t	args;
	mhd_error_t		mherror;
	mhd_set_t		*mhsp = &args.set;
	uint_t			i;
	char			*e;
	mhd_handle_t		*hp = NULL;
	int			rval = -1;

	/*
	 * RFE 4126509.  Check the runtime parameters to see if
	 * they're set to disable MHIOCTKOWN ioctl() operations
	 * on the disks.  If so, return immediately without
	 * performing the operations.
	 */

	if (do_owner_ioctls() == B_FALSE) {
		return (0);
	}

	/* count drives, get set */
	for (p = dnlp; (p != NULL); p = p->next)
		++ndev;
	if (ndev == 0)
		return (0);

	/* initialize */
	(void) memset(&args, 0, sizeof (args));
	(void) memset(&mherror, 0, sizeof (mherror));

	/* build arguments */
	mhsp->setname = Strdup(sname);
	mhsp->drives.drives_len = ndev;
	mhsp->drives.drives_val
	    = Calloc(ndev, sizeof (*mhsp->drives.drives_val));
	for (p = dnlp, i = 0; (i < ndev); p = p->next, ++i) {
		mhsp->drives.drives_val[i] = Strdup(p->drivenamep->rname);
	}
	args.timeouts = *mhiargsp;
	args.ff_mode = MHD_FF_DRIVER;
	if (((e = getenv("MD_DEBUG")) != NULL) &&
	    ((e = strstr(e, "FAILFAST=")) != NULL) &&
	    ((e = strchr(e, '=')) != NULL)) {
		++e;
		if (strcmp(e, "NONE") == 0)
			args.ff_mode = MHD_FF_NONE;
		else if (strcmp(e, "DRIVER") == 0)
			args.ff_mode = MHD_FF_DRIVER;
		else if (strcmp(e, "DEBUG") == 0)
			args.ff_mode = MHD_FF_DEBUG;
		else if (strcmp(e, "HALT") == 0)
			args.ff_mode = MHD_FF_HALT;
		else if (strcmp(e, "PANIC") == 0)
			args.ff_mode = MHD_FF_PANIC;
	}
	if (partial_set)
		args.options |= MHD_PARTIAL_SET;
	if (((e = getenv("MD_DEBUG")) != NULL) &&
	    (strstr(e, "NOTHREAD") != NULL)) {
		args.options |= MHD_SERIAL;
	}

	/* open connection */
	if ((hp = open_metamhd(NULL, ep)) == NULL)
		return (-1);
	clnt_control(hp->clientp, CLSET_TIMEOUT, (char *)&tk_own_timeout);

	/* take ownership */
	if (mhd_tkown_1(&args, &mherror, hp->clientp) != RPC_SUCCESS) {
		(void) mdrpcerror(ep, hp->clientp, hp->hostname,
		    "metamhd tkown");
	} else if (mhstealerror(&mherror, ep) == 0) {
		rval = 0;	/* success */
	}

	/* cleanup, return success */
out:
	xdr_free(xdr_mhd_tkown_args_t, (char *)&args);
	xdr_free(xdr_mhd_error_t, (char *)&mherror);
	if (hp != NULL)
		close_metamhd(hp);
	return (rval);
}
Exemplo n.º 27
0
CLIENT *
get_client(struct sockaddr_in *host_addr, u_long vers)
{
	CLIENT *client;
	int     sock_no, i;
	struct timeval retry_time, time_now;

	gettimeofday(&time_now, NULL);

	/*
	 * Search for the given client in the cache, zapping any expired
	 * entries that we happen to notice in passing.
	 */
	for (i = 0; i < CLIENT_CACHE_SIZE; i++) {
		client = clnt_cache_ptr[i];
		if (client && ((clnt_cache_time[i] + CLIENT_CACHE_LIFETIME)
		    < time_now.tv_sec)) {
			/* Cache entry has expired. */
			if (debug_level > 3)
				syslog(LOG_DEBUG, "Expired CLIENT* in cache");
			clnt_cache_time[i] = 0L;
			clnt_destroy(client);
			clnt_cache_ptr[i] = NULL;
			client = NULL;
		}
		if (client && !memcmp(&clnt_cache_addr[i], &host_addr->sin_addr,
			sizeof(struct in_addr))) {
			/* Found it! */
			if (debug_level > 3)
				syslog(LOG_DEBUG, "Found CLIENT* in cache");
			return client;
		}
	}

	/* Not found in cache.  Free the next entry if it is in use. */
	if (clnt_cache_ptr[clnt_cache_next_to_use]) {
		clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]);
		clnt_cache_ptr[clnt_cache_next_to_use] = NULL;
	}

	sock_no = RPC_ANYSOCK;
	retry_time.tv_sec = 5;
	retry_time.tv_usec = 0;
	host_addr->sin_port = 0;
	client = clntudp_create(host_addr, NLM_PROG, vers, retry_time, &sock_no);
	if (!client) {
		syslog(LOG_ERR, "%s", clnt_spcreateerror("clntudp_create"));
		syslog(LOG_ERR, "Unable to return result to %s",
		    inet_ntoa(host_addr->sin_addr));
		return NULL;
	}

	/* Success - update the cache entry */
	clnt_cache_ptr[clnt_cache_next_to_use] = client;
	clnt_cache_addr[clnt_cache_next_to_use] = host_addr->sin_addr;
	clnt_cache_time[clnt_cache_next_to_use] = time_now.tv_sec;
	if (++clnt_cache_next_to_use >= CLIENT_CACHE_SIZE)
		clnt_cache_next_to_use = 0;

	/*
	 * Disable the default timeout, so we can specify our own in calls
	 * to clnt_call().  (Note that the timeout is a different concept
	 * from the retry period set in clnt_udp_create() above.)
	 */
	retry_time.tv_sec = -1;
	retry_time.tv_usec = -1;
	clnt_control(client, CLSET_TIMEOUT, (char *)(void *)&retry_time);

	if (debug_level > 3)
		syslog(LOG_DEBUG, "Created CLIENT* for %s",
		    inet_ntoa(host_addr->sin_addr));
	return client;
}
Exemplo n.º 28
0
int
__yp_ping(struct in_addr *restricted_addrs, int cnt, char *dom, short *port)
{
	struct timeval		tv = { 5, 0 };
	struct ping_req		**reqs;
	unsigned long		i;
	int			async;
	struct sockaddr_in	sin, *any = NULL;
	struct netbuf		addr;
	int			winner = -1;
	u_int32_t		xid_seed, xid_lookup;
	int			sock, dontblock = 1;
	CLIENT			*clnt;
	char			*foo = dom;
	int			validsrvs = 0;

	/* Set up handles. */
	reqs = calloc(1, sizeof(struct ping_req *) * cnt);
	xid_seed = time(NULL) ^ getpid();

	for (i = 0; i < cnt; i++) {
		bzero((char *)&sin, sizeof(sin));
		sin.sin_family = AF_INET;
		bcopy((char *)&restricted_addrs[i],
			(char *)&sin.sin_addr, sizeof(struct in_addr));
		sin.sin_port = htons(__pmap_getport(&sin, YPPROG,
					YPVERS, IPPROTO_UDP));
		if (sin.sin_port == 0)
			continue;
		reqs[i] = calloc(1, sizeof(struct ping_req));
		bcopy((char *)&sin, (char *)&reqs[i]->sin, sizeof(sin));
		any = &reqs[i]->sin;
		reqs[i]->xid = xid_seed;
		xid_seed++;
		validsrvs++;
	}

	/* Make sure at least one server was assigned */
	if (!validsrvs) {
		free(reqs);
		return(-1);
	}

	/* Create RPC handle */
	sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	clnt = clntudp_create(any, YPPROG, YPVERS, tv, &sock);
	if (clnt == NULL) {
		close(sock);
		for (i = 0; i < cnt; i++)
			if (reqs[i] != NULL)
				free(reqs[i]);
		free(reqs);
		return(-1);
	}
	clnt->cl_auth = authunix_create_default();
	tv.tv_sec = 0;

	clnt_control(clnt, CLSET_TIMEOUT, (char *)&tv);
	async = TRUE;
	clnt_control(clnt, CLSET_ASYNC, (char *)&async);
	ioctl(sock, FIONBIO, &dontblock);

	/* Transmit */
	for (i = 0; i < cnt; i++) {
		if (reqs[i] != NULL) {
			clnt_control(clnt, CLSET_XID, (char *)&reqs[i]->xid);
			addr.len = sizeof(reqs[i]->sin);
			addr.buf = (char *) &reqs[i]->sin;
			clnt_control(clnt, CLSET_SVC_ADDR, &addr);
			ypproc_domain_nonack_2_send(&foo, clnt);
		}
	}

	/* Receive reply */
	ypproc_domain_nonack_2_recv(&foo, clnt);

	/* Got a winner -- look him up. */
	clnt_control(clnt, CLGET_XID, (char *)&xid_lookup);
	for (i = 0; i < cnt; i++) {
		if (reqs[i] != NULL && reqs[i]->xid == xid_lookup) {
			winner = i;
			*port = reqs[i]->sin.sin_port;
		}
	}

	/* Shut everything down */
	auth_destroy(clnt->cl_auth);
	clnt_destroy(clnt);
	close(sock);

	for (i = 0; i < cnt; i++)
		if (reqs[i] != NULL)
			free(reqs[i]);
	free(reqs);

	return(winner);
}
Exemplo n.º 29
0
int main(int argn, char *argc[])
{
	//Program parameters : argc[1] : HostName or Host IP
	//                                         argc[2] : Server Program Number
	//                                         other arguments depend on test case

	//run_mode can switch into stand alone program or program launch by shell script
	//1 : stand alone, debug mode, more screen information
	//0 : launch by shell script as test case, only one printf -> result status
	int run_mode = 0;
	int test_status = 0;	//Default test result set to FAILED
	int progNum = atoi(argc[2]);
	char proto[8] = "udp";
	CLIENT *clnt = NULL;
	struct timeval tvSet;
	struct timeval tvGet;

	//First of all, create a client
	clnt = clnt_create(argc[1], progNum, VERSNUM, proto);

	if (run_mode) {
		printf("CLIENT : %p\n", clnt);
	}

	tvSet.tv_sec = 1000;
	tvSet.tv_usec = 2000;

	clnt_control(clnt, CLSET_TIMEOUT, (char *)&tvSet);
	clnt_control(clnt, CLGET_TIMEOUT, (char *)&tvGet);

	if ((tvSet.tv_sec != tvGet.tv_sec) || (tvSet.tv_usec != tvGet.tv_usec))
		test_status = 1;

	if (run_mode) {
		printf("Time Set : %ld sec %ld usec\n",
		       (long)tvSet.tv_sec, (long)tvSet.tv_usec);
		printf("Time Get : %ld sec %ld usec\n",
		       (long)tvGet.tv_sec, (long)tvGet.tv_usec);
	}

	tvSet.tv_sec = 4000;
	tvSet.tv_usec = 8000;

	clnt_control(clnt, CLSET_RETRY_TIMEOUT, (char *)&tvSet);
	clnt_control(clnt, CLGET_RETRY_TIMEOUT, (char *)&tvGet);

	if ((tvSet.tv_sec != tvGet.tv_sec) || (tvSet.tv_usec != tvGet.tv_usec))
		test_status = 1;

	if (run_mode) {
		printf("Time Set : %ld sec %ld usec\n",
		       (long)tvSet.tv_sec, (long)tvSet.tv_usec);
		printf("Time Get : %ld sec %ld usec\n",
		       (long)tvGet.tv_sec, (long)tvGet.tv_usec);
	}
	//This last printf gives the result status to the tests suite
	//normally should be 0: test has passed or 1: test has failed
	printf("%d\n", test_status);

	return test_status;
}
Exemplo n.º 30
0
/*
 * Generic client creation: takes (hostname, program-number, protocol) and
 * returns client handle. Default options are set, which the user can
 * change using the rpc equivalent of ioctl()'s.
 */
CLIENT *
clnt_create(
	char *hostname,
	rpcprog_t prog,
	rpcvers_t vers,
	char *proto)
{
	struct hostent *h;
	struct protoent *p;
	struct sockaddr_in sockin;
	int sock;
	struct timeval tv;
	CLIENT *client;

	h = gethostbyname(hostname);
	if (h == NULL) {
		rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
		return (NULL);
	}
	if (h->h_addrtype != AF_INET) {
		/*
		 * Only support INET for now
		 */
		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
		rpc_createerr.cf_error.re_errno = EAFNOSUPPORT;
		return (NULL);
	}
	memset(&sockin, 0, sizeof(sockin));
#if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
	sockin.sin_len = sizeof(sockin);
#endif
	sockin.sin_family = h->h_addrtype;
	sockin.sin_port = 0;
	memmove((char*)&sockin.sin_addr, h->h_addr, sizeof(sockin.sin_addr));
	p = getprotobyname(proto);
	if (p == NULL) {
		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
		rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;
		return (NULL);
	}
	sock = RPC_ANYSOCK;
	switch (p->p_proto) {
	case IPPROTO_UDP:
		tv.tv_sec = 5;
		tv.tv_usec = 0;
		client = clntudp_create(&sockin, prog, vers, tv, &sock);
		if (client == NULL) {
			return (NULL);
		}
		tv.tv_sec = 120;
		clnt_control(client, CLSET_TIMEOUT, &tv);
		break;
	case IPPROTO_TCP:
		client = clnttcp_create(&sockin, prog, vers, &sock, 0, 0);
		if (client == NULL) {
			return (NULL);
		}
		tv.tv_sec = 120;
		tv.tv_usec = 0;
		clnt_control(client, CLSET_TIMEOUT, &tv);
		break;
	default:
		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
		rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;
		return (NULL);
	}
	return (client);
}