doveadm-connection.c revision 79ee504bdf920f01e12e28f238799bf2616489df
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber/* Copyright (c) 2010-2016 Dovecot authors, see the included COPYING file */
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber#define DOVEADM_HANDSHAKE "VERSION\tdirector-doveadm\t1\t0\n"
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graberstatic struct doveadm_connection *doveadm_connections;
e582991fd00734436ad0cc95c42cc3d16fd3d229Stéphane Graberstatic struct director_reset_cmd *reset_cmds = NULL;
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graberstatic void doveadm_connection_set_io(struct doveadm_connection *conn);
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graberstatic void doveadm_connection_deinit(struct doveadm_connection **_conn);
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graberstatic void doveadm_cmd_host_list(struct doveadm_connection *conn)
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber array_foreach(mail_hosts_get(conn->dir->mail_hosts), hostp) {
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber net_ip2addr(&(*hostp)->ip), (*hostp)->vhost_count,
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber str_append_tabescaped(str, mail_host_get_tag(*hostp));
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber str_printfa(str, "\t%c\t%ld", (*hostp)->down ? 'D' : 'U',
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber o_stream_nsend(conn->output, str_data(str), str_len(str));
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graberstatic void doveadm_cmd_host_list_removed(struct doveadm_connection *conn)
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber struct mail_host *const *orig_hosts, *const *cur_hosts;
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber unsigned int i, j, orig_hosts_count, cur_hosts_count;
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber orig_hosts_list = mail_hosts_init(conn->dir->set->director_consistent_hashing);
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber (void)mail_hosts_parse_and_add(orig_hosts_list,
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber orig_hosts = array_get(mail_hosts_get(orig_hosts_list),
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber cur_hosts = array_get(mail_hosts_get(conn->dir->mail_hosts),
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber /* the hosts are sorted by IP */
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber for (i = j = 0; i < orig_hosts_count && j < cur_hosts_count; ) {
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber ret = net_ip_cmp(&orig_hosts[i]->ip, &cur_hosts[j]->ip);
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber else if (ret > 0)
a771fe18d28890cfc545995fb818aa7472744fdeDwight Engen for (; i < orig_hosts_count; i++)
a771fe18d28890cfc545995fb818aa7472744fdeDwight Engen str_printfa(str, "%s\n", net_ip2addr(&orig_hosts[i]->ip));
a771fe18d28890cfc545995fb818aa7472744fdeDwight Engen o_stream_nsend(conn->output, str_data(str), str_len(str));
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graberstatic void doveadm_director_append_status(struct director *dir, string_t *str)
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber str_printfa(str, "syncing - last sync %d secs ago",
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber (int)(ioloop_time - dir->ring_last_sync_time));
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graberdoveadm_director_connection_append_status(struct director_connection *conn,
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber if (!director_connection_is_handshaked(conn))
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber else if (director_connection_is_synced(conn))
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graberdoveadm_director_host_append_status(struct director *dir,
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber director_connection_get_host(dir->left) == host)
e447a8a706cc786257bc755a25e6441a766b0a4dStéphane Graber director_connection_get_host(dir->right) == host)
e447a8a706cc786257bc755a25e6441a766b0a4dStéphane Graber /* we might have a connection that is being connected */
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield if (director_connection_get_host(*connp) == host) {
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield doveadm_director_connection_append_status(conn, str);
e447a8a706cc786257bc755a25e6441a766b0a4dStéphane Graberstatic void doveadm_cmd_director_list(struct doveadm_connection *conn)
e447a8a706cc786257bc755a25e6441a766b0a4dStéphane Graber director_connection_get_host(dir->left) == host;
e582991fd00734436ad0cc95c42cc3d16fd3d229Stéphane Graber director_connection_get_host(dir->right) == host;
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber last_failed = I_MAX(host->last_network_failure,
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield net_ip2addr(&host->ip), host->port, type,
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield (unsigned long)last_failed);
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield doveadm_director_append_status(dir, str);
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield doveadm_director_host_append_status(dir, host, str);
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield o_stream_nsend(conn->output, str_data(str), str_len(str));
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfielddoveadm_cmd_director_add(struct doveadm_connection *conn,
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield const char *const *args)
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield (args[1] != NULL && net_str2port(args[1], &port) < 0)) {
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield i_error("doveadm sent invalid DIRECTOR-ADD parameters");
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield if (director_host_lookup(conn->dir, &ip, port) == NULL) {
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield host = director_host_add(conn->dir, &ip, port);
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield director_notify_ring_added(host, conn->dir->self_host);
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield o_stream_nsend(conn->output, "OK\n", 3);
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfielddoveadm_cmd_director_remove(struct doveadm_connection *conn,
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield const char *const *args)
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield (args[1] != NULL && net_str2port(args[1], &port) < 0)) {
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield i_error("doveadm sent invalid DIRECTOR-REMOVE parameters");
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield director_host_lookup(conn->dir, &ip, port) :
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield director_host_lookup_ip(conn->dir, &ip);
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield o_stream_nsend_str(conn->output, "NOTFOUND\n");
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield director_ring_remove(host, conn->dir->self_host);
015f0dd7924d27aeb2f16bb0c4d243f3fd93e94bMichael H. Warfield o_stream_nsend(conn->output, "OK\n", 3);
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graberdoveadm_cmd_host_set_or_update(struct doveadm_connection *conn,
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber if (ip_str == NULL || net_addr2ip(ip_str, &ip) < 0 ||
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber (args[1] != NULL && str_to_uint(args[1], &vhost_count) < 0) ||
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber i_error("doveadm sent invalid %s parameters",
if (update) {
const char *const *args)
const char *const *args)
unsigned int total_user_count = 0;
return FALSE;
} T_END;
unsigned int count;
return FALSE;
return TRUE;
const char *const *args)
unsigned int i = 0, count;
args[0]);
for (i = 0; i < count; i++) {
if (i == count) {
const char *const *args)
unsigned int username_hash;
} 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)
void doveadm_connections_continue_reset_cmds(void)