aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToni Uhlig <matzeton@googlemail.com>2018-05-30 12:13:16 +0200
committerToni Uhlig <matzeton@googlemail.com>2018-05-30 12:13:16 +0200
commit0dc05d5eaf474c30bcb71f77a2c34f521452c0b5 (patch)
tree24033124bd2b4ea13a9bbf24b7a264f8f6ce0372
parentd5ea8f4ae6db7a198fdd139417c08b346b8834b5 (diff)
POTD skeleton #82.
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r--configure.ac38
-rw-r--r--src/redirector.c23
2 files changed, 57 insertions, 4 deletions
diff --git a/configure.ac b/configure.ac
index 5edde66..34bd487 100644
--- a/configure.ac
+++ b/configure.ac
@@ -62,16 +62,47 @@ AC_SUBST([valgrind_CFLAGS])
AC_SUBST([valgrind_LIBS])
dnl Check for std header files
-AC_CHECK_HEADERS([stdio.h ctype.h assert.h sched.h signal.h errno.h pwd.h])
+AC_CHECK_HEADERS([stdio.h ctype.h assert.h sched.h signal.h time.h errno.h pwd.h], [],
+ [ AC_MSG_ERROR([required std header not available]) ])
dnl Check for system specific header files
-AC_CHECK_HEADERS([pty.h linux/capability.h sys/wait.h])
+AC_CHECK_HEADERS([pty.h linux/capability.h sys/wait.h], [],
+ [ AC_MSG_ERROR([required system specific header not available]) ])
AC_CHECK_HEADERS([libutil.h pthread.h syslog.h sys/prctl.h linux/limits.h \
sys/uio.h poll.h sys/epoll.h sys/sysmacros.h sys/mount.h util.h])
dnl Check for GAI header
AC_CHECK_HEADERS([netdb.h])
+AC_MSG_CHECKING([working time])
+AC_COMPILE_IFELSE([
+ AC_LANG_SOURCE([#include <time.h>
+ int fn(void) \
+ { time_t s0 = time(NULL); \
+ time_t s1 = time(NULL); \
+ double r = difftime(s0, s1); }])
+ ],
+ AC_MSG_RESULT([yes]),
+ [ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([time is not available on your platform]) ])
+
+AC_MSG_CHECKING([for working epoll])
+AC_COMPILE_IFELSE([
+ AC_LANG_SOURCE([#include <sys/epoll.h>
+ #include <signal.h>
+ int fn(void) \
+ { int fd = epoll_create1(0); \
+ struct epoll_event ev = {0,{0}}; \
+ struct epoll_event polled[[16]]; \
+ sigset_t eset; sigemptyset(&eset); \
+ epoll_ctl(fd, EPOLL_CTL_ADD, 0, &ev); \
+ epoll_pwait(fd, polled, 16, -1, &eset); \
+ close(fd); }])
+ ],
+ AC_MSG_RESULT([yes]),
+ [ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([epoll is not available on your platform]) ])
+
AC_MSG_CHECKING([for working va_arg])
AC_COMPILE_IFELSE([
AC_LANG_SOURCE([#include <stdio.h>
@@ -139,7 +170,8 @@ AC_CHECK_FUNCS([open read write close malloc free memset memcpy fork unshare \
wait waitpid isprint remove unlink mkdir access stat chroot chdir mount umount mknod \
strncat strncpy snprintf vsnprintf printf fprintf getpid \
prctl signal signalfd fcntl getenv kill exit \
- setsockopt socket connect accept bind listen], [],
+ setsockopt socket connect accept bind listen \
+ time difftime], [],
[ AC_MSG_ERROR([required function not available]) ])
dnl GAI functions
AC_CHECK_FUNCS([getaddrinfo getnameinfo freeaddrinfo], [],
diff --git a/src/redirector.c b/src/redirector.c
index be3802f..b4d7a78 100644
--- a/src/redirector.c
+++ b/src/redirector.c
@@ -4,6 +4,7 @@
#include <string.h>
#include <signal.h>
#include <pthread.h>
+#include <time.h>
#include <assert.h>
#include "redirector.h"
@@ -21,6 +22,8 @@ typedef struct client_thread {
typedef struct server_event {
redirector_ctx **rdr_ctx;
const size_t siz;
+ size_t last_accept_count;
+ time_t last_accept_stamp;
} server_event;
typedef struct client_event {
@@ -222,11 +225,12 @@ fwd_state_string(const forward_state c_state, const client_thread *args,
static int redirector_mainloop(event_ctx **ev_ctx, redirector_ctx *rdr_ctx[], size_t siz)
{
int rc;
- server_event ev_srv = { rdr_ctx, siz };
+ server_event ev_srv = { rdr_ctx, siz, 0, 0 };
set_procname("[potd] redirector");
assert( set_child_sighandler() == 0 );
+ ev_srv.last_accept_stamp = time(NULL);
rc = event_loop(*ev_ctx, redirector_accept_client, &ev_srv);
event_free(ev_ctx);
@@ -236,7 +240,9 @@ static int redirector_mainloop(event_ctx **ev_ctx, redirector_ctx *rdr_ctx[], si
static int redirector_accept_client(event_ctx *ev_ctx, int fd, void *user_data)
{
size_t i;
+ double d;
int s;
+ time_t t;
server_event *ev_srv = (server_event *) user_data;
client_thread *args;
redirector_ctx *rdr_ctx;
@@ -258,6 +264,21 @@ static int redirector_accept_client(event_ctx *ev_ctx, int fd, void *user_data)
goto error;
}
+ ev_srv->last_accept_count++;
+ t = time(NULL);
+ d = difftime(t, ev_srv->last_accept_stamp);
+ if (d == 0.0f)
+ d = 1.0f;
+ if (d > 5.0f) {
+ ev_srv->last_accept_stamp = t;
+ ev_srv->last_accept_count = 0;
+ }
+ if (ev_srv->last_accept_count / (size_t)d > 3) {
+ W2("DoS protection: Got %zu accepts/s",
+ ev_srv->last_accept_count / (size_t)d);
+ goto error;
+ }
+
args->rdr_ctx = rdr_ctx;
s = socket_addrtostr_in(&args->client_sock,
args->host_buf, args->service_buf);