- prototypes now in include file

- overhaul for unlimited fd's
- OpenBSD's ftp port bounce attack fix
- fix timeouts

Obtained from: a diff of FreeBSD vs. OpenBSD/NetBSD rpc code.
This commit is contained in:
Peter Wemm 1996-12-30 15:19:08 +00:00
parent 75a98e21b1
commit 9ff75e1aac
1 changed files with 47 additions and 25 deletions

View File

@ -30,7 +30,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC";*/
static char *rcsid = "$Id: svc_tcp.c,v 1.6 1996/06/10 20:13:09 jraynard Exp $";
static char *rcsid = "$Id: svc_tcp.c,v 1.7 1996/08/12 14:00:25 peter Exp $";
#endif
/*
@ -51,9 +51,6 @@ static char *rcsid = "$Id: svc_tcp.c,v 1.6 1996/06/10 20:13:09 jraynard Exp $";
#include <sys/socket.h>
#include <errno.h>
int bindresvport(int sd, struct sockaddr_in *);
int _rpc_dtablesize(void);
/*
* Ops vector for TCP/IP based rpc service handle
*/
@ -142,7 +139,7 @@ svctcp_create(sock, sendsize, recvsize)
}
madesock = TRUE;
}
bzero((char *)&addr, sizeof (addr));
memset(&addr, 0, sizeof (addr));
addr.sin_len = sizeof(struct sockaddr_in);
addr.sin_family = AF_INET;
if (bindresvport(sock, &addr)) {
@ -246,6 +243,14 @@ rendezvous_request(xprt)
goto again;
return (FALSE);
}
/*
* XXX careful for ftp bounce attacks. If discovered, close the
* socket and look for another connection.
*/
if (addr.sin_port == htons(20)) {
close(sock);
goto again;
}
/*
* make a new transporter (re-uses xprt)
*/
@ -299,35 +304,52 @@ readtcp(xprt, buf, len)
register int len;
{
register int sock = xprt->xp_sock;
#ifdef FD_SETSIZE
fd_set mask;
fd_set readfds;
struct timeval start, delta, tv;
struct timeval tmp1, tmp2;
fd_set *fds, readfds;
FD_ZERO(&mask);
FD_SET(sock, &mask);
#else
register int mask = 1 << sock;
int readfds;
#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)
goto fatal_err;
memset(fds, 0, bytes);
} else {
fds = &readfds;
FD_ZERO(fds);
}
delta = wait_per_try;
gettimeofday(&start, NULL);
do {
readfds = mask;
if (select(_rpc_dtablesize(), &readfds, (fd_set *)NULL,
(fd_set *)NULL, &wait_per_try) <= 0) {
if (errno == EINTR) {
continue;
}
/* XXX we know the other bits are still clear */
FD_SET(sock, fds);
tv = delta; /* in case select() implements writeback */
switch (select(sock + 1, fds, NULL, NULL, &tv)) {
case -1:
if (errno != EINTR)
goto fatal_err;
gettimeofday(&tmp1, NULL);
timersub(&tmp1, &start, &tmp2);
timersub(&delta, &tmp2, &tmp1);
if (tmp1.tv_sec < 0 || !timerisset(&tmp1))
goto fatal_err;
delta = tmp1;
continue;
case 0:
goto fatal_err;
}
#ifdef FD_SETSIZE
} while (!FD_ISSET(sock, &readfds));
#else
} while (readfds != mask);
#endif /* def FD_SETSIZE */
} while (!FD_ISSET(sock, fds));
if ((len = read(sock, buf, len)) > 0) {
if (fds != &readfds)
free(fds);
return (len);
}
fatal_err:
((struct tcp_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
if (fds != &readfds)
free(fds);
return (-1);
}