summaryrefslogtreecommitdiffstats
path: root/lib/libc
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2001-06-23 19:43:21 +0000
committeriedowse <iedowse@FreeBSD.org>2001-06-23 19:43:21 +0000
commitdd53c9014eb416417cb746063d7cd8385096ce35 (patch)
tree99ec7e9456e1c6a6ad70863104b49dce3c96cf1c /lib/libc
parent0235c0e8cbac19c911822f6ca12627292b50c4ff (diff)
downloadFreeBSD-src-dd53c9014eb416417cb746063d7cd8385096ce35.zip
FreeBSD-src-dd53c9014eb416417cb746063d7cd8385096ce35.tar.gz
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.
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/rpc/clnt_dg.c30
-rw-r--r--lib/libc/rpc/rpc_clnt_create.31
2 files changed, 27 insertions, 4 deletions
diff --git a/lib/libc/rpc/clnt_dg.c b/lib/libc/rpc/clnt_dg.c
index 2ab6f4a..e46c008 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 @@ call_again:
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 26b83a0..b0f5ef0 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
OpenPOWER on IntegriCloud