]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
director: If user host conflict is detected, make sure new host is sent back.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 24 Oct 2016 21:13:23 +0000 (00:13 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 25 Oct 2016 18:01:23 +0000 (21:01 +0300)
USER-KICK-HASH was sent, but the sender didn't get back a USER reply with
the new host. This could have increased how long user's host differred in
directors.

Avoids repeating this error:
Error: User hash 2957018085 is being redirected to two hosts: 10.0.0.30 and 10.0.0.201 (old_ts=1477338836)

src/director/director-connection.c

index e216e39b67a007cde0088ce20e1ded698113203d..9aa5b1546374933657f77aba4ea67f8404f87fc3 100644 (file)
@@ -497,12 +497,15 @@ static bool director_cmd_me(struct director_connection *conn,
 static bool
 director_user_refresh(struct director_connection *conn,
                      unsigned int username_hash, struct mail_host *host,
-                     time_t timestamp, bool weak, struct user **user_r)
+                     time_t timestamp, bool weak, bool *forced_r,
+                     struct user **user_r)
 {
        struct director *dir = conn->dir;
        struct user *user;
        bool ret = FALSE, unset_weak_user = FALSE;
 
+       *forced_r = FALSE;
+
        user = user_directory_lookup(dir->users, username_hash);
        if (user == NULL) {
                *user_r = user_directory_add(dir->users, username_hash,
@@ -585,7 +588,10 @@ director_user_refresh(struct director_connection *conn,
                if (net_ip_cmp(&user->host->ip, &host->ip) > 0) {
                        /* change the host. we'll also need to remove the user
                           from the old host's user_count, because we can't
-                          keep track of the user for more than one host */
+                          keep track of the user for more than one host.
+
+                          send the updated USER back to the sender as well. */
+                       *forced_r = TRUE;
                } else {
                        /* keep the host */
                        host = user->host;
@@ -628,7 +634,7 @@ director_handshake_cmd_user(struct director_connection *conn,
        struct ip_addr ip;
        struct mail_host *host;
        struct user *user;
-       bool weak;
+       bool weak, forced;
 
        if (str_array_length(args) < 3 ||
            str_to_uint(args[0], &username_hash) < 0 ||
@@ -647,7 +653,7 @@ director_handshake_cmd_user(struct director_connection *conn,
        }
 
        (void)director_user_refresh(conn, username_hash, host,
-                                   timestamp, weak, &user);
+                                   timestamp, weak, &forced, &user);
        if (user->timestamp < timestamp) {
                conn->users_unsorted = TRUE;
                user->timestamp = timestamp;
@@ -663,6 +669,7 @@ director_cmd_user(struct director_connection *conn,
        struct ip_addr ip;
        struct mail_host *host;
        struct user *user;
+       bool forced;
 
        /* NOTE: if more parameters are added, update also
           CMD_IS_USER_HANDHAKE() macro */
@@ -680,9 +687,11 @@ director_cmd_user(struct director_connection *conn,
        }
 
        if (director_user_refresh(conn, username_hash,
-                                 host, ioloop_time, FALSE, &user)) {
+                                 host, ioloop_time, FALSE, &forced, &user)) {
+               struct director_host *src_host =
+                       forced ? conn->dir->self_host : conn->host;
                i_assert(!user->weak);
-               director_update_user(conn->dir, conn->host, user);
+               director_update_user(conn->dir, src_host, user);
        }
        return TRUE;
 }
@@ -828,7 +837,7 @@ director_cmd_user_weak(struct director_connection *conn,
        struct mail_host *host;
        struct user *user;
        struct director_host *src_host = conn->host;
-       bool weak = TRUE, weak_forward = FALSE;
+       bool weak = TRUE, weak_forward = FALSE, forced;
        int ret;
 
        /* note that unlike other commands we don't want to just ignore
@@ -876,8 +885,10 @@ director_cmd_user_weak(struct director_connection *conn,
        }
 
        if (director_user_refresh(conn, username_hash,
-                                 host, ioloop_time, weak, &user) ||
+                                 host, ioloop_time, weak, &forced, &user) ||
            weak_forward) {
+               if (forced)
+                       src_host = conn->dir->self_host;
                if (!user->weak)
                        director_update_user(conn->dir, src_host, user);
                else {