dovecot-2.2: director: If we detect that a user is being proxied...
dovecot at dovecot.org
dovecot at dovecot.org
Mon Jun 2 01:17:51 UTC 2014
details: http://hg.dovecot.org/dovecot-2.2/rev/8aa0cd95d6a8
changeset: 17419:8aa0cd95d6a8
user: Timo Sirainen <tss at iki.fi>
date: Mon Jun 02 04:16:08 2014 +0300
description:
director: If we detect that a user is being proxied to multiple backends, disconnect wrong connections.
Especially IMAP connections can otherwise stay alive for a long time and
cause problems.
diffstat:
src/director/director-connection.c | 31 +++++++++++++++++++++++++++++++
src/director/director.c | 22 ++++++++++++++++++++++
src/director/director.h | 5 +++++
src/login-common/login-proxy.c | 15 +++++++++++++--
4 files changed, 71 insertions(+), 2 deletions(-)
diffs (144 lines):
diff -r 64808a9703db -r 8aa0cd95d6a8 src/director/director-connection.c
--- a/src/director/director-connection.c Mon Jun 02 04:00:19 2014 +0300
+++ b/src/director/director-connection.c Mon Jun 02 04:16:08 2014 +0300
@@ -531,6 +531,11 @@
/* keep the host */
host = user->host;
}
+ /* especially IMAP connections can take a long time to die.
+ make sure we kill off the connections in the wrong
+ backends. */
+ director_kick_user_hash(dir, dir->self_host, NULL,
+ username_hash, &host->ip);
ret = TRUE;
}
if (user->host != host) {
@@ -958,6 +963,30 @@
}
static bool
+director_cmd_user_kick_hash(struct director_connection *conn,
+ const char *const *args)
+{
+ struct director_host *dir_host;
+ unsigned int username_hash;
+ struct ip_addr except_ip;
+ int ret;
+
+ if ((ret = director_cmd_is_seen(conn, &args, &dir_host)) != 0)
+ return ret > 0;
+
+ if (str_array_length(args) != 2 ||
+ str_to_uint(args[0], &username_hash) < 0 ||
+ net_addr2ip(args[1], &except_ip) < 0) {
+ director_cmd_error(conn, "Invalid parameters");
+ return FALSE;
+ }
+
+ director_kick_user_hash(conn->dir, conn->host, dir_host,
+ username_hash, &except_ip);
+ return TRUE;
+}
+
+static bool
director_cmd_user_killed(struct director_connection *conn,
const char *const *args)
{
@@ -1337,6 +1366,8 @@
return director_cmd_user_move(conn, args);
if (strcmp(cmd, "USER-KICK") == 0)
return director_cmd_user_kick(conn, args);
+ if (strcmp(cmd, "USER-KICK-HASH") == 0)
+ return director_cmd_user_kick_hash(conn, args);
if (strcmp(cmd, "USER-KILLED") == 0)
return director_cmd_user_killed(conn, args);
if (strcmp(cmd, "USER-KILLED-EVERYWHERE") == 0)
diff -r 64808a9703db -r 8aa0cd95d6a8 src/director/director.c
--- a/src/director/director.c Mon Jun 02 04:00:19 2014 +0300
+++ b/src/director/director.c Mon Jun 02 04:16:08 2014 +0300
@@ -782,6 +782,28 @@
director_update_send_version(dir, src, DIRECTOR_VERSION_USER_KICK, cmd);
}
+void director_kick_user_hash(struct director *dir, struct director_host *src,
+ struct director_host *orig_src,
+ unsigned int username_hash,
+ const struct ip_addr *except_ip)
+{
+ const char *cmd;
+
+ cmd = t_strdup_printf("proxy\t*\tKICK-DIRECTOR-HASH\t%u\t%s",
+ username_hash, net_ip2addr(except_ip));
+ ipc_client_cmd(dir->ipc_proxy, cmd,
+ director_kick_user_callback, (void *)NULL);
+
+ if (orig_src == NULL) {
+ orig_src = dir->self_host;
+ orig_src->last_seq++;
+ }
+ cmd = t_strdup_printf("USER-KICK-HASH\t%s\t%u\t%u\t%u\t%s\n",
+ net_ip2addr(&orig_src->ip), orig_src->port, orig_src->last_seq,
+ username_hash, net_ip2addr(except_ip));
+ director_update_send_version(dir, src, DIRECTOR_VERSION_USER_KICK, cmd);
+}
+
void director_user_killed(struct director *dir, unsigned int username_hash)
{
struct user *user;
diff -r 64808a9703db -r 8aa0cd95d6a8 src/director/director.h
--- a/src/director/director.h Mon Jun 02 04:00:19 2014 +0300
+++ b/src/director/director.h Mon Jun 02 04:16:08 2014 +0300
@@ -136,6 +136,11 @@
void director_kick_user(struct director *dir, struct director_host *src,
struct director_host *orig_src, const char *username)
ATTR_NULL(3);
+void director_kick_user_hash(struct director *dir, struct director_host *src,
+ struct director_host *orig_src,
+ unsigned int username_hash,
+ const struct ip_addr *except_ip)
+ ATTR_NULL(3);
void director_user_killed(struct director *dir, unsigned int username_hash);
void director_user_killed_everywhere(struct director *dir,
struct director_host *src,
diff -r 64808a9703db -r 8aa0cd95d6a8 src/login-common/login-proxy.c
--- a/src/login-common/login-proxy.c Mon Jun 02 04:00:19 2014 +0300
+++ b/src/login-common/login-proxy.c Mon Jun 02 04:16:08 2014 +0300
@@ -650,17 +650,27 @@
login_proxy_cmd_kick_director_hash(struct ipc_cmd *cmd, const char *const *args)
{
struct login_proxy *proxy, *next;
+ struct ip_addr except_ip;
unsigned int hash, count = 0;
if (args[0] == NULL || str_to_uint(args[0], &hash) < 0) {
ipc_cmd_fail(&cmd, "Invalid parameters");
return;
}
+ /* optional except_ip parameter specifies that we're not killing the
+ connections that are proxying to the except_ip backend */
+ except_ip.family = 0;
+ if (args[1] != NULL && args[1][0] != '\0' &&
+ net_addr2ip(args[1], &except_ip) < 0) {
+ ipc_cmd_fail(&cmd, "Invalid except_ip parameter");
+ return;
+ }
for (proxy = login_proxies; proxy != NULL; proxy = next) {
next = proxy->next;
- if (director_username_hash(proxy->client) == hash) {
+ if (director_username_hash(proxy->client) == hash &&
+ !net_ip_compare(&proxy->ip, &except_ip)) {
login_proxy_free_reason(&proxy, KILLED_BY_ADMIN_REASON);
count++;
}
@@ -668,7 +678,8 @@
for (proxy = login_proxies_pending; proxy != NULL; proxy = next) {
next = proxy->next;
- if (director_username_hash(proxy->client) == hash) {
+ if (director_username_hash(proxy->client) == hash &&
+ !net_ip_compare(&proxy->ip, &except_ip)) {
client_destroy(proxy->client, "Connection kicked");
count++;
}
More information about the dovecot-cvs
mailing list