summaryrefslogtreecommitdiffstats
path: root/lib/libc/rpc/clnt_udp.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1996-12-30 14:40:34 +0000
committerpeter <peter@FreeBSD.org>1996-12-30 14:40:34 +0000
commitacdf726df9abb53422e33ee79f99d1a84e9286c4 (patch)
tree52842eb7fc9cc02bedb2e99e43c5a41db9998919 /lib/libc/rpc/clnt_udp.c
parentef8a9f54798ab23b9ada182eac485647314183ca (diff)
downloadFreeBSD-src-acdf726df9abb53422e33ee79f99d1a84e9286c4.zip
FreeBSD-src-acdf726df9abb53422e33ee79f99d1a84e9286c4.tar.gz
- prototypes now in include file
- fix timeout code - better "random" initial transaction id for long running daemons - unlimited number of file descriptors to select(). - 64 bit type safe wire protocol Obtained from: a diff of FreeBSD vs. OpenBSD/NetBSD rpc code. - typo (spelling police :-) - dont die on select() that returns time remaining (on my systems)
Diffstat (limited to 'lib/libc/rpc/clnt_udp.c')
-rw-r--r--lib/libc/rpc/clnt_udp.c113
1 files changed, 64 insertions, 49 deletions
diff --git a/lib/libc/rpc/clnt_udp.c b/lib/libc/rpc/clnt_udp.c
index 28dfddc..2e45f63 100644
--- a/lib/libc/rpc/clnt_udp.c
+++ b/lib/libc/rpc/clnt_udp.c
@@ -30,7 +30,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)clnt_udp.c 2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$Id: clnt_udp.c,v 1.6 1995/12/07 12:50:54 bde Exp $";
+static char *rcsid = "$Id: clnt_udp.c,v 1.7 1996/06/10 00:49:16 jraynard Exp $";
#endif
/*
@@ -50,10 +50,6 @@ static char *rcsid = "$Id: clnt_udp.c,v 1.6 1995/12/07 12:50:54 bde Exp $";
#include <errno.h>
#include <rpc/pmap_clnt.h>
-int bindresvport(int sd, struct sockaddr_in *);
-int _rpc_dtablesize(void);
-bool_t xdr_opaque_auth(XDR *, struct opaque_auth *);
-
/*
* UDP bases client side rpc operations
*/
@@ -122,6 +118,10 @@ clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
register struct cu_data *cu = NULL;
struct timeval now;
struct rpc_msg call_msg;
+ static u_int32_t disrupt;
+
+ if (disrupt == 0)
+ disrupt = (u_int32_t)(long)raddr;
cl = (CLIENT *)mem_alloc(sizeof(CLIENT));
if (cl == NULL) {
@@ -159,7 +159,7 @@ clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
cu->cu_total.tv_usec = -1;
cu->cu_sendsz = sendsz;
cu->cu_recvsz = recvsz;
- call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
+ call_msg.rm_xid = (++disrupt) ^ getpid() ^ now.tv_sec ^ now.tv_usec;
call_msg.rm_direction = CALL;
call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
call_msg.rm_call.cb_prog = program;
@@ -179,7 +179,7 @@ clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
rpc_createerr.cf_error.re_errno = errno;
goto fooy;
}
- /* attempt to bind to prov port */
+ /* attempt to bind to priv port */
(void)bindresvport(*sockp, (struct sockaddr_in *)0);
/* the sockets rpc controls are non-blocking */
(void)ioctl(*sockp, FIONBIO, (char *) &dontblock);
@@ -226,29 +226,33 @@ clntudp_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
register int outlen;
register int inlen;
int fromlen;
-#ifdef FD_SETSIZE
- fd_set readfds;
- fd_set mask;
-#else
- int readfds;
- register int mask;
-#endif /* def FD_SETSIZE */
+ fd_set *fds, readfds;
struct sockaddr_in from;
struct rpc_msg reply_msg;
XDR reply_xdrs;
- struct timeval time_waited;
+ struct timeval time_waited, start, after, tmp1, tmp2, tv;
bool_t ok;
int nrefreshes = 2; /* number of times to refresh cred */
struct timeval timeout;
- if (cu->cu_total.tv_usec == -1) {
+ if (cu->cu_total.tv_usec == -1)
timeout = utimeout; /* use supplied timeout */
- } else {
+ else
timeout = cu->cu_total; /* use default timeout */
+
+ if (cu->cu_sock + 1 > FD_SETSIZE) {
+ int bytes = howmany(cu->cu_sock + 1, NFDBITS) * sizeof(fd_mask);
+ fds = (fd_set *)malloc(bytes);
+ if (fds == NULL)
+ return (cu->cu_error.re_status = RPC_CANTSEND);
+ memset(fds, 0, bytes);
+ } else {
+ fds = &readfds;
+ FD_ZERO(fds);
}
- time_waited.tv_sec = 0;
- time_waited.tv_usec = 0;
+ timerclear(&time_waited);
+
call_again:
xdrs = &(cu->cu_outxdrs);
xdrs->x_op = XDR_ENCODE;
@@ -259,22 +263,28 @@ call_again:
(*(u_short *)(cu->cu_outbuf))++;
if ((! XDR_PUTLONG(xdrs, (long *)&proc)) ||
(! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
- (! (*xargs)(xdrs, argsp)))
+ (! (*xargs)(xdrs, argsp))) {
+ if (fds != &readfds)
+ free(fds);
return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
+ }
outlen = (int)XDR_GETPOS(xdrs);
send_again:
if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0,
- (struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen)
- != outlen) {
+ (struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen) != outlen) {
cu->cu_error.re_errno = errno;
+ if (fds != &readfds)
+ free(fds);
return (cu->cu_error.re_status = RPC_CANTSEND);
}
/*
* Hack to provide rpc-based message passing
*/
- if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
+ if (!timerisset(&timeout)) {
+ if (fds != &readfds)
+ free(fds);
return (cu->cu_error.re_status = RPC_TIMEDOUT);
}
/*
@@ -285,40 +295,41 @@ send_again:
reply_msg.acpted_rply.ar_verf = _null_auth;
reply_msg.acpted_rply.ar_results.where = resultsp;
reply_msg.acpted_rply.ar_results.proc = xresults;
-#ifdef FD_SETSIZE
- FD_ZERO(&mask);
- FD_SET(cu->cu_sock, &mask);
-#else
- mask = 1 << cu->cu_sock;
-#endif /* def FD_SETSIZE */
+
+ gettimeofday(&start, NULL);
for (;;) {
- readfds = mask;
- switch (select(_rpc_dtablesize(), &readfds, (fd_set *)NULL,
- (fd_set *)NULL, &(cu->cu_wait))) {
+ /* XXX we know the other bits are still clear */
+ FD_SET(cu->cu_sock, fds);
+ tv = cu->cu_wait;
+ switch (select(cu->cu_sock+1, fds, NULL, NULL, &tv)) {
case 0:
- time_waited.tv_sec += cu->cu_wait.tv_sec;
- time_waited.tv_usec += cu->cu_wait.tv_usec;
- while (time_waited.tv_usec >= 1000000) {
- time_waited.tv_sec++;
- time_waited.tv_usec -= 1000000;
- }
- if ((time_waited.tv_sec < timeout.tv_sec) ||
- ((time_waited.tv_sec == timeout.tv_sec) &&
- (time_waited.tv_usec < timeout.tv_usec)))
+ timeradd(&time_waited, &cu->cu_wait, &tmp1);
+ time_waited = tmp1;
+ if (timercmp(&time_waited, &timeout, <))
goto send_again;
+ if (fds != &readfds)
+ free(fds);
return (cu->cu_error.re_status = RPC_TIMEDOUT);
- /*
- * buggy in other cases because time_waited is not being
- * updated.
- */
case -1:
- if (errno == EINTR)
- continue;
+ if (errno == EINTR) {
+ gettimeofday(&after, NULL);
+ timersub(&after, &start, &tmp1);
+ timeradd(&time_waited, &tmp1, &tmp2);
+ time_waited = tmp2;
+ if (timercmp(&time_waited, &timeout, <))
+ continue;
+ if (fds != &readfds)
+ free(fds);
+ return (cu->cu_error.re_status = RPC_TIMEDOUT);
+ }
cu->cu_error.re_errno = errno;
+ if (fds != &readfds)
+ free(fds);
return (cu->cu_error.re_status = RPC_CANTRECV);
}
+
do {
fromlen = sizeof(struct sockaddr);
inlen = recvfrom(cu->cu_sock, cu->cu_inbuf,
@@ -329,12 +340,14 @@ send_again:
if (errno == EWOULDBLOCK)
continue;
cu->cu_error.re_errno = errno;
+ if (fds != &readfds)
+ free(fds);
return (cu->cu_error.re_status = RPC_CANTRECV);
}
- if (inlen < sizeof(u_long))
+ if (inlen < sizeof(u_int32_t))
continue;
/* see if reply transaction id matches sent id */
- if (*((u_long *)(cu->cu_inbuf)) != *((u_long *)(cu->cu_outbuf)))
+ if (*((u_int32_t *)(cu->cu_inbuf)) != *((u_int32_t *)(cu->cu_outbuf)))
continue;
/* we now assume we have the proper reply */
break;
@@ -371,6 +384,8 @@ send_again:
else {
cu->cu_error.re_status = RPC_CANTDECODERES;
}
+ if (fds != &readfds)
+ free(fds);
return (cu->cu_error.re_status);
}
OpenPOWER on IntegriCloud