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