From: Timo Sirainen Date: Mon, 24 Oct 2016 21:13:23 +0000 (+0300) Subject: director: If user host conflict is detected, make sure new host is sent back. X-Git-Tag: 2.2.27~290 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=50d96a7656432f1c22014664798ed98a2647bc67;p=thirdparty%2Fdovecot%2Fcore.git director: If user host conflict is detected, make sure new host is sent back. 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) --- diff --git a/src/director/director-connection.c b/src/director/director-connection.c index e216e39b67..9aa5b15463 100644 --- a/src/director/director-connection.c +++ b/src/director/director-connection.c @@ -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 {