diff options
author | Nick Mathewson <nickm@torproject.org> | 2004-12-01 03:15:59 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2004-12-01 03:15:59 +0000 |
commit | 6e88abf418684ccaf4a1d7146b0129857a3864fe (patch) | |
tree | 40fe96c95f262f00fdf714759553f42eb45429eb | |
parent | bde1d5bfb2a6c1c39d51ff807e2d13ce6e8a30ce (diff) | |
download | tor-6e88abf418684ccaf4a1d7146b0129857a3864fe.tar tor-6e88abf418684ccaf4a1d7146b0129857a3864fe.tar.gz |
If we are using select, make sure we stay within FD_SETSIZE.
svn:r3051
-rw-r--r-- | src/common/compat.c | 13 | ||||
-rw-r--r-- | src/common/fakepoll.c | 6 | ||||
-rw-r--r-- | src/common/fakepoll.h | 25 | ||||
-rw-r--r-- | src/or/connection.c | 23 |
4 files changed, 58 insertions, 9 deletions
diff --git a/src/common/compat.c b/src/common/compat.c index 528f0beed..16e1bee4b 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -241,6 +241,11 @@ tor_socketpair(int family, int type, int protocol, int fd[2]) listener = socket(AF_INET, type, 0); if (listener == -1) return -1; + if (!SOCKET_IS_POLLABLE(listener)) { + log_fn(LOG_WARN, "Too many connections; can't open socketpair"); + tor_close_socket(listener); + return -1; + } memset(&listen_addr, 0, sizeof(listen_addr)); listen_addr.sin_family = AF_INET; listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); @@ -254,6 +259,10 @@ tor_socketpair(int family, int type, int protocol, int fd[2]) connector = socket(AF_INET, type, 0); if (connector == -1) goto tidy_up_and_fail; + if (!SOCKET_IS_POLLABLE(connector)) { + log_fn(LOG_WARN, "Too many connections; can't open socketpair"); + goto tidy_up_and_fail; + } /* We want to find out the port number to connect to. */ size = sizeof(connect_addr); if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1) @@ -268,6 +277,10 @@ tor_socketpair(int family, int type, int protocol, int fd[2]) acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size); if (acceptor == -1) goto tidy_up_and_fail; + if (!SOCKET_IS_POLLABLE(acceptor)) { + log_fn(LOG_WARN, "Too many connections; can't open socketpair"); + goto tidy_up_and_fail; + } if (size != sizeof(listen_addr)) goto abort_tidy_up_and_fail; tor_close_socket(listener); diff --git a/src/common/fakepoll.c b/src/common/fakepoll.c index 712f2bd36..02be8c9d8 100644 --- a/src/common/fakepoll.c +++ b/src/common/fakepoll.c @@ -12,9 +12,6 @@ const char fakepoll_c_id[] = "$Id$"; #include "orconfig.h" #include "fakepoll.h" -#define MAXCONNECTIONS 10000 /* XXXX copied from or.h */ -#define FD_SETSIZE MAXCONNECTIONS - #ifdef HAVE_SYS_TYPES_H #include <sys/types.h> #endif @@ -44,7 +41,6 @@ tor_poll(struct pollfd *ufds, unsigned int nfds, int timeout) return poll(ufds,nfds,timeout); } #else - int tor_poll(struct pollfd *ufds, unsigned int nfds, int timeout) { @@ -71,7 +67,7 @@ tor_poll(struct pollfd *ufds, unsigned int nfds, int timeout) for (idx = 0; idx < nfds; ++idx) { ufds[idx].revents = 0; fd = ufds[idx].fd; - tor_assert(fd >= 0); + tor_assert(SOCKET_SEEMS_POLLABLE(fd)); if (fd > maxfd) { maxfd = fd; #ifdef MS_WINDOWS diff --git a/src/common/fakepoll.h b/src/common/fakepoll.h index 44fc63d85..3f3d1610b 100644 --- a/src/common/fakepoll.h +++ b/src/common/fakepoll.h @@ -44,7 +44,30 @@ struct pollfd { #define POLLNVAL 0x0020 #endif -int tor_poll(struct pollfd *ufds, unsigned int nfds, int timeout); +#ifdef MS_WINDOWS +#define MAXCONNECTIONS 10000 /* XXXX copied from or.h */ +/* This trick makes winsock resize fd_set, which defaults to the insanely low + * 64. */ +#define FD_SETSIZE MAXCONNECTIONS +/* XXXX But Windows FD_SET and FD_CLR are tremendously ugly, and linear in + * the total number of sockets set! Perhaps we should eventually use + * WSAEventSelect and WSAWaitForMultipleEvents instead of select? */ +#endif +#if defined(MS_WINDOWS) || ! defined(USE_FAKE_POLL) +/* If we're using poll, we can poll as many sockets as we want. + * If we're on Windows, having too many sockets is harmless, since + * select stupidly uses an array of sockets rather than a bitfield. */ +#define SOCKET_IS_POLLABLE(fd) ((fd) >= 0) +#else +/* If we're using a real Posix select, then in order to be pollable, a socket + * must + * a) be valid (>= 0) + * b) be < FD_SETSIZE. + */ +#define SOCKET_IS_POLLABLE(fd) ((fd) >= 0 && (fd) < FD_SETSIZE) #endif +int tor_poll(struct pollfd *ufds, unsigned int nfds, int timeout); + +#endif diff --git a/src/or/connection.c b/src/or/connection.c index ab5197cf2..fb7efdc24 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -363,6 +363,10 @@ static int connection_create_listener(const char *bindaddress, uint16_t bindport if (s < 0) { log_fn(LOG_WARN,"Socket creation failed."); return -1; + } else if (!SOCKET_IS_POLLABLE(s)) { + log_fn(LOG_WARN,"Too many connections; can't create pollable listener."); + tor_close_socket(s); + return -1; } setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*) &one, sizeof(one)); @@ -410,8 +414,16 @@ static int connection_handle_listener_read(connection_t *conn, int new_type) { int remotelen = sizeof(struct sockaddr_in); news = accept(conn->s,(struct sockaddr *)&remote,&remotelen); - if (news == -1) { /* accept() error */ - int e = tor_socket_errno(conn->s); + if (!SOCKET_IS_POLLABLE(news)) { + /* accept() error, or two many conns to poll */ + int e; + if (news>=0) { + /* Too many conns to poll. */ + log_fn(LOG_WARN,"Too many connections; couldn't accept connection."); + tor_close_socket(news); + return 0; + } + e = tor_socket_errno(conn->s); if (ERRNO_IS_ACCEPT_EAGAIN(e)) { return 0; /* he hung up before we could accept(). that's fine. */ } else if (ERRNO_IS_ACCEPT_RESOURCE_LIMIT(e)) { @@ -505,11 +517,16 @@ int connection_connect(connection_t *conn, char *address, uint32_t addr, uint16_ struct sockaddr_in dest_addr; or_options_t *options = get_options(); - s=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); + s = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); if (s < 0) { log_fn(LOG_WARN,"Error creating network socket: %s", tor_socket_strerror(tor_socket_errno(-1))); return -1; + } else if (!SOCKET_IS_POLLABLE(s)) { + log_fn(LOG_WARN, + "Too many connections; can't create pollable connection to %s", address); + tor_close_socket(s); + return -1; } if (options->OutboundBindAddress) { |