diff --git a/include/rpc/clnt.h b/include/rpc/clnt.h index f845e8e346b5..130369058db7 100644 --- a/include/rpc/clnt.h +++ b/include/rpc/clnt.h @@ -229,6 +229,7 @@ struct rpc_timers { #define CLSET_RETRY_TIMEOUT 4 /* set retry timeout (timeval) */ #define CLGET_RETRY_TIMEOUT 5 /* get retry timeout (timeval) */ #define CLSET_ASYNC 19 +#define CLSET_CONNECT 20 /* Use connect() for UDP. (int) */ /* * void diff --git a/lib/libc/rpc/clnt_dg.c b/lib/libc/rpc/clnt_dg.c index 2ab6f4a12999..e46c00800afd 100644 --- a/lib/libc/rpc/clnt_dg.c +++ b/lib/libc/rpc/clnt_dg.c @@ -126,6 +126,8 @@ struct cu_data { u_int cu_recvsz; /* recv size */ struct pollfd pfdp; int cu_async; + int cu_connect; /* Use connect(). */ + int cu_connected; /* Have done connect(). */ char cu_inbuf[1]; }; @@ -239,6 +241,8 @@ clnt_dg_create(fd, svcaddr, program, version, sendsz, recvsz) cu->cu_sendsz = sendsz; cu->cu_recvsz = recvsz; cu->cu_async = FALSE; + cu->cu_connect = FALSE; + cu->cu_connected = FALSE; (void) gettimeofday(&now, NULL); call_msg.rm_xid = __RPC_GETXID(&now); call_msg.rm_call.cb_prog = program; @@ -308,9 +312,10 @@ clnt_dg_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout) struct timeval startime, curtime; int firsttimeout = 1; int dtbsize = __rpc_dtbsize(); + struct sockaddr *sa; sigset_t mask; sigset_t newmask; - socklen_t inlen; + socklen_t inlen, salen; ssize_t recvlen = 0; int rpc_lock_value; u_int32_t xid; @@ -332,6 +337,22 @@ clnt_dg_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout) timeout = cu->cu_total; /* use default timeout */ } + if (cu->cu_connect && !cu->cu_connected) { + if (_connect(cu->cu_fd, (struct sockaddr *)&cu->cu_raddr, + cu->cu_rlen) < 0) { + release_fd_lock(cu->cu_fd, mask); + cu->cu_error.re_errno = errno; + return (cu->cu_error.re_status = RPC_CANTSEND); + } + cu->cu_connected = 1; + } + if (cu->cu_connected) { + sa = NULL; + salen = 0; + } else { + sa = (struct sockaddr *)&cu->cu_raddr; + salen = cu->cu_rlen; + } time_waited.tv_sec = 0; time_waited.tv_usec = 0; retransmit_time = cu->cu_wait; @@ -360,9 +381,7 @@ clnt_dg_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout) outlen = (size_t)XDR_GETPOS(xdrs); send_again: - if (_sendto(cu->cu_fd, cu->cu_outbuf, outlen, 0, - (struct sockaddr *)(void *)&cu->cu_raddr, (socklen_t)cu->cu_rlen) - != outlen) { + if (_sendto(cu->cu_fd, cu->cu_outbuf, outlen, 0, sa, salen) != outlen) { cu->cu_error.re_errno = errno; release_fd_lock(cu->cu_fd, mask); return (cu->cu_error.re_status = RPC_CANTSEND); @@ -738,6 +757,9 @@ clnt_dg_control(cl, request, info) case CLSET_ASYNC: cu->cu_async = *(int *)(void *)info; break; + case CLSET_CONNECT: + cu->cu_connect = *(int *)(void *)info; + break; default: release_fd_lock(cu->cu_fd, mask); return (FALSE); diff --git a/lib/libc/rpc/rpc_clnt_create.3 b/lib/libc/rpc/rpc_clnt_create.3 index 26b83a0f9946..b0f5ef0510bb 100644 --- a/lib/libc/rpc/rpc_clnt_create.3 +++ b/lib/libc/rpc/rpc_clnt_create.3 @@ -105,6 +105,7 @@ The following operations are valid for connectionless transports only: .Bl -column CLSET_RETRY_TIMEOUT "struct timeval *" "set total timeout" .It Dv CLSET_RETRY_TIMEOUT Ta "struct timeval *" Ta "set the retry timeout" .It Dv CLGET_RETRY_TIMEOUT Ta "struct timeval *" Ta "get the retry timeout" +.It Dv CLSET_CONNECT Ta Vt "int *" Ta use Xr connect 2 .El .Pp The retry timeout is the time that RPC