doveadm-connection.c revision 892e25e1c0caad62ced087d9eba2741a59e3d9ce
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2010-2016 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define DOVEADM_HANDSHAKE "VERSION\tdirector-doveadm\t1\t0\n"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic struct doveadm_connection *doveadm_connections;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void doveadm_connection_deinit(struct doveadm_connection **_conn);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void doveadm_cmd_host_list(struct doveadm_connection *conn)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen array_foreach(mail_hosts_get(conn->dir->mail_hosts), hostp) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen net_ip2addr(&(*hostp)->ip), (*hostp)->vhost_count,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append_tabescaped(str, mail_host_get_tag(*hostp));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_printfa(str, "\t%c\t%ld", (*hostp)->down ? 'D' : 'U',
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen o_stream_nsend(conn->output, str_data(str), str_len(str));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void doveadm_cmd_host_list_removed(struct doveadm_connection *conn)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_host *const *orig_hosts, *const *cur_hosts;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int i, j, orig_hosts_count, cur_hosts_count;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen orig_hosts_list = mail_hosts_init(conn->dir->set->director_consistent_hashing);
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen (void)mail_hosts_parse_and_add(orig_hosts_list,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen orig_hosts = array_get(mail_hosts_get(orig_hosts_list),
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cur_hosts = array_get(mail_hosts_get(conn->dir->mail_hosts),
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* the hosts are sorted by IP */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = j = 0; i < orig_hosts_count && j < cur_hosts_count; ) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = net_ip_cmp(&orig_hosts[i]->ip, &cur_hosts[j]->ip);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else if (ret > 0)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen for (; i < orig_hosts_count; i++)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen str_printfa(str, "%s\n", net_ip2addr(&orig_hosts[i]->ip));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen o_stream_nsend(conn->output, str_data(str), str_len(str));
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenstatic void doveadm_director_append_status(struct director *dir, string_t *str)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen str_printfa(str, "syncing - last sync %d secs ago",
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen (int)(ioloop_time - dir->ring_last_sync_time));
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainendoveadm_director_connection_append_status(struct director_connection *conn,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainendoveadm_director_host_append_status(struct director *dir,
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen director_connection_get_host(dir->left) == host)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen director_connection_get_host(dir->right) == host)
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen /* we might have a connection that is being connected */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (director_connection_get_host(*connp) == host) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen doveadm_director_connection_append_status(conn, str);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenstatic void doveadm_cmd_director_list(struct doveadm_connection *conn)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen director_connection_get_host(dir->left) == host;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen director_connection_get_host(dir->right) == host;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen last_failed = I_MAX(host->last_network_failure,
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen (unsigned long)last_failed);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen doveadm_director_host_append_status(dir, host, str);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen o_stream_nsend(conn->output, str_data(str), str_len(str));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainendoveadm_cmd_director_add(struct doveadm_connection *conn,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *const *args)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (args[1] != NULL && net_str2port(args[1], &port) < 0)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("doveadm sent invalid DIRECTOR-ADD parameters");
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (director_host_lookup(conn->dir, &ip, port) == NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen host = director_host_add(conn->dir, &ip, port);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen director_notify_ring_added(host, conn->dir->self_host);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainendoveadm_cmd_director_remove(struct doveadm_connection *conn,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *const *args)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (args[1] != NULL && net_str2port(args[1], &port) < 0)) {
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen i_error("doveadm sent invalid DIRECTOR-REMOVE parameters");
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen director_ring_remove(host, conn->dir->self_host);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainendoveadm_cmd_host_set_or_update(struct doveadm_connection *conn,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (ip_str == NULL || net_addr2ip(ip_str, &ip) < 0 ||
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (args[1] != NULL && str_to_uint(args[1], &vhost_count) < 0) ||
ba482d3624ca4f1b3d638e6e8470ba5134f21493Timo Sirainen if (vhost_count > MAX_VALID_VHOST_COUNT && vhost_count != UINT_MAX) {
ba482d3624ca4f1b3d638e6e8470ba5134f21493Timo Sirainen o_stream_nsend_str(conn->output, "vhost count too large\n");
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen host = mail_host_lookup(dir->mail_hosts, &ip);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen host = mail_host_add_ip(dir->mail_hosts, &ip, tag);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen } else if (tag[0] != '\0' && strcmp(mail_host_get_tag(host), tag) != 0) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen o_stream_nsend_str(conn->output, "host tag can't be changed\n");
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen "host is already being updated - try again later\n");
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen /* NOTE: we don't support changing a tag for an existing host.
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen it needs to be removed first. otherwise it would be a bit ugly to
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen director_update_host(dir, dir->self_host, NULL, host);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainendoveadm_cmd_host_set(struct doveadm_connection *conn, const char *const *args)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return doveadm_cmd_host_set_or_update(conn, args, FALSE);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainendoveadm_cmd_host_update(struct doveadm_connection *conn, const char *const *args)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return doveadm_cmd_host_set_or_update(conn, args, TRUE);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainendoveadm_cmd_host_updown(struct doveadm_connection *conn, bool down,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen const char *const *args)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (args[0] == NULL || net_addr2ip(args[0], &ip) < 0) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_error("doveadm sent invalid %s parameters: %s",
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen host = mail_host_lookup(conn->dir->mail_hosts, &ip);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen "host is already being updated - try again later\n");
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen director_update_host(conn->dir, conn->dir->self_host,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainendoveadm_cmd_host_remove(struct doveadm_connection *conn,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *const *args)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (args[0] == NULL || net_addr2ip(args[0], &ip) < 0) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_error("doveadm sent invalid HOST-REMOVE parameters");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen host = mail_host_lookup(conn->dir->mail_hosts, &ip);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen director_remove_host(conn->dir, conn->dir->self_host,
unsigned int total_user_count = 0;
} T_END;
const char *const *args)
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)