- prototype now in include file, plus no longer needed anyway

- fix timeout code
- better sequence number generation (for long running daemons)
- dont close an unopen socket
- use standard functions
- 64 bit type safe for wire protocols
- unlimited file descriptors

Obtained from: a diff of FreeBSD vs. OpenBSD/NetBSD rpc code.
This commit is contained in:
Peter Wemm 1996-12-30 14:53:20 +00:00
parent fadfbc36c6
commit b93e2c954d

View File

@ -30,7 +30,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)pmap_rmt.c 2.2 88/08/01 4.0 RPCSRC";*/
static char *rcsid = "$Id: pmap_rmt.c,v 1.7 1996/06/10 04:59:05 wpaul Exp $";
static char *rcsid = "$Id: pmap_rmt.c,v 1.8 1996/08/12 14:00:23 peter Exp $";
#endif
/*
@ -47,6 +47,7 @@ static char *rcsid = "$Id: pmap_rmt.c,v 1.7 1996/06/10 04:59:05 wpaul Exp $";
#include <rpc/pmap_rmt.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
@ -57,8 +58,6 @@ static char *rcsid = "$Id: pmap_rmt.c,v 1.7 1996/06/10 04:59:05 wpaul Exp $";
static struct timeval timeout = { 3, 0 };
int _rpc_dtablesize(void);
/*
* pmapper remote-call-service interface.
* This routine is used to call the pmapper remote call service
@ -98,7 +97,8 @@ pmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, port_pt
} else {
stat = RPC_FAILED;
}
(void)close(socket);
if (socket != -1)
(void)close(socket);
addr->sin_port = 0;
return (stat);
}
@ -169,11 +169,11 @@ getbroadcastnets(addrs, sock, buf)
char *buf; /* why allocxate more when we can use existing... */
{
struct ifconf ifc;
struct ifreq ifreq, *ifr;
struct ifreq ifreq, *ifr;
struct sockaddr_in *sin;
struct in_addr addr;
char *cp, *cplim;
int n, i = 0;
char *cp, *cplim;
int n, i = 0;
ifc.ifc_len = UDPMSGSIZE;
ifc.ifc_buf = buf;
@ -242,13 +242,7 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
int outlen, inlen, fromlen, nets;
register int sock;
int on = 1;
#ifdef FD_SETSIZE
fd_set mask;
fd_set readfds;
#else
int readfds;
register int mask;
#endif /* def FD_SETSIZE */
fd_set *fds, readfds;
register int i;
bool_t done = FALSE;
register u_long xid;
@ -258,8 +252,12 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
struct rmtcallargs a;
struct rmtcallres r;
struct rpc_msg msg;
struct timeval t;
struct timeval t, tv;
char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE];
static u_int32_t disrupt;
if (disrupt == 0)
disrupt = (u_int32_t)(long)resultsp;
/*
* initialization: create a socket, a broadcast address, and
@ -277,21 +275,27 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
goto done_broad;
}
#endif /* def SO_BROADCAST */
#ifdef FD_SETSIZE
FD_ZERO(&mask);
FD_SET(sock, &mask);
#else
mask = (1 << sock);
#endif /* def FD_SETSIZE */
if (sock + 1 > FD_SETSIZE) {
int bytes = howmany(sock + 1, NFDBITS) * sizeof(fd_mask);
fds = (fd_set *)malloc(bytes);
if (fds == NULL) {
stat = RPC_CANTSEND;
goto done_broad;
}
memset(fds, 0, bytes);
} else {
fds = &readfds;
FD_ZERO(fds);
}
nets = getbroadcastnets(addrs, sock, inbuf);
bzero((char *)&baddr, sizeof (baddr));
memset(&baddr, 0, sizeof (baddr));
baddr.sin_len = sizeof(struct sockaddr_in);
baddr.sin_family = AF_INET;
baddr.sin_port = htons(PMAPPORT);
baddr.sin_addr.s_addr = htonl(INADDR_ANY);
/* baddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); */
(void)gettimeofday(&t, (struct timezone *)0);
msg.rm_xid = xid = getpid() ^ t.tv_sec ^ t.tv_usec;
msg.rm_xid = xid = (++disrupt) ^ getpid() ^ t.tv_sec ^ t.tv_usec;
t.tv_usec = 0;
msg.rm_direction = CALL;
msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
@ -318,6 +322,12 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
/*
* Basic loop: broadcast a packet and wait a while for response(s).
* The response timeout grows larger per iteration.
*
* XXX This will loop about 5 times the stop. If there are
* lots of signals being received by the process it will quit
* send them all in one quick burst, not paying attention to
* the intended function of sending them slowly over half a
* minute or so
*/
for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2) {
for (i = 0; i < nets; i++) {
@ -337,10 +347,11 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
recv_again:
msg.acpted_rply.ar_verf = _null_auth;
msg.acpted_rply.ar_results.where = (caddr_t)&r;
msg.acpted_rply.ar_results.proc = xdr_rmtcallres;
readfds = mask;
switch (select(_rpc_dtablesize(), &readfds, (fd_set *)NULL,
(fd_set *)NULL, &t)) {
msg.acpted_rply.ar_results.proc = xdr_rmtcallres;
/* XXX we know the other bits are still clear */
FD_SET(sock, fds);
tv = t; /* for select() that copies back */
switch (select(sock + 1, fds, NULL, NULL, &tv)) {
case 0: /* timed out */
stat = RPC_TIMEDOUT;
@ -365,7 +376,7 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
stat = RPC_CANTRECV;
goto done_broad;
}
if (inlen < sizeof(u_long))
if (inlen < sizeof(u_int32_t))
goto recv_again;
/*
* see if reply transaction id matches sent id.
@ -380,13 +391,6 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
done = (*eachresult)(resultsp, &raddr);
}
/* otherwise, we just ignore the errors ... */
} else {
#ifdef notdef
/* some kind of deserialization problem ... */
if (msg.rm_xid == xid)
fprintf(stderr, "Broadcast deserialization problem");
/* otherwise, just random garbage */
#endif
}
xdrs->x_op = XDR_FREE;
msg.acpted_rply.ar_results.proc = xdr_void;
@ -401,7 +405,10 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
}
}
done_broad:
(void)close(sock);
if (fds != &readfds)
free(fds);
if (sock >= 0)
(void)close(sock);
AUTH_DESTROY(unix_auth);
return (stat);
}