doveadm-connection.c revision 892e25e1c0caad62ced087d9eba2741a59e3d9ce
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2010-2016 Dovecot authors, see the included COPYING file */
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen#define DOVEADM_HANDSHAKE "VERSION\tdirector-doveadm\t1\t0\n"
f6edc54aa72596af8da681c07223108c322712d5Timo Sirainenstatic struct doveadm_connection *doveadm_connections;
f6edc54aa72596af8da681c07223108c322712d5Timo Sirainenstatic void doveadm_connection_deinit(struct doveadm_connection **_conn);
f6edc54aa72596af8da681c07223108c322712d5Timo Sirainenstatic void doveadm_cmd_host_list(struct doveadm_connection *conn)
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen array_foreach(mail_hosts_get(conn->dir->mail_hosts), hostp) {
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen net_ip2addr(&(*hostp)->ip), (*hostp)->vhost_count,
f6edc54aa72596af8da681c07223108c322712d5Timo Sirainen str_append_tabescaped(str, mail_host_get_tag(*hostp));
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen str_printfa(str, "\t%c\t%ld", (*hostp)->down ? 'D' : 'U',
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen o_stream_nsend(conn->output, str_data(str), str_len(str));
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainenstatic void doveadm_cmd_host_list_removed(struct doveadm_connection *conn)
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen struct mail_host *const *orig_hosts, *const *cur_hosts;
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen unsigned int i, j, orig_hosts_count, cur_hosts_count;
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen orig_hosts_list = mail_hosts_init(conn->dir->set->director_consistent_hashing);
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen (void)mail_hosts_parse_and_add(orig_hosts_list,
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen orig_hosts = array_get(mail_hosts_get(orig_hosts_list),
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen cur_hosts = array_get(mail_hosts_get(conn->dir->mail_hosts),
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen /* the hosts are sorted by IP */
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen for (i = j = 0; i < orig_hosts_count && j < cur_hosts_count; ) {
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen ret = net_ip_cmp(&orig_hosts[i]->ip, &cur_hosts[j]->ip);
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen else if (ret > 0)
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen for (; i < orig_hosts_count; i++)
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen str_printfa(str, "%s\n", net_ip2addr(&orig_hosts[i]->ip));
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen o_stream_nsend(conn->output, str_data(str), str_len(str));
c0e5c6a86e1de5d4f5591d39b4aa921a23c807d7Timo Sirainenstatic void doveadm_director_append_status(struct director *dir, string_t *str)
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen str_printfa(str, "syncing - last sync %d secs ago",
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen (int)(ioloop_time - dir->ring_last_sync_time));
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainendoveadm_director_connection_append_status(struct director_connection *conn,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainendoveadm_director_host_append_status(struct director *dir,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen director_connection_get_host(dir->left) == host)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen director_connection_get_host(dir->right) == host)
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen /* we might have a connection that is being connected */
f6edc54aa72596af8da681c07223108c322712d5Timo Sirainen if (director_connection_get_host(*connp) == host) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen doveadm_director_connection_append_status(conn, str);
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainenstatic void doveadm_cmd_director_list(struct doveadm_connection *conn)
9cd232cda7563ad81c01776e5ebc5ed2b3cef898Timo Sirainen director_connection_get_host(dir->left) == host;
9cd232cda7563ad81c01776e5ebc5ed2b3cef898Timo Sirainen director_connection_get_host(dir->right) == host;
9cd232cda7563ad81c01776e5ebc5ed2b3cef898Timo Sirainen last_failed = I_MAX(host->last_network_failure,
9cd232cda7563ad81c01776e5ebc5ed2b3cef898Timo Sirainen (unsigned long)last_failed);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen doveadm_director_host_append_status(dir, host, str);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen o_stream_nsend(conn->output, str_data(str), str_len(str));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainendoveadm_cmd_director_add(struct doveadm_connection *conn,
f7f13e206c9839f6e868088034b0b59d1d9be13aTimo Sirainen const char *const *args)
dadd250347d90d90bd65f529d45b50f79d6a0674Timo Sirainen (args[1] != NULL && net_str2port(args[1], &port) < 0)) {
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen i_error("doveadm sent invalid DIRECTOR-ADD parameters");
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen if (director_host_lookup(conn->dir, &ip, port) == NULL) {
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen host = director_host_add(conn->dir, &ip, port);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen director_notify_ring_added(host, conn->dir->self_host);
f7f13e206c9839f6e868088034b0b59d1d9be13aTimo Sirainendoveadm_cmd_director_remove(struct doveadm_connection *conn,
f7f13e206c9839f6e868088034b0b59d1d9be13aTimo Sirainen const char *const *args)
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen (args[1] != NULL && net_str2port(args[1], &port) < 0)) {
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen i_error("doveadm sent invalid DIRECTOR-REMOVE parameters");
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
f7f13e206c9839f6e868088034b0b59d1d9be13aTimo Sirainen director_ring_remove(host, conn->dir->self_host);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainendoveadm_cmd_host_set_or_update(struct doveadm_connection *conn,
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen if (ip_str == NULL || net_addr2ip(ip_str, &ip) < 0 ||
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen (args[1] != NULL && str_to_uint(args[1], &vhost_count) < 0) ||
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen if (vhost_count > MAX_VALID_VHOST_COUNT && vhost_count != UINT_MAX) {
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen o_stream_nsend_str(conn->output, "vhost count too large\n");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen host = mail_host_lookup(dir->mail_hosts, &ip);
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen host = mail_host_add_ip(dir->mail_hosts, &ip, tag);
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen } else if (tag[0] != '\0' && strcmp(mail_host_get_tag(host), tag) != 0) {
b2ed2b25c4c457ec1c99ebe5e9bd66a2e2f89cfdTimo Sirainen o_stream_nsend_str(conn->output, "host tag can't be changed\n");
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen "host is already being updated - try again later\n");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* NOTE: we don't support changing a tag for an existing host.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen it needs to be removed first. otherwise it would be a bit ugly to
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen director_update_host(dir, dir->self_host, NULL, host);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainendoveadm_cmd_host_set(struct doveadm_connection *conn, const char *const *args)
b2ed2b25c4c457ec1c99ebe5e9bd66a2e2f89cfdTimo Sirainen return doveadm_cmd_host_set_or_update(conn, args, FALSE);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainendoveadm_cmd_host_update(struct doveadm_connection *conn, const char *const *args)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen return doveadm_cmd_host_set_or_update(conn, args, TRUE);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainendoveadm_cmd_host_updown(struct doveadm_connection *conn, bool down,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen const char *const *args)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (args[0] == NULL || net_addr2ip(args[0], &ip) < 0) {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen i_error("doveadm sent invalid %s parameters: %s",
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen host = mail_host_lookup(conn->dir->mail_hosts, &ip);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen "host is already being updated - try again later\n");
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen director_update_host(conn->dir, conn->dir->self_host,
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainendoveadm_cmd_host_remove(struct doveadm_connection *conn,
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen const char *const *args)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (args[0] == NULL || net_addr2ip(args[0], &ip) < 0) {
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen i_error("doveadm sent invalid HOST-REMOVE parameters");
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen host = mail_host_lookup(conn->dir->mail_hosts, &ip);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen director_remove_host(conn->dir, conn->dir->self_host,
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainendoveadm_cmd_host_flush_all(struct doveadm_connection *conn)
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen unsigned int total_user_count = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen array_foreach(mail_hosts_get(conn->dir->mail_hosts), hostp) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen director_flush_host(conn->dir, conn->dir->self_host,
dc07b75b7ea83ff5f447970a20419032725271a7Timo Sirainen i_warning("Flushed all backend hosts with %u users. This is an unsafe "
dc07b75b7ea83ff5f447970a20419032725271a7Timo Sirainen "operation and may cause the same users to end up in multiple backends.",
dc07b75b7ea83ff5f447970a20419032725271a7Timo Sirainendoveadm_cmd_host_flush(struct doveadm_connection *conn, const char *const *args)
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen i_error("doveadm sent invalid HOST-FLUSH parameters");
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen host = mail_host_lookup(conn->dir->mail_hosts, &ip);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen director_flush_host(conn->dir, conn->dir->self_host,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainendirector_host_reset_users(struct director *dir, struct director_host *src,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen while ((user = user_directory_iter_next(iter)) != NULL) {
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen new_host = mail_host_get_by_hash(dir->mail_hosts,
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainendoveadm_cmd_host_reset_users_all(struct doveadm_connection *conn)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen array_foreach(mail_hosts_get(conn->dir->mail_hosts), hostp)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen director_host_reset_users(conn->dir, conn->dir->self_host, *hostp);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainendoveadm_cmd_host_reset_users(struct doveadm_connection *conn,
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen const char *const *args)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_error("doveadm sent invalid HOST-RESET-USERS parameters");
2b2e5f7a24c24d971351877ad4c5150662856bfbTimo Sirainen host = mail_host_lookup(conn->dir->mail_hosts, &ip);
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
57dc3cb5d5e315272353abf55f702eefc084db26Timo Sirainen director_host_reset_users(conn->dir, conn->dir->self_host, host);
2b2e5f7a24c24d971351877ad4c5150662856bfbTimo Sirainendoveadm_cmd_user_lookup(struct doveadm_connection *conn,
2b2e5f7a24c24d971351877ad4c5150662856bfbTimo Sirainen const char *const *args)
} T_END;
unsigned int username_hash;
args++;
return ret;
const char *line;
T_BEGIN {
} T_END;
struct doveadm_connection *
return conn;
void doveadm_connections_deinit(void)