dovecot-2.0-sslstream: anvil: Added support for penalty tracking.

dovecot at dovecot.org dovecot at dovecot.org
Sat Feb 13 02:56:17 EET 2010


details:   http://hg.dovecot.org/dovecot-2.0-sslstream/rev/ea209b33ef96
changeset: 10299:ea209b33ef96
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Nov 10 15:06:43 2009 -0500
description:
anvil: Added support for penalty tracking.

diffstat:

7 files changed, 179 insertions(+), 12 deletions(-)
src/anvil/Makefile.am        |    6 +-
src/anvil/anvil-connection.c |   35 +++++++++--
src/anvil/anvil-settings.c   |    6 +-
src/anvil/common.h           |    1 
src/anvil/main.c             |    4 +
src/anvil/penalty.c          |  125 ++++++++++++++++++++++++++++++++++++++++++
src/anvil/penalty.h          |   14 ++++

diffs (truncated from 306 to 300 lines):

diff -r e6840e39ebc7 -r ea209b33ef96 src/anvil/Makefile.am
--- a/src/anvil/Makefile.am	Mon Nov 09 22:04:33 2009 -0500
+++ b/src/anvil/Makefile.am	Tue Nov 10 15:06:43 2009 -0500
@@ -17,9 +17,11 @@ anvil_SOURCES = \
 	main.c \
 	anvil-connection.c \
 	anvil-settings.c \
-	connect-limit.c
+	connect-limit.c \
+	penalty.c
 
 noinst_HEADERS = \
 	anvil-connection.h \
 	common.h \
-	connect-limit.h
+	connect-limit.h \
+	penalty.h
diff -r e6840e39ebc7 -r ea209b33ef96 src/anvil/anvil-connection.c
--- a/src/anvil/anvil-connection.c	Mon Nov 09 22:04:33 2009 -0500
+++ b/src/anvil/anvil-connection.c	Tue Nov 10 15:06:43 2009 -0500
@@ -7,6 +7,7 @@
 #include "master-service.h"
 #include "master-interface.h"
 #include "connect-limit.h"
+#include "penalty.h"
 #include "anvil-connection.h"
 
 #include <stdlib.h>
@@ -46,7 +47,8 @@ anvil_connection_request(struct anvil_co
 			 const char *const *args, const char **error_r)
 {
 	const char *cmd = args[0];
-	unsigned int count;
+	unsigned int value;
+	time_t stamp;
 	pid_t pid;
 
 	args++;
@@ -57,7 +59,6 @@ anvil_connection_request(struct anvil_co
 		}
 		pid = strtol(args[0], NULL, 10);
 		connect_limit_connect(connect_limit, pid, args[1]);
-		return 0;
 	} else if (strcmp(cmd, "DISCONNECT") == 0) {
 		if (args[0] == NULL || args[1] == NULL) {
 			*error_r = "DISCONNECT: Not enough parameters";
@@ -65,10 +66,8 @@ anvil_connection_request(struct anvil_co
 		}
 		pid = strtol(args[0], NULL, 10);
 		connect_limit_disconnect(connect_limit, pid, args[1]);
-		return 0;
 	} else if (strcmp(cmd, "CONNECT-DUMP") == 0) {
 		connect_limit_dump(connect_limit, conn->output);
-		return 0;
 	} else if (strcmp(cmd, "KILL") == 0) {
 		if (args[0] == NULL) {
 			*error_r = "KILL: Not enough parameters";
@@ -80,7 +79,6 @@ anvil_connection_request(struct anvil_co
 		}
 		pid = strtol(args[0], NULL, 10);
 		connect_limit_disconnect_pid(connect_limit, pid);
-		return 0;
 	} else if (strcmp(cmd, "LOOKUP") == 0) {
 		if (args[0] == NULL) {
 			*error_r = "LOOKUP: Not enough parameters";
@@ -90,14 +88,35 @@ anvil_connection_request(struct anvil_co
 			*error_r = "LOOKUP on a FIFO, can't send reply";
 			return -1;
 		}
-		count = connect_limit_lookup(connect_limit, args[0]);
+		value = connect_limit_lookup(connect_limit, args[0]);
 		(void)o_stream_send_str(conn->output,
-					t_strdup_printf("%u\n", count));
-		return 0;
+					t_strdup_printf("%u\n", value));
+	} else if (strcmp(cmd, "PENALTY-GET") == 0) {
+		if (args[0] == NULL) {
+			*error_r = "PENALTY-GET: Not enough parameters";
+			return -1;
+		}
+		value = penalty_get(penalty, args[0], &stamp);
+		(void)o_stream_send_str(conn->output,
+			t_strdup_printf("%u %s\n", value, dec2str(stamp)));
+	} else if (strcmp(cmd, "PENALTY-SET") == 0) {
+		if (args[0] == NULL || args[1] == NULL) {
+			*error_r = "PENALTY-SET: Not enough parameters";
+			return -1;
+		}
+		penalty_set(penalty, args[0], strtoul(args[1], NULL, 10));
+	} else if (strcmp(cmd, "PENALTY-SET-EXPIRE-SECS") == 0) {
+		if (args[0] == NULL) {
+			*error_r = "PENALTY-SET-EXPIRE-SECS: "
+				"Not enough parameters";
+			return -1;
+		}
+		penalty_set_expire_secs(penalty, atoi(args[0]));
 	} else {
 		*error_r = t_strconcat("Unknown command: ", cmd, NULL);
 		return -1;
 	}
+	return 0;
 }
 
 static void anvil_connection_input(void *context)
diff -r e6840e39ebc7 -r ea209b33ef96 src/anvil/anvil-settings.c
--- a/src/anvil/anvil-settings.c	Mon Nov 09 22:04:33 2009 -0500
+++ b/src/anvil/anvil-settings.c	Tue Nov 10 15:06:43 2009 -0500
@@ -9,10 +9,12 @@
 
 /* <settings checks> */
 static struct file_listener_settings anvil_unix_listeners_array[] = {
-	{ "anvil", 0600, "", "" }
+	{ "anvil", 0600, "", "" },
+	{ "anvil-auth-penalty", 0600, "", "" }
 };
 static struct file_listener_settings *anvil_unix_listeners[] = {
-	&anvil_unix_listeners_array[0]
+	&anvil_unix_listeners_array[0],
+	&anvil_unix_listeners_array[1]
 };
 static buffer_t anvil_unix_listeners_buf = {
 	anvil_unix_listeners, sizeof(anvil_unix_listeners), { 0, }
diff -r e6840e39ebc7 -r ea209b33ef96 src/anvil/common.h
--- a/src/anvil/common.h	Mon Nov 09 22:04:33 2009 -0500
+++ b/src/anvil/common.h	Tue Nov 10 15:06:43 2009 -0500
@@ -4,5 +4,6 @@
 #include "lib.h"
 
 extern struct connect_limit *connect_limit;
+extern struct penalty *penalty;
 
 #endif
diff -r e6840e39ebc7 -r ea209b33ef96 src/anvil/main.c
--- a/src/anvil/main.c	Mon Nov 09 22:04:33 2009 -0500
+++ b/src/anvil/main.c	Tue Nov 10 15:06:43 2009 -0500
@@ -6,9 +6,11 @@
 #include "master-service.h"
 #include "master-interface.h"
 #include "connect-limit.h"
+#include "penalty.h"
 #include "anvil-connection.h"
 
 struct connect_limit *connect_limit;
+struct penalty *penalty;
 
 static void client_connected(const struct master_service_connection *conn)
 {
@@ -27,9 +29,11 @@ int main(int argc, char *argv[])
 	master_service_init_log(master_service, "anvil: ");
 	master_service_init_finish(master_service);
 	connect_limit = connect_limit_init();
+	penalty = penalty_init();
 
 	master_service_run(master_service, client_connected);
 
+	penalty_deinit(&penalty);
 	connect_limit_deinit(&connect_limit);
 	anvil_connections_destroy_all();
 	master_service_deinit(&master_service);
diff -r e6840e39ebc7 -r ea209b33ef96 src/anvil/penalty.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/anvil/penalty.c	Tue Nov 10 15:06:43 2009 -0500
@@ -0,0 +1,125 @@
+/* Copyright (C) 2009 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "ioloop.h"
+#include "hash.h"
+#include "llist.h"
+#include "penalty.h"
+
+#include <time.h>
+
+#define PENALTY_DEFAULT_EXPIRE_SECS (60*60)
+
+struct penalty_rec {
+	/* ordered by last_update */
+	struct penalty_rec *prev, *next;
+
+	char *ident;
+	unsigned int penalty;
+	time_t last_update;
+};
+
+struct penalty {
+	/* ident => penalty_rec */
+	struct hash_table *hash;
+	struct penalty_rec *oldest, *newest;
+
+	unsigned int expire_secs;
+	struct timeout *to;
+};
+
+struct penalty *penalty_init(void)
+{
+	struct penalty *penalty;
+
+	penalty = i_new(struct penalty, 1);
+	penalty->hash =
+		hash_table_create(default_pool, default_pool, 0,
+				  str_hash, (hash_cmp_callback_t *)strcmp);
+	penalty->expire_secs = PENALTY_DEFAULT_EXPIRE_SECS;
+	return penalty;
+}
+
+static void penalty_rec_free(struct penalty *penalty, struct penalty_rec *rec)
+{
+	DLLIST2_REMOVE(&penalty->oldest, &penalty->newest, rec);
+	i_free(rec->ident);
+	i_free(rec);
+}
+
+void penalty_deinit(struct penalty **_penalty)
+{
+	struct penalty *penalty = *_penalty;
+
+	*_penalty = NULL;
+
+	while (penalty->oldest != NULL)
+		penalty_rec_free(penalty, penalty->oldest);
+	hash_table_destroy(&penalty->hash);
+
+	if (penalty->to != NULL)
+		timeout_remove(&penalty->to);
+	i_free(penalty);
+}
+
+void penalty_set_expire_secs(struct penalty *penalty, unsigned int expire_secs)
+{
+	penalty->expire_secs = expire_secs;
+}
+
+unsigned int penalty_get(struct penalty *penalty, const char *ident,
+			 time_t *last_update_r)
+{
+	struct penalty_rec *rec;
+
+	rec = hash_table_lookup(penalty->hash, ident);
+	if (rec == NULL) {
+		*last_update_r = 0;
+		return 0;
+	} else {
+		*last_update_r = rec->last_update;
+		return rec->penalty;
+	}
+}
+
+static void penalty_timeout(struct penalty *penalty)
+{
+	time_t expire_time;
+
+	expire_time = ioloop_time - penalty->expire_secs;
+	while (penalty->oldest != NULL &&
+	       penalty->oldest->last_update <= expire_time) {
+		hash_table_remove(penalty->hash, penalty->oldest->ident);
+		penalty_rec_free(penalty, penalty->oldest);
+	}
+
+	timeout_remove(&penalty->to);
+	if (penalty->oldest != NULL) {
+		unsigned int diff = penalty->oldest->last_update - expire_time;
+		penalty->to = timeout_add(diff * 1000,
+					  penalty_timeout, penalty);
+	}
+}
+
+void penalty_set(struct penalty *penalty, const char *ident,
+		 unsigned int value)
+{
+	struct penalty_rec *rec;
+
+	rec = hash_table_lookup(penalty->hash, ident);
+	if (rec == NULL) {
+		rec = i_new(struct penalty_rec, 1);
+		rec->ident = i_strdup(ident);
+		hash_table_insert(penalty->hash, rec->ident, rec);
+	} else {
+		DLLIST2_REMOVE(&penalty->oldest, &penalty->newest, rec);
+	}
+	rec->penalty = value;
+	rec->last_update = time(NULL);
+	DLLIST2_APPEND(&penalty->oldest, &penalty->newest, rec);
+
+	if (penalty->to == NULL) {
+		penalty->to = timeout_add(penalty->expire_secs * 1000,
+					  penalty_timeout, penalty);
+	}
+}
diff -r e6840e39ebc7 -r ea209b33ef96 src/anvil/penalty.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/anvil/penalty.h	Tue Nov 10 15:06:43 2009 -0500
@@ -0,0 +1,14 @@
+#ifndef PENALTY_H
+#define PENALTY_H
+
+struct penalty *penalty_init(void);
+void penalty_deinit(struct penalty **penalty);
+
+void penalty_set_expire_secs(struct penalty *penalty, unsigned int expire_secs);
+


More information about the dovecot-cvs mailing list