void *my_thread_process(void *arg)
{
	CLIENT *client = NULL;
	struct netconfig *nconf = NULL;
	struct netbuf svcaddr;
	char addrbuf[ADDRBUFSIZE];
	enum clnt_stat cs;
	int var_snd = 10;
	int var_rec = -1;
	struct timeval tv;
	int i;

	if (run_mode == 1) {
		fprintf(stderr, "Thread %d\n", atoi(arg));
	}

	tv.tv_sec = 0;
	tv.tv_usec = 100;

	nconf = getnetconfigent("udp");
	if (nconf == (struct netconfig *)NULL) {
		//syslog(LOG_ERR, "getnetconfigent for udp failed");
		printf("err nconf\n");
		pthread_exit(1);
	}

	svcaddr.len = 0;
	svcaddr.maxlen = ADDRBUFSIZE;
	svcaddr.buf = addrbuf;

	if (svcaddr.buf == NULL) {
		pthread_exit(1);
	}
	//printf("svcaddr reserved (%s)\n", argc[1]);

	if (!rpcb_getaddr(progNum + atoi(arg), VERSNUM, nconf,
			  &svcaddr, hostname)) {
		fprintf(stderr, "rpcb_getaddr failed!!\n");
		pthread_exit(1);
	}
	//printf("svc get\n");

	client = clnt_dg_create(RPC_ANYFD, &svcaddr,
				progNum + atoi(arg), VERSNUM, 1024, 1024);

	if (client == NULL) {
		clnt_pcreateerror("ERR");
		pthread_exit(1);
	}

	for (i = 0; i < callNb; i++) {
		cs = clnt_call(client, PROCNUM,
			       (xdrproc_t) xdr_int, (char *)&var_snd,
			       (xdrproc_t) xdr_int, (char *)&var_rec, tv);

		thread_array_result[atoi(arg)] += (cs == RPC_SUCCESS);
	}

	pthread_exit(0);
}
void *my_thread_process(void *arg)
{
	int i;
	CLIENT *clnt = NULL;
	struct datas vars;
	static double result = 0;
	struct timeval total_timeout;
	struct netconfig *nconf = NULL;
	struct netbuf svcaddr;
	char addrbuf[ADDRBUFSIZE];

	total_timeout.tv_sec = 1;
	total_timeout.tv_usec = 1;

	nconf = getnetconfigent("udp");

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

	svcaddr.len = 0;
	svcaddr.maxlen = ADDRBUFSIZE;
	svcaddr.buf = addrbuf;

	if (svcaddr.buf == NULL) {
		printf("5\n");
		pthread_exit(5);
	}

	if (!rpcb_getaddr(progNum, VERSNUM, nconf, &svcaddr, hostname)) {
		fprintf(stderr, "rpcb_getaddr failed!!\n");
		printf("5\n");
		pthread_exit(5);
	}

	clnt = clnt_dg_create(RPC_ANYFD, &svcaddr,
			      progNum, VERSNUM, 1024, 1024);

	if (clnt == NULL) {
		printf("5\n");
		pthread_exit(5);
	}

	if (run_mode == 1) {
		fprintf(stderr, "Thread %d\n", atoi(arg));
	}

	vars.a = getRand();
	vars.b = getRand();
	vars.c = getRand();

	resTbl[atoi(arg)].locRes = vars.a + (vars.b * vars.c);

	clnt_call((CLIENT *) clnt, CALCTHREADPROC, (xdrproc_t) xdr_datas, (char *)&vars,	// xdr_in
		  (xdrproc_t) xdr_double, (char *)&resTbl[atoi(arg)].svcRes,	// xdr_out
		  total_timeout);

	thread_array_result[atoi(arg)] =
	    (resTbl[atoi(arg)].svcRes == resTbl[atoi(arg)].locRes) ? 0 : 1;

	if (run_mode == 1) {
		fprintf(stderr, "Thread #%d calc : %lf, received : %lf\n",
			atoi(arg), resTbl[atoi(arg)].locRes,
			resTbl[atoi(arg)].svcRes);
	}

	pthread_exit(0);
}
Пример #3
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 netbuf svcaddr;
    char addrbuf[ADDRBUFSIZE];
	bool_t rpcb_rslt;

	//Initialization
    if (run_mode)
    {
    	printf("Before creation\n");
		printf("client : %d\n", client);
		printf("nconf : %d\n", nconf);
	}

	nconf = getnetconfigent("udp");
	if (nconf == (struct netconfig *) NULL)
	{
		//syslog(LOG_ERR, "getnetconfigent for udp failed");
		fprintf(stderr, "err nconf\n");
		printf("5\n");
		exit(1);
	}

	svcaddr.len = 0;
	svcaddr.maxlen = ADDRBUFSIZE;
	svcaddr.buf = addrbuf;

	if (svcaddr.buf == NULL)
	{
    	/* if malloc() failed, print error messages and exit */
    	printf("5\n");
  		return 1;
    }

    //printf("svcaddr reserved (%s)\n", argc[1]);

	if (!rpcb_getaddr(progNum, VERSNUM, nconf,
                               &svcaddr, argc[1]))
    {
    	fprintf(stderr, "rpcb_getaddr failed!!\n");
    	printf("5\n");
    	exit(1);
    }
    //printf("svc get\n");

	client =  clnt_dg_create(RPC_ANYFD, &svcaddr,
			 				 progNum, VERSNUM, 1024, 1024);/**/

	test_status = ((CLIENT *)client != NULL) ? 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);

	return test_status;
}
int main(int argn, char *argc[])
{
	//Program parameters : argc[1] : HostName or Host IP
	//                                         argc[2] : Server Program Number
	//                                         argc[3] : Number of test call
	//                                         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 i;
	double *resultTbl;
	struct timeval tv1, tv2;
	struct timezone tz;
	long long diff;
	double rslt;
	int progNum = atoi(argc[2]);
	CLIENT *client = NULL;
	struct netconfig *nconf = NULL;
	struct netbuf svcaddr;
	char addrbuf[ADDRBUFSIZE];
	enum clnt_stat cs;
	int var_snd = 0;
	int var_rec = -1;
	struct timeval tv;

	//Test initialisation
	maxIter = atoi(argc[3]);
	resultTbl = malloc(maxIter * sizeof(double));

	tv.tv_sec = 0;
	tv.tv_usec = 100;

	nconf = getnetconfigent("udp");
	if (nconf == NULL) {
		//syslog(LOG_ERR, "getnetconfigent for udp failed");
		fprintf(stderr, "err nconf\n");
		printf("5\n");
		exit(1);
	}

	svcaddr.len = 0;
	svcaddr.maxlen = ADDRBUFSIZE;
	svcaddr.buf = addrbuf;

	if (svcaddr.buf == NULL) {
		/* if malloc() failed, print error messages and exit */
		printf("5\n");
		exit(1);
	}
	//printf("svcaddr reserved (%s)\n", argc[1]);

	if (!rpcb_getaddr(progNum, VERSNUM, nconf, &svcaddr, argc[1])) {
		fprintf(stderr, "rpcb_getaddr failed!!\n");
		printf("5\n");
		exit(1);
	}
	//printf("svc get\n");

	client = clnt_dg_create(RPC_ANYFD, &svcaddr,
				progNum, VERSNUM, 1024, 1024);

	if (client == NULL) {
		clnt_pcreateerror("ERR");
		exit(1);
	}
	//Call tested function several times
	for (i = 0; i < maxIter; i++) {
		//Tic
		gettimeofday(&tv1, &tz);

		//Call function
		cs = clnt_call(client, PROCNUM,
			       (xdrproc_t) xdr_int, (char *)&var_snd,
			       (xdrproc_t) xdr_int, (char *)&var_rec, tv);

		//Toc
		gettimeofday(&tv2, &tz);

		//Add function execution time (toc-tic)
		diff =
		    (tv2.tv_sec - tv1.tv_sec) * 1000000L + (tv2.tv_usec -
							    tv1.tv_usec);
		rslt = (double)diff / 1000;

		if (cs == RPC_SUCCESS) {
			resultTbl[i] = rslt;
		} else {
			test_status = 1;
			break;
		}

		if (run_mode) {
			fprintf(stderr, "lf time  = %lf usecn\n", resultTbl[i]);
		}
	}

	//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);
	printf("%lf %d\n", average(resultTbl), maxIter);
	printf("%lf\n", mini(resultTbl));
	printf("%lf\n", maxi(resultTbl));

	return test_status;
}
Пример #5
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 PASS
    int progNum = atoi(argc[2]);
    int i;
    params paramList[NBCASE];
    CLIENT *client = NULL;
    struct netconfig *nconf = NULL;
    struct netbuf svcaddr;
    char addrbuf[ADDRBUFSIZE];
    bool_t rpcb_rslt;

    //Test initialization
    nconf = getnetconfigent("udp");
    if (nconf == (struct netconfig *)NULL) {
        //syslog(LOG_ERR, "getnetconfigent for udp failed");
        fprintf(stderr, "err nconf\n");
        printf("5\n");
        exit(1);
    }

    svcaddr.len = 0;
    svcaddr.maxlen = ADDRBUFSIZE;
    svcaddr.buf = addrbuf;

    if (svcaddr.buf == NULL) {
        /* if malloc() failed, print error messages and exit */
        printf("5\n");
        return 1;
    }

    if (!rpcb_getaddr(progNum, VERSNUM, nconf, &svcaddr, argc[1])) {
        fprintf(stderr, "rpcb_getaddr failed!!\n");
        printf("5\n");
        exit(1);
    }
    //Test arguments initialization
    paramList[0].bufsnd = 0;
    paramList[0].bufrec = 0;
    paramList[1].bufsnd = 0;
    paramList[1].bufrec = 2147483647;
    paramList[2].bufsnd = 2147483647;
    paramList[2].bufrec = 0;
    paramList[3].bufsnd = 2147483647;
    paramList[3].bufrec = 2147483647;

    //Call tested function using all tests cases
    for (i = 0; i < NBCASE; i++) {
        //Debug mode prints
        if (run_mode == 1) {
            printf("Test using values : %d ", paramList[i].bufsnd);
            printf("%d", paramList[i].bufrec);
            printf("\n");
        }
        //Call function
        client = clnt_dg_create(RPC_ANYFD, &svcaddr,
                                progNum, VERSNUM, paramList[i].bufsnd,
                                paramList[i].bufrec);

        //Check result
        if (client == NULL) {
            //test has failed
            test_status = 1;
            break;
        }
    }

    //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;
}
int main(int argn, char *argc[])
{
	//Program parameters : argc[1] : HostName or Host IP
	//                                         argc[2] : Server Program Number
	//                                         argc[3] : Number of testes function calls
	//                                         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 netbuf svcaddr;
	char addrbuf[ADDRBUFSIZE];
	enum clnt_stat cs;
	int var_snd = 10;
	int var_rec = -1;
	struct timeval tv;
	int nbCall = atoi(argc[3]);
	int nbOk = 0;
	int i;

	//Initialization
	if (run_mode) {
		printf("Before creation\n");
		printf("client : %d\n", client);
		printf("nconf : %d\n", nconf);
	}

	tv.tv_sec = 0;
	tv.tv_usec = 100;

	nconf = getnetconfigent("udp");
	if (nconf == (struct netconfig *)NULL) {
		//syslog(LOG_ERR, "getnetconfigent for udp failed");
		printf("err nconf\n");
		exit(1);
	}

	svcaddr.len = 0;
	svcaddr.maxlen = ADDRBUFSIZE;
	svcaddr.buf = addrbuf;

	if (svcaddr.buf == NULL) {
		/* if malloc() failed, print error messages and exit */
		printf("5\n");
		exit(1);
	}
	//printf("svcaddr reserved (%s)\n", argc[1]);

	if (!rpcb_getaddr(progNum, VERSNUM, nconf, &svcaddr, argc[1])) {
		fprintf(stderr, "rpcb_getaddr failed!!\n");
		exit(1);
	}
	//printf("svc get\n");

	client = clnt_dg_create(RPC_ANYFD, &svcaddr,
				progNum, VERSNUM, 1024, 1024);

	for (i = 0; i < nbCall; i++) {
		cs = clnt_call((CLIENT *) client, PROCNUM, (xdrproc_t) xdr_int, (char *)&var_snd,	// xdr_in
			       (xdrproc_t) xdr_int, (char *)&var_rec,	// xdr_out
			       tv);
		if (cs == RPC_SUCCESS)
			nbOk++;
	}

	if (run_mode == 1) {
		printf("Aimed : %d\n", nbCall);
		printf("Got : %d\n", nbOk);
	}

	test_status = (nbOk == nbCall) ? 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;
}
Пример #7
0
/*
 * Generic client creation:  returns client handle.
 * Default options are set, which the user can
 * change using the rpc equivalent of _ioctl()'s : clnt_control().
 * If fd is RPC_ANYFD, it will be opened using nconf.
 * It will be bound if not so.
 * If sizes are 0; appropriate defaults will be chosen.
 */
CLIENT *
clnt_tli_create(int fd, const struct netconfig *nconf,
	struct netbuf *svcaddr, rpcprog_t prog, rpcvers_t vers,
	uint sendsz, uint recvsz)
{
	CLIENT *cl;			/* client handle */
	bool_t madefd = FALSE;		/* whether fd opened here */
	long servtype;
	int one = 1;
	struct __rpc_sockinfo si;
	extern int __rpc_minfd;

	if (fd == RPC_ANYFD) {
		if (nconf == NULL) {
			rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
			return (NULL);
		}

		fd = __rpc_nconf2fd(nconf);

		if (fd == -1)
			goto err;
		if (fd < __rpc_minfd)
			fd = __rpc_raise_fd(fd);
		madefd = TRUE;
		servtype = nconf->nc_semantics;
		if (!__rpc_fd2sockinfo(fd, &si))
			goto err;
		bindresvport(fd, NULL);
	} else {
		if (!__rpc_fd2sockinfo(fd, &si))
			goto err;
		servtype = __rpc_socktype2seman(si.si_socktype);
		if (servtype == -1) {
			rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
			return (NULL);
		}
	}

	if (si.si_af != ((struct sockaddr *)svcaddr->buf)->sa_family) {
		rpc_createerr.cf_stat = RPC_UNKNOWNHOST;	/* XXX */
		goto err1;
	}

	switch (servtype) {
	case NC_TPI_COTS:
		cl = clnt_vc_create(fd, svcaddr, prog, vers, sendsz, recvsz);
		break;
	case NC_TPI_COTS_ORD:
		if (nconf &&
		    ((strcmp(nconf->nc_protofmly, "inet") == 0) ||
		     (strcmp(nconf->nc_protofmly, "inet6") == 0))) {
			setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one,
			    sizeof (one));
		}
		cl = clnt_vc_create(fd, svcaddr, prog, vers, sendsz, recvsz);
		break;
	case NC_TPI_CLTS:
		cl = clnt_dg_create(fd, svcaddr, prog, vers, sendsz, recvsz);
		break;
	default:
		goto err;
	}

	if (cl == NULL)
		goto err1; /* borrow errors from clnt_dg/vc creates */
	if (nconf) {
		cl->cl_netid = strdup(nconf->nc_netid);
		cl->cl_tp = strdup(nconf->nc_device);
	} else {
		cl->cl_netid = "";
		cl->cl_tp = "";
	}
	if (madefd) {
		(void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL);
/*		(void) CLNT_CONTROL(cl, CLSET_POP_TIMOD, NULL);  */
	};

	return (cl);

err:
	rpc_createerr.cf_stat = RPC_SYSTEMERROR;
	rpc_createerr.cf_error.re_errno = errno;
err1:	if (madefd)
		(void)close(fd);
	return (NULL);
}
Пример #8
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 PASSED
    int progNum = atoi(argc[2]);
    CLIENT *client = NULL;
    struct netconfig *nconf = NULL;
    struct netbuf svcaddr;
    char addrbuf[ADDRBUFSIZE];
    enum clnt_stat cs;
    struct timeval tv;
    //Sent variables
    int intSnd;
    double dblSnd;
    long lngSnd;
    char *strSnd;
    //Received variables
    int intRec;
    double dblRec;
    long lngRec;
    char *strRec;

    //Test initialization
    tv.tv_sec = 0;
    tv.tv_usec = 100;

    nconf = getnetconfigent("udp");
    if (nconf == (struct netconfig *) NULL)
    {
        //syslog(LOG_ERR, "getnetconfigent for udp failed");
        fprintf(stderr, "err nconf\n");
        printf("5\n");
        exit(1);
    }

    svcaddr.len = 0;
    svcaddr.maxlen = ADDRBUFSIZE;
    svcaddr.buf = addrbuf;

    if (svcaddr.buf == (char *)NULL)
    {
        /* if malloc() failed, print error messages and exit */
        printf("5\n");
        exit(1);
    }

    //printf("svcaddr reserved (%s)\n", argc[1]);

    if (!rpcb_getaddr(progNum, VERSNUM, nconf,
                      &svcaddr, argc[1]))
    {
        fprintf(stderr, "rpcb_getaddr failed!!\n");
        printf("5\n");
        exit(1);
    }
    //printf("svc get\n");

    client = clnt_dg_create(RPC_ANYFD, &svcaddr,
                            progNum, VERSNUM, 1024, 1024);

    if (client == (CLIENT *)NULL)
    {
        clnt_pcreateerror("ERR");
        exit(1);
    }

    //Call tested procedure several times
    //Int test : call INTPROCNUM RPC
    intSnd = -65536;

    cs = clnt_call(client, INTPROCNUM,
                   (xdrproc_t)xdr_int, (char *)&intSnd,
                   (xdrproc_t)xdr_int, (char *)&intRec,
                   tv);

    if (intSnd != intRec)
        test_status = 1;
    if (run_mode == 1)
        printf("Send (int) : %d, Received : %d\n", intSnd, intRec);

    //Test positive number
    intSnd = 16777216;

    cs = clnt_call(client, INTPROCNUM,
                   (xdrproc_t)xdr_int, (char *)&intSnd,
                   (xdrproc_t)xdr_int, (char *)&intRec,
                   tv);

    if (intSnd != intRec)
        test_status = 1;
    if (run_mode == 1)
        printf("Send (int) : %d, Received : %d\n", intSnd, intRec);

    //Long test : call LNGPROCNUM RPC
    lngSnd = -430000;

    cs = clnt_call(client, LNGPROCNUM,
                   (xdrproc_t)xdr_long, (char *)&lngSnd,
                   (xdrproc_t)xdr_long, (char *)&lngRec,
                   tv);

    if (lngSnd != lngRec)
        test_status = 1;
    if (run_mode == 1)
        printf("Send (long) : %ld, Received : %ld\n", lngSnd, lngRec);

    //Double test : call DBLPROCNUM RPC
    dblSnd = -1735.63000f;

    cs = clnt_call(client, DBLPROCNUM,
                   (xdrproc_t)xdr_double, (char *)&dblSnd,
                   (xdrproc_t)xdr_double, (char *)&dblRec,
                   tv);

    if (dblSnd != dblRec)
        test_status = 1;
    if (run_mode == 1)
        printf("Send (double) : %lf, Received : %lf\n", dblSnd, dblRec);

    //String test : call STRPROCNUM RPC
    strSnd = "text to send.";
    strRec = (char *)malloc(64 * sizeof(char));

    cs = clnt_call(client, STRPROCNUM,
                   (xdrproc_t)xdr_wrapstring, (char *)&strSnd,
                   (xdrproc_t)xdr_wrapstring, (char *)&strRec,
                   tv);

    if (strcmp(strSnd, strRec))
        test_status = 1;
    if (run_mode == 1)
        printf("Send (string) : %s, Received : %s\n", strSnd, strRec);

    //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;
}
Пример #9
0
/* Create a channel for a new clientid (v4) or session, optionally
 * connecting it */
int nfs_rpc_create_chan_v40(nfs_client_id_t *pclientid,
                            uint32_t flags)
{
    struct netbuf raddr;
    int fd, proto, code = 0;
    rpc_call_channel_t *chan = &pclientid->cid_cb.cb_u.v40.cb_chan;



    assert(! chan->clnt);

    /* XXX we MUST error RFC 3530bis, sec. 3.3.3 */
    if (! supported_auth_flavor(pclientid->cid_credential.flavor)) {
        code = EINVAL;
        goto out;
    }

    chan->type = RPC_CHAN_V40;
    chan->nvu.v40.pclientid = pclientid;

    code = nfs_clid_connected_socket(pclientid, &fd, &proto);
    if (code) {
        LogWarn(COMPONENT_NFS_CB,
                 "Failed creating socket");
        goto out;
    }

    raddr.buf = &pclientid->cid_cb.cid_addr.ss;

    switch (proto) {
    case IPPROTO_TCP:
        raddr.maxlen = raddr.len = sizeof(struct sockaddr_in);
        chan->clnt = clnt_vc_create(fd,
                                    &raddr,
                                    pclientid->cid_cb.cid_program,
                                    1 /* Errata ID: 2291 */,
                                    0, 0);
        break;
    case IPPROTO_UDP:
        raddr.maxlen = raddr.len = sizeof(struct sockaddr_in6);
        chan->clnt = clnt_dg_create(fd,
                                    &raddr,
                                    pclientid->cid_cb.cid_program,
                                    1 /* Errata ID: 2291 */,
                                    0, 0);
        break;
    default:
        break;
    }

    if (! chan->clnt) {
        code = EINVAL;
        goto out;
    }

    /* channel protection */
    if (! nfs_rpc_callback_seccreate(chan)) {
        /* XXX */
        code = EINVAL;
    }

out:
    return (code);
}
Пример #10
0
static enum clnt_stat
clnt_reconnect_connect(CLIENT *cl)
{
	struct thread *td = curthread;
	struct rc_data *rc = (struct rc_data *)cl->cl_private;
	struct socket *so;
	enum clnt_stat stat;
	int error;
	int one = 1;
	struct ucred *oldcred;
	CLIENT *newclient = NULL;

	mtx_lock(&rc->rc_lock);
	while (rc->rc_connecting) {
		error = msleep(rc, &rc->rc_lock,
		    rc->rc_intr ? PCATCH : 0, "rpcrecon", 0);
		if (error) {
			mtx_unlock(&rc->rc_lock);
			return (RPC_INTR);
		}
	}
	if (rc->rc_closed) {
		mtx_unlock(&rc->rc_lock);
		return (RPC_CANTSEND);
	}
	if (rc->rc_client) {
		mtx_unlock(&rc->rc_lock);
		return (RPC_SUCCESS);
	}

	/*
	 * My turn to attempt a connect. The rc_connecting variable
	 * serializes the following code sequence, so it is guaranteed
	 * that rc_client will still be NULL after it is re-locked below,
	 * since that is the only place it is set non-NULL.
	 */
	rc->rc_connecting = TRUE;
	mtx_unlock(&rc->rc_lock);

	oldcred = td->td_ucred;
	td->td_ucred = rc->rc_ucred;
	so = __rpc_nconf2socket(rc->rc_nconf);
	if (!so) {
		stat = rpc_createerr.cf_stat = RPC_TLIERROR;
		rpc_createerr.cf_error.re_errno = 0;
		td->td_ucred = oldcred;
		goto out;
	}

	if (rc->rc_privport)
		bindresvport(so, NULL);

	if (rc->rc_nconf->nc_semantics == NC_TPI_CLTS)
		newclient = clnt_dg_create(so,
		    (struct sockaddr *) &rc->rc_addr, rc->rc_prog, rc->rc_vers,
		    rc->rc_sendsz, rc->rc_recvsz);
	else
		newclient = clnt_vc_create(so,
		    (struct sockaddr *) &rc->rc_addr, rc->rc_prog, rc->rc_vers,
		    rc->rc_sendsz, rc->rc_recvsz, rc->rc_intr);
	td->td_ucred = oldcred;

	if (!newclient) {
		soclose(so);
		rc->rc_err = rpc_createerr.cf_error;
		stat = rpc_createerr.cf_stat;
		goto out;
	}

	CLNT_CONTROL(newclient, CLSET_FD_CLOSE, 0);
	CLNT_CONTROL(newclient, CLSET_CONNECT, &one);
	CLNT_CONTROL(newclient, CLSET_TIMEOUT, &rc->rc_timeout);
	CLNT_CONTROL(newclient, CLSET_RETRY_TIMEOUT, &rc->rc_retry);
	CLNT_CONTROL(newclient, CLSET_WAITCHAN, rc->rc_waitchan);
	CLNT_CONTROL(newclient, CLSET_INTERRUPTIBLE, &rc->rc_intr);
	if (rc->rc_backchannel != NULL)
		CLNT_CONTROL(newclient, CLSET_BACKCHANNEL, rc->rc_backchannel);
	stat = RPC_SUCCESS;

out:
	mtx_lock(&rc->rc_lock);
	KASSERT(rc->rc_client == NULL, ("rc_client not null"));
	if (!rc->rc_closed) {
		rc->rc_client = newclient;
		newclient = NULL;
	}
	rc->rc_connecting = FALSE;
	wakeup(rc);
	mtx_unlock(&rc->rc_lock);

	if (newclient) {
		/*
		 * It has been closed, so discard the new client.
		 * nb: clnt_[dg|vc]_close()/clnt_[dg|vc]_destroy() cannot
		 * be called with the rc_lock mutex held, since they may
		 * msleep() while holding a different mutex.
		 */
		CLNT_CLOSE(newclient);
		CLNT_RELEASE(newclient);
	}

	return (stat);
}
Пример #11
0
/*
 * Create an rpc client attached to the mount daemon.
 */
CLIENT *
get_mount_client(char *host, struct sockaddr_in *unused_sin, struct timeval *tv, int *sock, u_long mnt_version)
{
  CLIENT *client;
  struct netbuf nb;
  struct netconfig *nc = NULL;
  struct sockaddr_in sin;

  nb.maxlen = sizeof(sin);
  nb.buf = (char *) &sin;

  /*
   * First try a TCP handler
   */

  /*
   * Find mountd address on TCP
   */
  if ((nc = getnetconfigent(NC_TCP)) == NULL) {
    plog(XLOG_ERROR, "getnetconfig for tcp failed: %s", nc_sperror());
    goto tryudp;
  }
  if (!rpcb_getaddr(MOUNTPROG, mnt_version, nc, &nb, host)) {
    /*
     * don't print error messages here, since mountd might legitimately
     * serve udp only
     */
    goto tryudp;
  }
  /*
   * Create privileged TCP socket
   */
  *sock = t_open(nc->nc_device, O_RDWR, 0);

  if (*sock < 0) {
    plog(XLOG_ERROR, "t_open %s: %m", nc->nc_device);
    goto tryudp;
  }
  if (bind_resv_port(*sock, (u_short *) 0) < 0)
    plog(XLOG_ERROR, "couldn't bind mountd socket to privileged port");

  if ((client = clnt_vc_create(*sock, &nb, MOUNTPROG, mnt_version, 0, 0))
      == (CLIENT *) NULL) {
    plog(XLOG_ERROR, "clnt_vc_create failed");
    t_close(*sock);
    goto tryudp;
  }
  /* tcp succeeded */
  dlog("get_mount_client: using tcp, port %d", sin.sin_port);
  if (nc)
    freenetconfigent(nc);
  return client;

tryudp:
  /* first free possibly previously allocated netconfig entry */
  if (nc)
    freenetconfigent(nc);

  /*
   * TCP failed so try UDP
   */

  /*
   * Find mountd address on UDP
   */
  if ((nc = getnetconfigent(NC_UDP)) == NULL) {
    plog(XLOG_ERROR, "getnetconfig for udp failed: %s", nc_sperror());
    goto badout;
  }
  if (!rpcb_getaddr(MOUNTPROG, mnt_version, nc, &nb, host)) {
    plog(XLOG_ERROR, "%s",
	 clnt_spcreateerror("couldn't get mountd address on udp"));
    goto badout;
  }
  /*
   * Create privileged UDP socket
   */
  *sock = t_open(nc->nc_device, O_RDWR, 0);

  if (*sock < 0) {
    plog(XLOG_ERROR, "t_open %s: %m", nc->nc_device);
    goto badout;		/* neither tcp not udp succeeded */
  }
  if (bind_resv_port(*sock, (u_short *) 0) < 0)
    plog(XLOG_ERROR, "couldn't bind mountd socket to privileged port");

  if ((client = clnt_dg_create(*sock, &nb, MOUNTPROG, mnt_version, 0, 0))
      == (CLIENT *) NULL) {
    plog(XLOG_ERROR, "clnt_dg_create failed");
    t_close(*sock);
    goto badout;		/* neither tcp not udp succeeded */
  }
  if (clnt_control(client, CLSET_RETRY_TIMEOUT, (char *) tv) == FALSE) {
    plog(XLOG_ERROR, "clnt_control CLSET_RETRY_TIMEOUT for udp failed");
    clnt_destroy(client);
    goto badout;		/* neither tcp not udp succeeded */
  }
  /* udp succeeded */
  dlog("get_mount_client: using udp, port %d", sin.sin_port);
  return client;

badout:
  /* failed */
  if (nc)
    freenetconfigent(nc);
  return NULL;
}