diff options
Diffstat (limited to 'lib/libc/rpc/svc_tcp.c')
| -rw-r--r-- | lib/libc/rpc/svc_tcp.c | 97 |
1 files changed, 62 insertions, 35 deletions
diff --git a/lib/libc/rpc/svc_tcp.c b/lib/libc/rpc/svc_tcp.c index 9d19504858fb..1387ee126620 100644 --- a/lib/libc/rpc/svc_tcp.c +++ b/lib/libc/rpc/svc_tcp.c @@ -5,23 +5,23 @@ * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. - * + * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * + * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. - * + * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. - * + * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. - * + * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 @@ -30,11 +30,11 @@ #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.1 1993/10/27 05:41:02 paul Exp $"; +static char *rcsid = "$Id: svc_tcp.c,v 1.8 1996/12/30 15:19:08 peter Exp $"; #endif /* - * svc_tcp.c, Server side for TCP/IP based RPC. + * svc_tcp.c, Server side for TCP/IP based RPC. * * Copyright (C) 1984, Sun Microsystems, Inc. * @@ -44,11 +44,12 @@ static char *rcsid = "$Id: svc_tcp.c,v 1.1 1993/10/27 05:41:02 paul Exp $"; */ #include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> #include <rpc/rpc.h> #include <sys/socket.h> #include <errno.h> -extern bool_t abort(); -extern errno; /* * Ops vector for TCP/IP based rpc service handle @@ -78,9 +79,9 @@ static enum xprt_stat rendezvous_stat(); static struct xp_ops svctcp_rendezvous_op = { rendezvous_request, rendezvous_stat, - abort, - abort, - abort, + (bool_t (*)())abort, + (bool_t (*)())abort, + (bool_t (*)())abort, svctcp_destroy }; @@ -138,7 +139,8 @@ 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)) { addr.sin_port = 0; @@ -195,7 +197,7 @@ makefd_xprt(fd, sendsize, recvsize) { register SVCXPRT *xprt; register struct tcp_conn *cd; - + xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT)); if (xprt == (SVCXPRT *)NULL) { (void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n"); @@ -242,6 +244,14 @@ rendezvous_request(xprt) 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) */ xprt = makefd_xprt(sock, r->sendsize, r->recvsize); @@ -294,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; - - FD_ZERO(&mask); - FD_SET(sock, &mask); -#else - register int mask = 1 << sock; - int readfds; -#endif /* def FD_SETSIZE */ + struct timeval start, delta, tv; + struct timeval tmp1, tmp2; + fd_set *fds, readfds; + + 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, (int*)NULL, (int*)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); } |
