summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorCamiel Dobbelaar <camield@cvs.openbsd.org>2012-04-05 19:08:41 +0000
committerCamiel Dobbelaar <camield@cvs.openbsd.org>2012-04-05 19:08:41 +0000
commit3e8899e9ae184d1808ca24e1856315f3f0bf1642 (patch)
treed605e29214bbe3257d7dc585c10ed480e29c5026 /usr.sbin
parent4acbe6a0ba21ec14fc42aba7435591ae7a420607 (diff)
Rate-limit accepting of new connections while we are experiencing
fd exhaustion. ok deraadt mikeb
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/ftp-proxy/ftp-proxy.c31
1 files changed, 25 insertions, 6 deletions
diff --git a/usr.sbin/ftp-proxy/ftp-proxy.c b/usr.sbin/ftp-proxy/ftp-proxy.c
index 5a0dbb9f5af..0facc4de434 100644
--- a/usr.sbin/ftp-proxy/ftp-proxy.c
+++ b/usr.sbin/ftp-proxy/ftp-proxy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ftp-proxy.c,v 1.24 2012/03/04 04:05:15 fgsch Exp $ */
+/* $OpenBSD: ftp-proxy.c,v 1.25 2012/04/05 19:08:40 camield Exp $ */
/*
* Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl>
@@ -113,6 +113,7 @@ size_t linelen;
char ntop_buf[NTOP_BUFS][INET6_ADDRSTRLEN];
+struct event listen_ev, pause_accept_ev;
struct sockaddr_storage fixed_server_ss, fixed_proxy_ss;
char *fixed_server, *fixed_server_port, *fixed_proxy, *listen_ip, *listen_port,
*qname, *tagname;
@@ -370,7 +371,7 @@ get_line(char *buf, size_t *valid)
}
void
-handle_connection(const int listen_fd, short event, void *ev)
+handle_connection(const int listen_fd, short event, void *arg)
{
struct sockaddr_storage tmp_ss;
struct sockaddr *client_sa, *server_sa, *fixed_server_sa;
@@ -379,6 +380,12 @@ handle_connection(const int listen_fd, short event, void *ev)
socklen_t len;
int client_fd, fc, on;
+ event_add(&listen_ev, NULL);
+
+ if ((event & EV_TIMEOUT))
+ /* accept() is no longer paused. */
+ return;
+
/*
* We _must_ accept the connection, otherwise libevent will keep
* coming back, and we will chew up all CPU.
@@ -386,7 +393,18 @@ handle_connection(const int listen_fd, short event, void *ev)
client_sa = sstosa(&tmp_ss);
len = sizeof(struct sockaddr_storage);
if ((client_fd = accept(listen_fd, client_sa, &len)) < 0) {
- logmsg(LOG_CRIT, "accept failed: %s", strerror(errno));
+ logmsg(LOG_CRIT, "accept() failed: %s", strerror(errno));
+
+ /*
+ * Pause accept if we are out of file descriptors, or
+ * libevent will haunt us here too.
+ */
+ if (errno == ENFILE || errno == EMFILE) {
+ struct timeval pause = { 1, 0 };
+
+ event_del(&listen_ev);
+ evtimer_add(&pause_accept_ev, &pause);
+ }
return;
}
@@ -589,7 +607,7 @@ main(int argc, char *argv[])
{
struct rlimit rlp;
struct addrinfo hints, *res;
- struct event ev, ev_sighup, ev_sigint, ev_sigterm;
+ struct event ev_sighup, ev_sigint, ev_sigterm;
int ch, error, listenfd, on;
const char *errstr;
@@ -770,8 +788,9 @@ main(int argc, char *argv[])
signal_add(&ev_sigint, NULL);
signal_add(&ev_sigterm, NULL);
- event_set(&ev, listenfd, EV_READ | EV_PERSIST, handle_connection, &ev);
- event_add(&ev, NULL);
+ event_set(&listen_ev, listenfd, EV_READ, handle_connection, NULL);
+ event_add(&listen_ev, NULL);
+ evtimer_set(&pause_accept_ev, handle_connection, NULL);
logmsg(LOG_NOTICE, "listening on %s port %s", listen_ip, listen_port);