diff --git a/src/main.h b/src/main.h
index 9b98dbbb..3fc6f583 100644
--- a/src/main.h
+++ b/src/main.h
@@ -236,19 +236,28 @@ int handle_resume_store_req(main_server_st* s, struct proc_st *proc,
int session_open(main_server_st * s, struct proc_st *proc, const uint8_t *cookie, unsigned cookie_size);
int session_close(main_server_st * s, struct proc_st *proc);
+#ifdef DISABLE_LOGS
+/* for testing */
+# define mslog(...)
+
+#else
+
void
__attribute__ ((format(printf, 4, 5)))
_mslog(const main_server_st * s, const struct proc_st* proc,
int priority, const char *fmt, ...);
-#ifdef __GNUC__
-# define mslog(s, proc, prio, fmt, ...) \
+# ifdef __GNUC__
+# define mslog(s, proc, prio, fmt, ...) \
(prio==LOG_ERR)?_mslog(s, proc, prio, "%s:%d: "fmt, __FILE__, __LINE__, ##__VA_ARGS__): \
_mslog(s, proc, prio, fmt, ##__VA_ARGS__)
-#else
-# define mslog _mslog
+# else
+# define mslog _mslog
+# endif
+
#endif
+
void mslog_hex(const main_server_st * s, const struct proc_st* proc,
int priority, const char *prefix, uint8_t* bin, unsigned bin_size, unsigned b64);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ee8bc23e..d378ed26 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -31,6 +31,12 @@ AM_CPPFLAGS = \
-I$(top_builddir)/gl/ \
-I$(top_srcdir)/ \
-I$(top_builddir)/
+
+CCAN_SOURCES = ../src/ccan/build_assert/build_assert.h ../src/ccan/check_type/check_type.h \
+ ../src/ccan/container_of/container_of.h ../src/ccan/hash/hash.c ../src/ccan/hash/hash.h \
+ ../src/ccan/htable/htable.c ../src/ccan/htable/htable.h ../src/ccan/htable/htable_type.h \
+ ../src/ccan/list/list.c ../src/ccan/list/list.h
+
kkdcp_parsing_SOURCES = ../src/config-kkdcp.c kkdcp-parsing.c
kkdcp_parsing_LDADD = ../gl/libgnu.a $(LIBTALLOC_LIBS)
@@ -40,13 +46,17 @@ json_escape_LDADD = ../gl/libgnu.a $(LIBTALLOC_LIBS)
ipv4_prefix_SOURCES = ../src/ip-util.c ../src/ip-util.h ipv4-prefix.c
ipv4_prefix_LDADD = ../gl/libgnu.a $(LIBTALLOC_LIBS)
+ban_ips_CPPFLAGS = $(AM_CPPFLAGS) -DDISABLE_LOGS
+ban_ips_SOURCES = ../src/main-ban.c ../src/main.h ban-ips.c $(CCAN_SOURCES)
+ban_ips_LDADD = ../gl/libgnu.a $(LIBTALLOC_LIBS)
+
str_test_SOURCES = ../src/str.c ../src/str.h str-test.c
str_test_LDADD = ../gl/libgnu.a $(LIBTALLOC_LIBS)
ipv6_prefix_SOURCES = ../src/ip-util.c ../src/ip-util.h ipv6-prefix.c
ipv6_prefix_LDADD = ../gl/libgnu.a $(LIBTALLOC_LIBS)
-check_PROGRAMS = str-test ipv4-prefix ipv6-prefix kkdcp-parsing json-escape
+check_PROGRAMS = str-test ipv4-prefix ipv6-prefix kkdcp-parsing json-escape ban-ips
TESTS = $(dist_check_SCRIPTS) $(check_PROGRAMS)
diff --git a/tests/ban-ips.c b/tests/ban-ips.c
new file mode 100644
index 00000000..ed6a4add
--- /dev/null
+++ b/tests/ban-ips.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "../src/main.h"
+#include "../src/main-ban.h"
+#include "../src/ip-util.h"
+
+/* Test the IP banning functionality */
+static
+unsigned check_if_banned_str(main_server_st *s, const char *ip)
+{
+ struct sockaddr_storage addr;
+ int ret;
+
+ if (strchr(ip, ':') != 0) {
+ ret = inet_pton(AF_INET6, ip, SA_IN6_P(&addr));
+ addr.ss_family = AF_INET6;
+ } else {
+ ret = inet_pton(AF_INET, ip, SA_IN_P(&addr));
+ addr.ss_family = AF_INET;
+ }
+
+ if (ret != 1) {
+ fprintf(stderr, "cannot convert IP: %s\n", ip);
+ exit(1);
+ }
+ return check_if_banned(s, &addr, addr.ss_family==AF_INET?sizeof(struct sockaddr_in):sizeof(struct sockaddr_in6));
+}
+
+int main()
+{
+ main_server_st *s = talloc(NULL, struct main_server_st);
+ if (s == NULL)
+ exit(1);
+
+ memset(s, 0, sizeof(*s));
+
+ s->config = talloc(s, struct cfg_st);
+ if (s->config == NULL)
+ exit(1);
+
+ memset(s->config, 0, sizeof(struct cfg_st));
+
+ s->config->max_ban_score = 20;
+ s->config->min_reauth_time = 30;
+
+ main_ban_db_init(s);
+
+ /* check IPv4 */
+ add_str_ip_to_ban_list(s, "192.168.1.1", 5);
+ add_str_ip_to_ban_list(s, "192.168.1.1", 10);
+ add_str_ip_to_ban_list(s, "192.168.1.1", 5);
+
+ add_str_ip_to_ban_list(s, "192.168.2.1", 5);
+
+ add_str_ip_to_ban_list(s, "192.168.3.1", 40);
+
+ cleanup_banned_entries(s);
+
+ if (check_if_banned_str(s, "192.168.1.1") == 0) {
+ fprintf(stderr, "error in %d\n", __LINE__);
+ exit(1);
+ }
+
+ if (check_if_banned_str(s, "192.168.2.1") != 0) {
+ fprintf(stderr, "error in %d\n", __LINE__);
+ exit(1);
+ }
+
+ if (check_if_banned_str(s, "192.168.3.1") == 0) {
+ fprintf(stderr, "error in %d\n", __LINE__);
+ exit(1);
+ }
+
+ /* check IPv6 */
+
+ /* a single /64 */
+ add_str_ip_to_ban_list(s, "fc8e:899a:0624:5a89:1a45:63d8:1c92:0bc1", 5);
+ add_str_ip_to_ban_list(s, "fc8e:899a:0624:5a89:1a45:63d9:1c92:0bc1", 10);
+ add_str_ip_to_ban_list(s, "fc8e:899a:0624:5a89:1a45:63d8:1c93:0bc1", 5);
+
+ add_str_ip_to_ban_list(s, "fdd9:1ce6:1bee:bdea:5d8c:0840:8666:5942", 5);
+
+ add_str_ip_to_ban_list(s, "fdc0:c81f:22ab:23a2:4479:f107:1855:bf50", 40);
+
+ /* check /64 */
+ if (check_if_banned_str(s, "fc8e:899a:0624:5a89:1a45:63d8:1c93:0bc1") == 0) {
+ fprintf(stderr, "error in %d\n", __LINE__);
+ exit(1);
+ }
+
+ if (check_if_banned_str(s, "fc8e:899a:0624:5a89:1a46:63d9:1c93:0bc1") == 0) {
+ fprintf(stderr, "error in %d\n", __LINE__);
+ exit(1);
+ }
+
+ /* check individual */
+ if (check_if_banned_str(s, "fdd9:1ce6:1bee:bdea:5d8c:0840:8666:5942") != 0) {
+ fprintf(stderr, "error in %d\n", __LINE__);
+ exit(1);
+ }
+
+ if (check_if_banned_str(s, "fdc0:c81f:22ab:23a2:4479:f107:1855:bf50") == 0) {
+ fprintf(stderr, "error in %d\n", __LINE__);
+ exit(1);
+ }
+
+ /* check expiration of entries */
+ sleep(s->config->min_reauth_time+1);
+
+ if (check_if_banned_str(s, "192.168.1.1") != 0) {
+ fprintf(stderr, "error in %d\n", __LINE__);
+ exit(1);
+ }
+
+ if (check_if_banned_str(s, "192.168.2.1") != 0) {
+ fprintf(stderr, "error in %d\n", __LINE__);
+ exit(1);
+ }
+
+ if (check_if_banned_str(s, "192.168.3.1") != 0) {
+ fprintf(stderr, "error in %d\n", __LINE__);
+ exit(1);
+ }
+
+ if (check_if_banned_str(s, "fdc0:c81f:22ab:23a2:4479:f107:1855:bf50") != 0) {
+ fprintf(stderr, "error in %d\n", __LINE__);
+ exit(1);
+ }
+
+ /* check cleanup */
+ sleep(s->config->min_reauth_time+1);
+
+ cleanup_banned_entries(s);
+
+ if (main_ban_db_elems(s) != 0) {
+ fprintf(stderr, "error in %d: have %d entries\n", __LINE__, main_ban_db_elems(s));
+ exit(1);
+ }
+
+
+ talloc_free(s);
+ return 0;
+}