doveadm-connection.c revision 6c76bcb36f50843dac534fc6aceabe952509e580
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2010-2017 Dovecot authors, see the included COPYING file */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "lib.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "ioloop.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "net.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "istream.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "ostream.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "array.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "str.h"
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen#include "strescape.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "llist.h"
9522aa5f33cc37fe8ccd0d647cc51dd3ba6a9b55Timo Sirainen#include "master-service.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "user-directory.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "mail-host.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "director.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "director-host.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "director-request.h"
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen#include "director-connection.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "doveadm-connection.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include <unistd.h>
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen#define DOVEADM_PROTOCOL_VERSION_MAJOR 1
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen#define DOVEADM_HANDSHAKE "VERSION\tdirector-doveadm\t1\t0\n"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#define MAX_VALID_VHOST_COUNT 1000
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen#define DEFAULT_MAX_MOVING_USERS 100
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen#define DOVEADM_CONNECTION_RING_SYNC_TIMEOUT_MSECS (30*1000)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainenenum doveadm_director_cmd_ret {
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen DOVEADM_DIRECTOR_CMD_RET_FAIL = -1,
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen DOVEADM_DIRECTOR_CMD_RET_UNFINISHED = 0,
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen DOVEADM_DIRECTOR_CMD_RET_OK = 1,
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen DOVEADM_DIRECTOR_CMD_RET_RING_SYNC_OK,
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen};
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainenenum doveadm_director_cmd_flag {
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen DOVEADM_DIRECTOR_CMD_FLAG_PRE_RING_SYNC = 0x01,
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen};
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainentypedef void
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainendoveadm_connection_ring_sync_callback_t(struct doveadm_connection *);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainenstruct director_reset_cmd {
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen struct director_reset_cmd *prev, *next;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen struct director *dir;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen struct doveadm_connection *_conn;
b44033e45e9f48f8a6e1ac5905234fec5de6d6ccAki Tuomi struct director_user_iter *iter;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen unsigned int host_idx, hosts_count;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen unsigned int max_moving_users;
6c76bcb36f50843dac534fc6aceabe952509e580Timo Sirainen bool users_killed;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen};
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstruct doveadm_connection {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct doveadm_connection *prev, *next;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen int fd;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct io *io;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct istream *input;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct ostream *output;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct director *dir;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen struct timeout *to_ring_sync_abort;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen struct director_reset_cmd *reset_cmd;
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen doveadm_connection_ring_sync_callback_t *ring_sync_callback;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen const char **cmd_pending_args;
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen unsigned int cmd_pending_idx;
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool handshaked:1;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen};
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic struct doveadm_connection *doveadm_connections;
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainenstatic struct doveadm_connection *doveadm_ring_sync_pending_connections;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainenstatic struct director_reset_cmd *reset_cmds = NULL;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainenstatic void doveadm_connection_set_io(struct doveadm_connection *conn);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic void doveadm_connection_deinit(struct doveadm_connection **_conn);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainenstatic void
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainendoveadm_connection_ring_sync_list_move(struct doveadm_connection *conn);
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainenstatic void doveadm_connection_cmd_run_synced(struct doveadm_connection *conn);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainenstatic enum doveadm_director_cmd_ret
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainendoveadm_cmd_host_list(struct doveadm_connection *conn,
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen const char *const *args ATTR_UNUSED)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct mail_host *const *hostp;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen string_t *str = t_str_new(1024);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen array_foreach(mail_hosts_get(conn->dir->mail_hosts), hostp) {
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen str_printfa(str, "%s\t%u\t%u\t",
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen net_ip2addr(&(*hostp)->ip), (*hostp)->vhost_count,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen (*hostp)->user_count);
093b42b11c1236a687d3da564b26a324e2189ae6Timo Sirainen str_append_tabescaped(str, mail_host_get_tag(*hostp));
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen str_printfa(str, "\t%c\t%ld", (*hostp)->down ? 'D' : 'U',
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen (long)(*hostp)->last_updown_change);
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen str_append_c(str, '\n');
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen str_append_c(str, '\n');
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(conn->output, str_data(str), str_len(str));
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainenstatic enum doveadm_director_cmd_ret
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainendoveadm_cmd_host_list_removed(struct doveadm_connection *conn,
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen const char *const *args ATTR_UNUSED)
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen{
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen struct mail_host_list *orig_hosts_list;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen struct mail_host *const *orig_hosts, *const *cur_hosts;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen unsigned int i, j, orig_hosts_count, cur_hosts_count;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen string_t *str = t_str_new(1024);
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen int ret;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen
b44033e45e9f48f8a6e1ac5905234fec5de6d6ccAki Tuomi orig_hosts_list = mail_hosts_init(conn->dir->set->director_user_expire,
b44033e45e9f48f8a6e1ac5905234fec5de6d6ccAki Tuomi NULL);
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen (void)mail_hosts_parse_and_add(orig_hosts_list,
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen conn->dir->set->director_mail_servers);
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen orig_hosts = array_get(mail_hosts_get(orig_hosts_list),
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen &orig_hosts_count);
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen cur_hosts = array_get(mail_hosts_get(conn->dir->mail_hosts),
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen &cur_hosts_count);
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen /* the hosts are sorted by IP */
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen for (i = j = 0; i < orig_hosts_count && j < cur_hosts_count; ) {
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen ret = net_ip_cmp(&orig_hosts[i]->ip, &cur_hosts[j]->ip);
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen if (ret == 0)
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen i++, j++;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen else if (ret > 0)
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen j++;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen else {
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen str_printfa(str, "%s\n",
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen net_ip2addr(&orig_hosts[i]->ip));
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen i++;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen }
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen }
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen for (; i < orig_hosts_count; i++)
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen str_printfa(str, "%s\n", net_ip2addr(&orig_hosts[i]->ip));
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen str_append_c(str, '\n');
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(conn->output, str_data(str), str_len(str));
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen mail_hosts_deinit(&orig_hosts_list);
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen}
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainenstatic void doveadm_director_append_status(struct director *dir, string_t *str)
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen{
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen if (!dir->ring_handshaked)
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen str_append(str, "handshaking");
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen else if (dir->ring_synced)
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen str_append(str, "synced");
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen else {
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen str_printfa(str, "syncing - last sync %d secs ago",
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen (int)(ioloop_time - dir->ring_last_sync_time));
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen }
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen}
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainenstatic void
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainendoveadm_director_connection_append_status(struct director_connection *conn,
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen string_t *str)
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen{
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen if (!director_connection_is_handshaked(conn))
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen str_append(str, "handshaking");
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen else if (director_connection_is_synced(conn))
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen str_append(str, "synced");
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen else
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen str_append(str, "syncing");
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen}
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainenstatic void
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainendoveadm_director_host_append_status(struct director *dir,
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen const struct director_host *host,
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen string_t *str)
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen{
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen struct director_connection *conn = NULL;
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen if (dir->left != NULL &&
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen director_connection_get_host(dir->left) == host)
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen conn = dir->left;
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen else if (dir->right != NULL &&
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen director_connection_get_host(dir->right) == host)
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen conn = dir->right;
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen else {
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen /* we might have a connection that is being connected */
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen struct director_connection *const *connp;
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen array_foreach(&dir->connections, connp) {
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen if (director_connection_get_host(*connp) == host) {
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen conn = *connp;
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen break;
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen }
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen }
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen }
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen if (conn != NULL)
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen doveadm_director_connection_append_status(conn, str);
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen}
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainenstatic enum doveadm_director_cmd_ret
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainendoveadm_cmd_director_list(struct doveadm_connection *conn,
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen const char *const *args ATTR_UNUSED)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen struct director *dir = conn->dir;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct director_host *const *hostp;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen string_t *str = t_str_new(1024);
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen const char *type;
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen bool left, right;
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen time_t last_failed;
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen array_foreach(&dir->dir_hosts, hostp) {
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen const struct director_host *host = *hostp;
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen left = dir->left != NULL &&
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen director_connection_get_host(dir->left) == host;
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen right = dir->right != NULL &&
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen director_connection_get_host(dir->right) == host;
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen if (host->removed)
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen type = "removed";
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen else if (dir->self_host == host)
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen type = "self";
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen else if (left)
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen type = right ? "l+r" : "left";
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen else if (right)
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen type = "right";
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen else
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen type = "";
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen last_failed = I_MAX(host->last_network_failure,
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen host->last_protocol_failure);
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen str_printfa(str, "%s\t%u\t%s\t%lu\t",
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen net_ip2addr(&host->ip), host->port, type,
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen (unsigned long)last_failed);
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen if (dir->self_host == host)
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen doveadm_director_append_status(dir, str);
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen else
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen doveadm_director_host_append_status(dir, host, str);
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen str_append_c(str, '\n');
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen str_append_c(str, '\n');
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(conn->output, str_data(str), str_len(str));
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainenstatic enum doveadm_director_cmd_ret
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_director_add(struct doveadm_connection *conn,
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen const char *const *args)
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen{
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen struct director_host *host;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen struct ip_addr ip;
009217abb57a24a4076092e8e4e165545747839eStephan Bosch in_port_t port = conn->dir->self_port;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen if (args[0] == NULL ||
49ec317299dedfbc27be79ab97d5b7a8ba7a4eacTimo Sirainen net_addr2ip(args[0], &ip) < 0 ||
009217abb57a24a4076092e8e4e165545747839eStephan Bosch (args[1] != NULL && net_str2port(args[1], &port) < 0)) {
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen i_error("doveadm sent invalid DIRECTOR-ADD parameters");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_FAIL;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen }
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen if (director_host_lookup(conn->dir, &ip, port) == NULL) {
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen host = director_host_add(conn->dir, &ip, port);
027f58ea63a1822bbf13d99ee5572e5f8b9e8d8bTimo Sirainen director_notify_ring_added(host, conn->dir->self_host, TRUE);
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen }
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(conn->output, "OK\n", 3);
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen}
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainenstatic enum doveadm_director_cmd_ret
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_director_remove(struct doveadm_connection *conn,
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen const char *const *args)
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen{
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen struct director_host *host;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen struct ip_addr ip;
009217abb57a24a4076092e8e4e165545747839eStephan Bosch in_port_t port = 0;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen if (args[0] == NULL ||
49ec317299dedfbc27be79ab97d5b7a8ba7a4eacTimo Sirainen net_addr2ip(args[0], &ip) < 0 ||
009217abb57a24a4076092e8e4e165545747839eStephan Bosch (args[1] != NULL && net_str2port(args[1], &port) < 0)) {
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen i_error("doveadm sent invalid DIRECTOR-REMOVE parameters");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_FAIL;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen }
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen host = port != 0 ?
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen director_host_lookup(conn->dir, &ip, port) :
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen director_host_lookup_ip(conn->dir, &ip);
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen if (host == NULL)
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
8913a7f43959c7d5e8692584fe056d420cc2f9e0Timo Sirainen else
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen director_ring_remove(host, conn->dir->self_host);
30089b563dd385f9b18835af2c5a47de2b560660Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_RING_SYNC_OK;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen}
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainenstatic enum doveadm_director_cmd_ret
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_host_set_or_update(struct doveadm_connection *conn,
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen const char *const *args, bool update)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen struct director *dir = conn->dir;
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen const char *ip_str, *tag = "";
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct mail_host *host;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct ip_addr ip;
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen unsigned int vhost_count = UINT_MAX;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen ip_str = args[0];
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen if (ip_str != NULL) {
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen tag = strchr(ip_str, '@');
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen if (tag == NULL)
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen tag = "";
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen else
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen ip_str = t_strdup_until(ip_str, tag++);
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen }
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen if (ip_str == NULL || net_addr2ip(ip_str, &ip) < 0 ||
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen (args[1] != NULL && str_to_uint(args[1], &vhost_count) < 0) ||
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen (args[1] == NULL && update)) {
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen i_error("doveadm sent invalid %s parameters",
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen update ? "HOST-UPDATE" : "HOST-SET");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_FAIL;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen if (vhost_count > MAX_VALID_VHOST_COUNT && vhost_count != UINT_MAX) {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(conn->output, "vhost count too large\n");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen host = mail_host_lookup(dir->mail_hosts, &ip);
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen if (host == NULL) {
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen if (update) {
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen }
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen host = mail_host_add_ip(dir->mail_hosts, &ip, tag);
9058f3006fffd25835ad701e1b2c3c8faafd3c80Timo Sirainen } else if (tag[0] != '\0' && strcmp(mail_host_get_tag(host), tag) != 0) {
9058f3006fffd25835ad701e1b2c3c8faafd3c80Timo Sirainen o_stream_nsend_str(conn->output, "host tag can't be changed\n");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
28789c7ce1aa66ab21798bfb73ec64308b9a4de8Timo Sirainen } else if (host->desynced) {
28789c7ce1aa66ab21798bfb73ec64308b9a4de8Timo Sirainen o_stream_nsend_str(conn->output,
28789c7ce1aa66ab21798bfb73ec64308b9a4de8Timo Sirainen "host is already being updated - try again later\n");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen }
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen if (vhost_count != UINT_MAX)
b3abfd0ac256ffa0cbfd74c3793eac4e83d41f78Martti Rannanjärvi mail_host_set_vhost_count(host, vhost_count, "doveadm: ");
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen /* NOTE: we don't support changing a tag for an existing host.
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen it needs to be removed first. otherwise it would be a bit ugly to
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen handle. */
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_update_host(dir, dir->self_host, NULL, host);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_RING_SYNC_OK;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainenstatic enum doveadm_director_cmd_ret
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_host_set(struct doveadm_connection *conn, const char *const *args)
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen{
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen return doveadm_cmd_host_set_or_update(conn, args, FALSE);
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen}
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainenstatic enum doveadm_director_cmd_ret
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_host_update(struct doveadm_connection *conn, const char *const *args)
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen{
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen return doveadm_cmd_host_set_or_update(conn, args, TRUE);
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen}
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainenstatic enum doveadm_director_cmd_ret
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainendoveadm_cmd_host_updown(struct doveadm_connection *conn, bool down,
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen const char *const *args)
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen{
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen struct mail_host *host;
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen struct ip_addr ip;
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen if (args[0] == NULL || net_addr2ip(args[0], &ip) < 0) {
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen i_error("doveadm sent invalid %s parameters: %s",
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen down ? "HOST-DOWN" : "HOST-UP",
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen args[0] == NULL ? "" : args[0]);
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_FAIL;
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen }
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen host = mail_host_lookup(conn->dir->mail_hosts, &ip);
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen if (host == NULL) {
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen }
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen if (host->down == down) {
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen o_stream_nsend_str(conn->output, "OK\n");
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen } else if (host->desynced) {
28789c7ce1aa66ab21798bfb73ec64308b9a4de8Timo Sirainen o_stream_nsend_str(conn->output,
28789c7ce1aa66ab21798bfb73ec64308b9a4de8Timo Sirainen "host is already being updated - try again later\n");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
28789c7ce1aa66ab21798bfb73ec64308b9a4de8Timo Sirainen } else {
b3abfd0ac256ffa0cbfd74c3793eac4e83d41f78Martti Rannanjärvi mail_host_set_down(host, down, ioloop_time, "doveadm: ");
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen director_update_host(conn->dir, conn->dir->self_host,
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen NULL, host);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_RING_SYNC_OK;
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen }
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen}
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainenstatic enum doveadm_director_cmd_ret
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainendoveadm_cmd_host_up(struct doveadm_connection *conn,
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen const char *const *args)
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen{
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen return doveadm_cmd_host_updown(conn, FALSE, args);
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen}
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainenstatic enum doveadm_director_cmd_ret
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainendoveadm_cmd_host_down(struct doveadm_connection *conn,
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen const char *const *args)
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen{
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen return doveadm_cmd_host_updown(conn, TRUE, args);
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen}
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainenstatic enum doveadm_director_cmd_ret
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_host_remove(struct doveadm_connection *conn,
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen const char *const *args)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct mail_host *host;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct ip_addr ip;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen if (args[0] == NULL || net_addr2ip(args[0], &ip) < 0) {
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen i_error("doveadm sent invalid HOST-REMOVE parameters");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_FAIL;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen host = mail_host_lookup(conn->dir->mail_hosts, &ip);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen if (host == NULL) {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen } else {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_remove_host(conn->dir, conn->dir->self_host,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen NULL, host);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_RING_SYNC_OK;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainenstatic void
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainendoveadm_cmd_host_flush_all(struct doveadm_connection *conn)
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen{
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen struct mail_host *const *hostp;
9ffd3c8ca82bd2af8ca4f7e167339820ddcf1fe3Timo Sirainen unsigned int total_user_count = 0;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen array_foreach(mail_hosts_get(conn->dir->mail_hosts), hostp) {
9ffd3c8ca82bd2af8ca4f7e167339820ddcf1fe3Timo Sirainen total_user_count += (*hostp)->user_count;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_flush_host(conn->dir, conn->dir->self_host,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen NULL, *hostp);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen }
9ffd3c8ca82bd2af8ca4f7e167339820ddcf1fe3Timo Sirainen i_warning("Flushed all backend hosts with %u users. This is an unsafe "
9ffd3c8ca82bd2af8ca4f7e167339820ddcf1fe3Timo Sirainen "operation and may cause the same users to end up in multiple backends.",
9ffd3c8ca82bd2af8ca4f7e167339820ddcf1fe3Timo Sirainen total_user_count);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(conn->output, "OK\n", 3);
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen}
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainenstatic enum doveadm_director_cmd_ret
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_host_flush(struct doveadm_connection *conn, const char *const *args)
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen{
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen struct mail_host *host;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen struct ip_addr ip;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen if (args[0] == NULL || args[0][0] == '\0') {
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen doveadm_cmd_host_flush_all(conn);
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen }
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen if (net_addr2ip(args[0], &ip) < 0) {
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen i_error("doveadm sent invalid HOST-FLUSH parameters");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_FAIL;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen }
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen host = mail_host_lookup(conn->dir->mail_hosts, &ip);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen if (host == NULL) {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen } else {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_flush_host(conn->dir, conn->dir->self_host,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen NULL, host);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_RING_SYNC_OK;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen }
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen}
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainenstatic void doveadm_reset_cmd_free(struct director_reset_cmd *cmd)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen{
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen DLLIST_REMOVE(&reset_cmds, cmd);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (cmd->iter != NULL)
b44033e45e9f48f8a6e1ac5905234fec5de6d6ccAki Tuomi director_iterate_users_deinit(&cmd->iter);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (cmd->_conn != NULL)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen cmd->_conn->reset_cmd = NULL;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen i_free(cmd);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen}
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainenstatic bool
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainendirector_host_reset_users(struct director_reset_cmd *cmd,
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen struct mail_host *host)
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen{
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen struct director *dir = cmd->dir;
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen struct user *user;
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen struct mail_host *new_host;
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (dir->users_moving_count >= cmd->max_moving_users)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen return FALSE;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen if (dir->right != NULL)
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen director_connection_cork(dir->right);
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen
6c76bcb36f50843dac534fc6aceabe952509e580Timo Sirainen if (cmd->iter == NULL) {
1f7f4294207557edf83171642ef62ce4922ffc9dTimo Sirainen cmd->iter = director_iterate_users_init(dir);
6c76bcb36f50843dac534fc6aceabe952509e580Timo Sirainen cmd->users_killed = FALSE;
6c76bcb36f50843dac534fc6aceabe952509e580Timo Sirainen }
b44033e45e9f48f8a6e1ac5905234fec5de6d6ccAki Tuomi
b44033e45e9f48f8a6e1ac5905234fec5de6d6ccAki Tuomi while ((user = director_iterate_users_next(cmd->iter)) != NULL) {
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen if (user->host != host)
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen continue;
f5d82a4b87a9b17894e1869cfe8b1a90afbced59Timo Sirainen
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen new_host = mail_host_get_by_hash(dir->mail_hosts,
093b42b11c1236a687d3da564b26a324e2189ae6Timo Sirainen user->username_hash,
093b42b11c1236a687d3da564b26a324e2189ae6Timo Sirainen mail_host_get_tag(host));
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen if (new_host != host) T_BEGIN {
f5d82a4b87a9b17894e1869cfe8b1a90afbced59Timo Sirainen if (new_host != NULL) {
f5d82a4b87a9b17894e1869cfe8b1a90afbced59Timo Sirainen director_move_user(dir, dir->self_host, NULL,
f5d82a4b87a9b17894e1869cfe8b1a90afbced59Timo Sirainen user->username_hash, new_host);
f5d82a4b87a9b17894e1869cfe8b1a90afbced59Timo Sirainen } else {
f5d82a4b87a9b17894e1869cfe8b1a90afbced59Timo Sirainen /* there are no more available backends.
f5d82a4b87a9b17894e1869cfe8b1a90afbced59Timo Sirainen kick the user instead. */
f5d82a4b87a9b17894e1869cfe8b1a90afbced59Timo Sirainen director_kill_user(dir, dir->self_host, user,
ce8d63810932f48176304ed08cd8b7652c4a8addTimo Sirainen user->host->tag, user->host,
ce8d63810932f48176304ed08cd8b7652c4a8addTimo Sirainen TRUE);
6c76bcb36f50843dac534fc6aceabe952509e580Timo Sirainen cmd->users_killed = TRUE;
f5d82a4b87a9b17894e1869cfe8b1a90afbced59Timo Sirainen }
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen } T_END;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (dir->users_moving_count >= cmd->max_moving_users)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen break;
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen }
6c76bcb36f50843dac534fc6aceabe952509e580Timo Sirainen if (user == NULL) {
1f7f4294207557edf83171642ef62ce4922ffc9dTimo Sirainen director_iterate_users_deinit(&cmd->iter);
6c76bcb36f50843dac534fc6aceabe952509e580Timo Sirainen if (cmd->users_killed) {
6c76bcb36f50843dac534fc6aceabe952509e580Timo Sirainen /* no more backends. we already sent kills. now remove
6c76bcb36f50843dac534fc6aceabe952509e580Timo Sirainen the users entirely from the host. */
6c76bcb36f50843dac534fc6aceabe952509e580Timo Sirainen director_flush_host(dir, dir->self_host, NULL, host);
6c76bcb36f50843dac534fc6aceabe952509e580Timo Sirainen }
f5d82a4b87a9b17894e1869cfe8b1a90afbced59Timo Sirainen }
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen if (dir->right != NULL)
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen director_connection_uncork(dir->right);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen return user == NULL;
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen}
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainenstatic bool
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainendirector_reset_cmd_run(struct director_reset_cmd *cmd)
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen{
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen struct mail_host *const *hosts;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen unsigned int count;
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen hosts = array_get(mail_hosts_get(cmd->dir->mail_hosts), &count);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (count > cmd->hosts_count)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen count = cmd->hosts_count;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen while (cmd->host_idx < count) {
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (!director_host_reset_users(cmd, hosts[cmd->host_idx]))
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen return FALSE;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen cmd->host_idx++;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen }
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (cmd->_conn != NULL) {
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen struct doveadm_connection *conn = cmd->_conn;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen o_stream_nsend(conn->output, "OK\n", 3);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (conn->io == NULL)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen doveadm_connection_set_io(conn);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen }
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen doveadm_reset_cmd_free(cmd);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen return TRUE;
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen}
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainenstatic enum doveadm_director_cmd_ret
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_host_reset_users(struct doveadm_connection *conn,
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen const char *const *args)
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen{
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen struct director_reset_cmd *cmd;
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen struct ip_addr ip;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen struct mail_host *const *hosts;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen unsigned int i = 0, count;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen unsigned int max_moving_users = DEFAULT_MAX_MOVING_USERS;
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (args[0] != NULL && args[1] != NULL &&
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen str_to_uint(args[1], &max_moving_users) < 0) {
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen i_error("doveadm sent invalid HOST-RESET-USERS parameters");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_FAIL;
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen }
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen hosts = array_get(mail_hosts_get(conn->dir->mail_hosts), &count);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (args[0] != NULL && args[0][0] != '\0') {
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (net_addr2ip(args[0], &ip) < 0) {
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen i_error("doveadm sent invalid HOST-RESET-USERS ip: %s",
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen args[0]);
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_FAIL;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen }
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen for (i = 0; i < count; i++) {
9954af4b72850a7c3158c99b444d49a529109c4dTimo Sirainen if (net_ip_compare(&hosts[i]->ip, &ip))
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen break;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen }
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (i == count) {
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen }
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen count = i+1;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen }
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen conn->reset_cmd = cmd = i_new(struct director_reset_cmd, 1);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen cmd->dir = conn->dir;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen cmd->_conn = conn;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen cmd->max_moving_users = max_moving_users;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen cmd->host_idx = i;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen cmd->hosts_count = count;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen DLLIST_PREPEND(&reset_cmds, cmd);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (!director_reset_cmd_run(cmd)) {
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen /* we still have work to do. don't handle any more doveadm
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen input until we're finished. */
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen io_remove(&conn->io);
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_UNFINISHED;
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen }
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen}
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainenstatic enum doveadm_director_cmd_ret
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_user_lookup(struct doveadm_connection *conn,
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen const char *const *args)
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen{
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen struct user *user;
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen struct mail_host *host;
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen const char *username, *tag;
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen unsigned int username_hash;
b44033e45e9f48f8a6e1ac5905234fec5de6d6ccAki Tuomi struct mail_tag *mail_tag;
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen string_t *str = t_str_new(256);
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen if (args[0] == NULL) {
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen username = "";
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen tag = "";
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen } else {
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen username = args[0];
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen tag = args[1] != NULL ? args[1] : "";
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen }
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (str_to_uint(username, &username_hash) < 0) {
de92873c366becfaea1554642f89b9169d7955e2Timo Sirainen if (!director_get_username_hash(conn->dir,
de92873c366becfaea1554642f89b9169d7955e2Timo Sirainen username, &username_hash)) {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen o_stream_nsend_str(conn->output, "TRYAGAIN\n");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen }
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen }
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen /* get user's current host */
b44033e45e9f48f8a6e1ac5905234fec5de6d6ccAki Tuomi mail_tag = mail_tag_find(conn->dir->mail_hosts, tag);
b44033e45e9f48f8a6e1ac5905234fec5de6d6ccAki Tuomi user = mail_tag == NULL ? NULL :
b44033e45e9f48f8a6e1ac5905234fec5de6d6ccAki Tuomi user_directory_lookup(mail_tag->users, username_hash);
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen if (user == NULL)
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen str_append(str, "\t0");
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen else {
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen str_printfa(str, "%s\t%u", net_ip2addr(&user->host->ip),
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen user->timestamp +
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen conn->dir->set->director_user_expire);
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen }
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen /* get host if it wasn't in user directory */
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen host = mail_host_get_by_hash(conn->dir->mail_hosts, username_hash, tag);
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen if (host == NULL)
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen str_append(str, "\t");
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen else
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen str_printfa(str, "\t%s", net_ip2addr(&host->ip));
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen /* get host with default configuration */
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen host = mail_host_get_by_hash(conn->dir->orig_config_hosts,
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen username_hash, tag);
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen if (host == NULL)
a99dcacb7cb6e0288f8642483f395f8e4a7aa79cTimo Sirainen str_append(str, "\t\n");
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen else
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen str_printfa(str, "\t%s\n", net_ip2addr(&host->ip));
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(conn->output, str_data(str), str_len(str));
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen}
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainenstatic enum doveadm_director_cmd_ret
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_user_list(struct doveadm_connection *conn, const char *const *args)
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen{
1f7f4294207557edf83171642ef62ce4922ffc9dTimo Sirainen struct director_user_iter *iter;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen struct user *user;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen struct ip_addr ip;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen if (args[0] != NULL && args[0][0] != '\0') {
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen if (net_addr2ip(args[0], &ip) < 0) {
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen i_error("doveadm sent invalid USER-LIST parameters");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_FAIL;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen }
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen } else {
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen ip.family = 0;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen }
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen
1f7f4294207557edf83171642ef62ce4922ffc9dTimo Sirainen iter = director_iterate_users_init(conn->dir);
1f7f4294207557edf83171642ef62ce4922ffc9dTimo Sirainen while ((user = director_iterate_users_next(iter)) != NULL) {
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen if (ip.family == 0 ||
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen net_ip_compare(&ip, &user->host->ip)) T_BEGIN {
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen unsigned int expire_time = user->timestamp +
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen conn->dir->set->director_user_expire;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(conn->output, t_strdup_printf(
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen "%u\t%u\t%s\n",
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen user->username_hash, expire_time,
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen net_ip2addr(&user->host->ip)));
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen } T_END;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen }
1f7f4294207557edf83171642ef62ce4922ffc9dTimo Sirainen director_iterate_users_deinit(&iter);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(conn->output, "\n", 1);
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen}
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainenstatic enum doveadm_director_cmd_ret
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_user_move(struct doveadm_connection *conn, const char *const *args)
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen{
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen unsigned int username_hash;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen struct user *user;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen struct mail_host *host;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen struct ip_addr ip;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen if (args[0] == NULL || args[1] == NULL ||
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen net_addr2ip(args[1], &ip) < 0) {
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen i_error("doveadm sent invalid USER-MOVE parameters");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_FAIL;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen }
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen host = mail_host_lookup(conn->dir->mail_hosts, &ip);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen if (host == NULL) {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen }
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (str_to_uint(args[0], &username_hash) < 0) {
de92873c366becfaea1554642f89b9169d7955e2Timo Sirainen if (!director_get_username_hash(conn->dir,
de92873c366becfaea1554642f89b9169d7955e2Timo Sirainen args[0], &username_hash)) {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen o_stream_nsend_str(conn->output, "TRYAGAIN\n");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen }
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen }
b44033e45e9f48f8a6e1ac5905234fec5de6d6ccAki Tuomi
b44033e45e9f48f8a6e1ac5905234fec5de6d6ccAki Tuomi user = user_directory_lookup(host->tag->users, username_hash);
79ee504bdf920f01e12e28f238799bf2616489dfTimo Sirainen if (user != NULL && USER_IS_BEING_KILLED(user)) {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(conn->output, "TRYAGAIN\n");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen }
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
82641f7aa58d560cc89ec5eb16f03571d6dedcffTimo Sirainen if (user == NULL || user->host != host) {
82641f7aa58d560cc89ec5eb16f03571d6dedcffTimo Sirainen director_move_user(conn->dir, conn->dir->self_host, NULL,
82641f7aa58d560cc89ec5eb16f03571d6dedcffTimo Sirainen username_hash, host);
a35f0649343f41bad5852d3fdca7deb69adb5f15Timo Sirainen } else {
a35f0649343f41bad5852d3fdca7deb69adb5f15Timo Sirainen /* already the correct host. reset the user's timeout. */
a35f0649343f41bad5852d3fdca7deb69adb5f15Timo Sirainen user_directory_refresh(host->tag->users, user);
a35f0649343f41bad5852d3fdca7deb69adb5f15Timo Sirainen director_update_user(conn->dir, conn->dir->self_host, user);
82641f7aa58d560cc89ec5eb16f03571d6dedcffTimo Sirainen }
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(conn->output, "OK\n", 3);
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen}
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainenstatic enum doveadm_director_cmd_ret
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_user_kick(struct doveadm_connection *conn, const char *const *args)
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen{
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen if (args[0] == NULL) {
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen i_error("doveadm sent invalid USER-KICK parameters");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_FAIL;
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen }
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen director_kick_user(conn->dir, conn->dir->self_host, NULL, args[0]);
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen o_stream_nsend(conn->output, "OK\n", 3);
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen}
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainenstatic enum doveadm_director_cmd_ret
365b5a495ae7f6fd20f6a0b0517f6aa3ad4fe1a7Timo Sirainendoveadm_cmd_user_kick_alt(struct doveadm_connection *conn, const char *const *args)
365b5a495ae7f6fd20f6a0b0517f6aa3ad4fe1a7Timo Sirainen{
365b5a495ae7f6fd20f6a0b0517f6aa3ad4fe1a7Timo Sirainen if (str_array_length(args) < 2) {
365b5a495ae7f6fd20f6a0b0517f6aa3ad4fe1a7Timo Sirainen i_error("doveadm sent invalid USER-KICK-ALT parameters");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_FAIL;
365b5a495ae7f6fd20f6a0b0517f6aa3ad4fe1a7Timo Sirainen }
365b5a495ae7f6fd20f6a0b0517f6aa3ad4fe1a7Timo Sirainen
365b5a495ae7f6fd20f6a0b0517f6aa3ad4fe1a7Timo Sirainen director_kick_user_alt(conn->dir, conn->dir->self_host, NULL,
365b5a495ae7f6fd20f6a0b0517f6aa3ad4fe1a7Timo Sirainen args[0], args[1]);
365b5a495ae7f6fd20f6a0b0517f6aa3ad4fe1a7Timo Sirainen o_stream_nsend(conn->output, "OK\n", 3);
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
365b5a495ae7f6fd20f6a0b0517f6aa3ad4fe1a7Timo Sirainen}
365b5a495ae7f6fd20f6a0b0517f6aa3ad4fe1a7Timo Sirainen
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainenstruct {
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen const char *name;
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen enum doveadm_director_cmd_ret (*cmd)
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen (struct doveadm_connection *conn, const char *const *args);
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen enum doveadm_director_cmd_flag flags;
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen} doveadm_director_commands[] = {
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen { "HOST-LIST", doveadm_cmd_host_list, 0 },
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen { "HOST-LIST-REMOVED", doveadm_cmd_host_list_removed, 0 },
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen { "DIRECTOR-LIST", doveadm_cmd_director_list, 0 },
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen { "DIRECTOR-ADD", doveadm_cmd_director_add, DOVEADM_DIRECTOR_CMD_FLAG_PRE_RING_SYNC },
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen { "DIRECTOR-REMOVE", doveadm_cmd_director_remove, DOVEADM_DIRECTOR_CMD_FLAG_PRE_RING_SYNC },
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen { "HOST-SET", doveadm_cmd_host_set, DOVEADM_DIRECTOR_CMD_FLAG_PRE_RING_SYNC },
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen { "HOST-UPDATE", doveadm_cmd_host_update, DOVEADM_DIRECTOR_CMD_FLAG_PRE_RING_SYNC },
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen { "HOST-UP", doveadm_cmd_host_up, DOVEADM_DIRECTOR_CMD_FLAG_PRE_RING_SYNC },
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen { "HOST-DOWN", doveadm_cmd_host_down, DOVEADM_DIRECTOR_CMD_FLAG_PRE_RING_SYNC },
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen { "HOST-REMOVE", doveadm_cmd_host_remove, DOVEADM_DIRECTOR_CMD_FLAG_PRE_RING_SYNC },
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen { "HOST-FLUSH", doveadm_cmd_host_flush, DOVEADM_DIRECTOR_CMD_FLAG_PRE_RING_SYNC },
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen { "HOST-RESET-USERS", doveadm_cmd_host_reset_users, 0 },
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen { "USER-LOOKUP", doveadm_cmd_user_lookup, 0 },
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen { "USER-LIST", doveadm_cmd_user_list, 0 },
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen { "USER-MOVE", doveadm_cmd_user_move, 0 },
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen { "USER-KICK", doveadm_cmd_user_kick, 0 },
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen { "USER-KICK-ALT", doveadm_cmd_user_kick_alt, 0 },
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen};
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainenstatic void
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainendoveadm_connection_ring_sync_timeout(struct doveadm_connection *conn)
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen{
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen doveadm_connection_ring_sync_list_move(conn);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen o_stream_nsend_str(conn->output, "Ring sync timed out\n");
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen doveadm_connection_set_io(conn);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen io_set_pending(conn->io);
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen i_free_and_null(conn->cmd_pending_args);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen}
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainenstatic void
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainendoveadm_connection_set_ring_sync_callback(struct doveadm_connection *conn,
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen doveadm_connection_ring_sync_callback_t *callback)
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen{
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen i_assert(conn->ring_sync_callback == NULL);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen i_assert(conn->to_ring_sync_abort == NULL);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen conn->ring_sync_callback = callback;
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen io_remove(&conn->io);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen DLLIST_REMOVE(&doveadm_connections, conn);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen DLLIST_PREPEND(&doveadm_ring_sync_pending_connections, conn);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen conn->to_ring_sync_abort =
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen timeout_add(DOVEADM_CONNECTION_RING_SYNC_TIMEOUT_MSECS,
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen doveadm_connection_ring_sync_timeout, conn);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen}
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainenstatic void doveadm_connection_ret_ok(struct doveadm_connection *conn)
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen{
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen o_stream_nsend(conn->output, "OK\n", 3);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen}
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainenstatic enum doveadm_director_cmd_ret
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainendoveadm_connection_cmd_run(struct doveadm_connection *conn,
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen const char *const *args, unsigned int i)
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen{
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen enum doveadm_director_cmd_ret ret;
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen if ((doveadm_director_commands[i].flags &
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen DOVEADM_DIRECTOR_CMD_FLAG_PRE_RING_SYNC) != 0 &&
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen !conn->dir->ring_synced) {
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen /* wait for ring to be synced before running the command */
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen conn->cmd_pending_args = p_strarray_dup(default_pool, args);
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen conn->cmd_pending_idx = i;
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen doveadm_connection_set_ring_sync_callback(conn,
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen doveadm_connection_cmd_run_synced);
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_UNFINISHED;
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen }
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen ret = doveadm_director_commands[i].cmd(conn, args);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen if (ret != DOVEADM_DIRECTOR_CMD_RET_RING_SYNC_OK)
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen return ret;
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen /* Delay sending OK until ring is synced. This way doveadm will know
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen whether the call actually succeeded or not. */
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen if (conn->dir->ring_synced) {
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen /* director is alone */
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen i_assert(conn->dir->right == NULL && conn->dir->left == NULL);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen o_stream_nsend(conn->output, "OK\n", 3);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_OK;
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen }
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen doveadm_connection_set_ring_sync_callback(conn, doveadm_connection_ret_ok);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_RING_SYNC_OK;
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen}
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainenstatic void doveadm_connection_cmd_run_synced(struct doveadm_connection *conn)
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen{
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen const char **args = conn->cmd_pending_args;
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen conn->cmd_pending_args = NULL;
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen (void)doveadm_connection_cmd_run(conn, args, conn->cmd_pending_idx);
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen i_free(args);
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen}
02e78eb1e4fbe13d0bd815d3d3fc7200f88a1fc4Timo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainenstatic enum doveadm_director_cmd_ret
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainendoveadm_connection_cmd(struct doveadm_connection *conn, const char *line)
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen{
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen const char *cmd, *const *args;
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen args = t_strsplit_tabescaped(line);
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen if (args[0] == NULL) {
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen i_error("doveadm sent empty command line");
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_FAIL;
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen }
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen cmd = args[0];
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen args++;
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen for (unsigned int i = 0; i < N_ELEMENTS(doveadm_director_commands); i++) {
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen if (strcmp(doveadm_director_commands[i].name, cmd) == 0)
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen return doveadm_connection_cmd_run(conn, args, i);
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen }
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen i_error("doveadm sent unknown command: %s", line);
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen return DOVEADM_DIRECTOR_CMD_RET_FAIL;
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen}
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic void doveadm_connection_input(struct doveadm_connection *conn)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen const char *line;
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen enum doveadm_director_cmd_ret ret = DOVEADM_DIRECTOR_CMD_RET_OK;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (!conn->handshaked) {
d2cadbf5445156fc12988506279d51d0e53b0449Timo Sirainen if ((line = i_stream_read_next_line(conn->input)) == NULL) {
d2cadbf5445156fc12988506279d51d0e53b0449Timo Sirainen if (conn->input->eof || conn->input->stream_errno != 0)
d2cadbf5445156fc12988506279d51d0e53b0449Timo Sirainen doveadm_connection_deinit(&conn);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return;
d2cadbf5445156fc12988506279d51d0e53b0449Timo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen if (!version_string_verify(line, "director-doveadm",
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen DOVEADM_PROTOCOL_VERSION_MAJOR)) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_error("doveadm not compatible with this server "
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen "(mixed old and new binaries?)");
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen doveadm_connection_deinit(&conn);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen conn->handshaked = TRUE;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen while ((line = i_stream_read_next_line(conn->input)) != NULL &&
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen ret == DOVEADM_DIRECTOR_CMD_RET_OK) {
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen T_BEGIN {
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen ret = doveadm_connection_cmd(conn, line);
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen } T_END;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen if (conn->input->eof || conn->input->stream_errno != 0 ||
6f5310d61cb7235ae5b3f42a3cd27605ace770c4Timo Sirainen ret == DOVEADM_DIRECTOR_CMD_RET_FAIL)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen doveadm_connection_deinit(&conn);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainenstatic void doveadm_connection_set_io(struct doveadm_connection *conn)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen{
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen conn->io = io_add(conn->fd, IO_READ, doveadm_connection_input, conn);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen}
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstruct doveadm_connection *
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainendoveadm_connection_init(struct director *dir, int fd)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct doveadm_connection *conn;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen conn = i_new(struct doveadm_connection, 1);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen conn->fd = fd;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen conn->dir = dir;
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi conn->input = i_stream_create_fd(conn->fd, 1024);
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi conn->output = o_stream_create_fd(conn->fd, (size_t)-1);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_set_no_error_handling(conn->output, TRUE);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen doveadm_connection_set_io(conn);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(conn->output, DOVEADM_HANDSHAKE);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen DLLIST_PREPEND(&doveadm_connections, conn);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return conn;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic void doveadm_connection_deinit(struct doveadm_connection **_conn)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct doveadm_connection *conn = *_conn;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen *_conn = NULL;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen i_assert(conn->to_ring_sync_abort == NULL);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (conn->reset_cmd != NULL) {
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen /* finish the move even if doveadm disconnected */
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen conn->reset_cmd->_conn = NULL;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen }
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen DLLIST_REMOVE(&doveadm_connections, conn);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen io_remove(&conn->io);
bcbca4b66800f0fbfe2643a86d5a6b63d752454dTimo Sirainen i_stream_unref(&conn->input);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen o_stream_unref(&conn->output);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (close(conn->fd) < 0)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_error("close(doveadm connection) failed: %m");
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_free(conn);
9522aa5f33cc37fe8ccd0d647cc51dd3ba6a9b55Timo Sirainen
9522aa5f33cc37fe8ccd0d647cc51dd3ba6a9b55Timo Sirainen master_service_client_connection_destroyed(master_service);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainenstatic void
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainendoveadm_connection_ring_sync_list_move(struct doveadm_connection *conn)
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen{
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen timeout_remove(&conn->to_ring_sync_abort);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen DLLIST_REMOVE(&doveadm_ring_sync_pending_connections, conn);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen DLLIST_PREPEND(&doveadm_connections, conn);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen}
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenvoid doveadm_connections_deinit(void)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen while (reset_cmds != NULL)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen doveadm_reset_cmd_free(reset_cmds);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen unsigned int pending_count = 0;
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen while (doveadm_ring_sync_pending_connections != NULL) {
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen doveadm_connection_ring_sync_list_move(doveadm_ring_sync_pending_connections);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen pending_count++;
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen }
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen if (pending_count > 0)
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen i_warning("Shutting down while %u doveadm connections were waiting for ring sync", pending_count);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen while (doveadm_connections != NULL) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct doveadm_connection *conn = doveadm_connections;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen doveadm_connection_deinit(&conn);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainenstatic void doveadm_connections_continue_reset_cmds(void)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen{
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen while (reset_cmds != NULL) {
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (!director_reset_cmd_run(reset_cmds))
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen break;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen }
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen}
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainenvoid doveadm_connections_ring_synced(void)
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen{
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen while (doveadm_ring_sync_pending_connections != NULL) {
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen struct doveadm_connection *conn =
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen doveadm_ring_sync_pending_connections;
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen doveadm_connection_ring_sync_callback_t *callback =
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen conn->ring_sync_callback;
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen conn->ring_sync_callback = NULL;
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen doveadm_connection_ring_sync_list_move(conn);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen doveadm_connection_set_io(conn);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen io_set_pending(conn->io);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen callback(conn);
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen }
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen doveadm_connections_continue_reset_cmds();
6ecc5475f7efd4dcdf4ce727191693de24c5cf51Timo Sirainen}