Add a new clnt_control() request `CLSET_CONNECT' that controls

whether or not connect(2) is used for UDP client sockets. The default
is not to connect(), so existing clients will see no change in
behaviour.

The use of connect(2) for UDP clients has a number of advantages:
only replies from the intended address are received, and ICMP errors
pertaining to the connection are reported back to the application.
This commit is contained in:
Ian Dowse 2001-06-23 19:43:21 +00:00
parent 1d57ebcdbf
commit 32de72d27f
3 changed files with 28 additions and 4 deletions

View File

@ -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

View File

@ -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);

View File

@ -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