From dd53c9014eb416417cb746063d7cd8385096ce35 Mon Sep 17 00:00:00 2001 From: iedowse Date: Sat, 23 Jun 2001 19:43:21 +0000 Subject: 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. --- include/rpc/clnt.h | 1 + lib/libc/rpc/clnt_dg.c | 30 ++++++++++++++++++++++++++---- lib/libc/rpc/rpc_clnt_create.3 | 1 + 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/include/rpc/clnt.h b/include/rpc/clnt.h index f845e8e..1303690 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 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 -- cgit v1.1