doveadm-connection.c revision 68f7668b9315dd6c9e3d61c04d6da08e1ac3624f
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2010-2017 Dovecot authors, see the included COPYING file */
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen#define DOVEADM_HANDSHAKE "VERSION\tdirector-doveadm\t1\t0\n"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic struct doveadm_connection *doveadm_connections;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainenstatic struct director_reset_cmd *reset_cmds = NULL;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainenstatic void doveadm_connection_set_io(struct doveadm_connection *conn);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic void doveadm_connection_deinit(struct doveadm_connection **_conn);
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainenstatic int doveadm_cmd_host_list(struct doveadm_connection *conn,
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen array_foreach(mail_hosts_get(conn->dir->mail_hosts), hostp) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen net_ip2addr(&(*hostp)->ip), (*hostp)->vhost_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',
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(conn->output, str_data(str), str_len(str));
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainenstatic int doveadm_cmd_host_list_removed(struct doveadm_connection *conn,
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen struct mail_host *const *orig_hosts, *const *cur_hosts;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen unsigned int i, j, orig_hosts_count, cur_hosts_count;
b44033e45e9f48f8a6e1ac5905234fec5de6d6ccAki Tuomi orig_hosts_list = mail_hosts_init(conn->dir->set->director_user_expire,
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen (void)mail_hosts_parse_and_add(orig_hosts_list,
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen orig_hosts = array_get(mail_hosts_get(orig_hosts_list),
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen cur_hosts = array_get(mail_hosts_get(conn->dir->mail_hosts),
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 else if (ret > 0)
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen for (; i < orig_hosts_count; i++)
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen str_printfa(str, "%s\n", net_ip2addr(&orig_hosts[i]->ip));
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(conn->output, str_data(str), str_len(str));
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainenstatic void doveadm_director_append_status(struct director *dir, string_t *str)
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen str_printfa(str, "syncing - last sync %d secs ago",
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen (int)(ioloop_time - dir->ring_last_sync_time));
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainendoveadm_director_connection_append_status(struct director_connection *conn,
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainendoveadm_director_host_append_status(struct director *dir,
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen director_connection_get_host(dir->left) == host)
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen director_connection_get_host(dir->right) == host)
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen /* we might have a connection that is being connected */
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen if (director_connection_get_host(*connp) == host) {
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen doveadm_director_connection_append_status(conn, str);
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainenstatic int doveadm_cmd_director_list(struct doveadm_connection *conn,
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen director_connection_get_host(dir->left) == host;
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen director_connection_get_host(dir->right) == host;
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen last_failed = I_MAX(host->last_network_failure,
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen (unsigned long)last_failed);
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen doveadm_director_host_append_status(dir, host, str);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(conn->output, str_data(str), str_len(str));
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_director_add(struct doveadm_connection *conn,
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen const char *const *args)
009217abb57a24a4076092e8e4e165545747839eStephan Bosch (args[1] != NULL && net_str2port(args[1], &port) < 0)) {
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen i_error("doveadm sent invalid DIRECTOR-ADD parameters");
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen if (director_host_lookup(conn->dir, &ip, port) == NULL) {
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen host = director_host_add(conn->dir, &ip, port);
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen director_notify_ring_added(host, conn->dir->self_host);
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_director_remove(struct doveadm_connection *conn,
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen const char *const *args)
009217abb57a24a4076092e8e4e165545747839eStephan Bosch (args[1] != NULL && net_str2port(args[1], &port) < 0)) {
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen i_error("doveadm sent invalid DIRECTOR-REMOVE parameters");
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen director_ring_remove(host, conn->dir->self_host);
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_host_set_or_update(struct doveadm_connection *conn,
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) ||
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");
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen host = mail_host_lookup(dir->mail_hosts, &ip);
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
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");
28789c7ce1aa66ab21798bfb73ec64308b9a4de8Timo Sirainen "host is already being updated - try again later\n");
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
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_update_host(dir, dir->self_host, NULL, host);
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_host_set(struct doveadm_connection *conn, const char *const *args)
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen return doveadm_cmd_host_set_or_update(conn, args, FALSE);
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_host_update(struct doveadm_connection *conn, const char *const *args)
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen return doveadm_cmd_host_set_or_update(conn, args, TRUE);
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainendoveadm_cmd_host_updown(struct doveadm_connection *conn, bool down,
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen const char *const *args)
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen if (args[0] == NULL || net_addr2ip(args[0], &ip) < 0) {
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen i_error("doveadm sent invalid %s parameters: %s",
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen host = mail_host_lookup(conn->dir->mail_hosts, &ip);
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
28789c7ce1aa66ab21798bfb73ec64308b9a4de8Timo Sirainen "host is already being updated - try again later\n");
b3abfd0ac256ffa0cbfd74c3793eac4e83d41f78Martti Rannanjärvi mail_host_set_down(host, down, ioloop_time, "doveadm: ");
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen director_update_host(conn->dir, conn->dir->self_host,
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainendoveadm_cmd_host_up(struct doveadm_connection *conn,
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen const char *const *args)
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen return doveadm_cmd_host_updown(conn, FALSE, args);
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainendoveadm_cmd_host_down(struct doveadm_connection *conn,
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen const char *const *args)
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen return doveadm_cmd_host_updown(conn, TRUE, args);
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_host_remove(struct doveadm_connection *conn,
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen const char *const *args)
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen if (args[0] == NULL || net_addr2ip(args[0], &ip) < 0) {
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen i_error("doveadm sent invalid HOST-REMOVE parameters");
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen host = mail_host_lookup(conn->dir->mail_hosts, &ip);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_remove_host(conn->dir, conn->dir->self_host,
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainendoveadm_cmd_host_flush_all(struct doveadm_connection *conn)
9ffd3c8ca82bd2af8ca4f7e167339820ddcf1fe3Timo Sirainen unsigned int total_user_count = 0;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen array_foreach(mail_hosts_get(conn->dir->mail_hosts), hostp) {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_flush_host(conn->dir, conn->dir->self_host,
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.",
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_host_flush(struct doveadm_connection *conn, const char *const *args)
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen i_error("doveadm sent invalid HOST-FLUSH parameters");
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen host = mail_host_lookup(conn->dir->mail_hosts, &ip);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_flush_host(conn->dir, conn->dir->self_host,
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainenstatic void doveadm_reset_cmd_free(struct director_reset_cmd *cmd)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainendirector_host_reset_users(struct director_reset_cmd *cmd,
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (dir->users_moving_count >= cmd->max_moving_users)
b44033e45e9f48f8a6e1ac5905234fec5de6d6ccAki Tuomi while ((user = director_iterate_users_next(cmd->iter)) != NULL) {
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen new_host = mail_host_get_by_hash(dir->mail_hosts,
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (dir->users_moving_count >= cmd->max_moving_users)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainendirector_reset_cmd_run(struct director_reset_cmd *cmd)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen unsigned int count;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen hosts = array_get(mail_hosts_get(cmd->dir->mail_hosts), &count);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (!director_host_reset_users(cmd, hosts[cmd->host_idx]))
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_host_reset_users(struct doveadm_connection *conn,
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen const char *const *args)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen unsigned int i = 0, count;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen unsigned int max_moving_users = DEFAULT_MAX_MOVING_USERS;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen str_to_uint(args[1], &max_moving_users) < 0) {
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen i_error("doveadm sent invalid HOST-RESET-USERS parameters");
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen hosts = array_get(mail_hosts_get(conn->dir->mail_hosts), &count);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen i_error("doveadm sent invalid HOST-RESET-USERS ip: %s",
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen for (i = 0; i < count; i++) {
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen conn->reset_cmd = cmd = i_new(struct director_reset_cmd, 1);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen /* we still have work to do. don't handle any more doveadm
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen input until we're finished. */
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_user_lookup(struct doveadm_connection *conn,
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen const char *const *args)
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (str_to_uint(username, &username_hash) < 0) {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen o_stream_nsend_str(conn->output, "TRYAGAIN\n");
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen /* get user's current host */
b44033e45e9f48f8a6e1ac5905234fec5de6d6ccAki Tuomi mail_tag = mail_tag_find(conn->dir->mail_hosts, tag);
b44033e45e9f48f8a6e1ac5905234fec5de6d6ccAki Tuomi user_directory_lookup(mail_tag->users, username_hash);
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen str_printfa(str, "%s\t%u", net_ip2addr(&user->host->ip),
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 str_printfa(str, "\t%s", net_ip2addr(&host->ip));
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen /* get host with default configuration */
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen host = mail_host_get_by_hash(conn->dir->orig_config_hosts,
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));
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_user_list(struct doveadm_connection *conn, const char *const *args)
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen i_error("doveadm sent invalid USER-LIST parameters");
1f7f4294207557edf83171642ef62ce4922ffc9dTimo Sirainen iter = director_iterate_users_init(conn->dir);
1f7f4294207557edf83171642ef62ce4922ffc9dTimo Sirainen while ((user = director_iterate_users_next(iter)) != NULL) {
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen net_ip_compare(&ip, &user->host->ip)) T_BEGIN {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(conn->output, t_strdup_printf(
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen "%u\t%u\t%s\n",
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_user_move(struct doveadm_connection *conn, const char *const *args)
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen i_error("doveadm sent invalid USER-MOVE parameters");
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen host = mail_host_lookup(conn->dir->mail_hosts, &ip);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(conn->output, "NOTFOUND\n");
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (str_to_uint(args[0], &username_hash) < 0) {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen o_stream_nsend_str(conn->output, "TRYAGAIN\n");
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");
82641f7aa58d560cc89ec5eb16f03571d6dedcffTimo Sirainen director_move_user(conn->dir, conn->dir->self_host, NULL,
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);
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainendoveadm_cmd_user_kick(struct doveadm_connection *conn, const char *const *args)
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen i_error("doveadm sent invalid USER-KICK parameters");
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen director_kick_user(conn->dir, conn->dir->self_host, NULL, args[0]);
365b5a495ae7f6fd20f6a0b0517f6aa3ad4fe1a7Timo Sirainendoveadm_cmd_user_kick_alt(struct doveadm_connection *conn, const char *const *args)
365b5a495ae7f6fd20f6a0b0517f6aa3ad4fe1a7Timo Sirainen i_error("doveadm sent invalid USER-KICK-ALT parameters");
365b5a495ae7f6fd20f6a0b0517f6aa3ad4fe1a7Timo Sirainen director_kick_user_alt(conn->dir, conn->dir->self_host, NULL,
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen int (*cmd)(struct doveadm_connection *conn, const char *const *args);
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen { "HOST-LIST-REMOVED", doveadm_cmd_host_list_removed },
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen { "DIRECTOR-LIST", doveadm_cmd_director_list },
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen { "DIRECTOR-REMOVE", doveadm_cmd_director_remove },
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen { "HOST-RESET-USERS", doveadm_cmd_host_reset_users },
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen { "USER-KICK-ALT", doveadm_cmd_user_kick_alt },
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainendoveadm_connection_cmd(struct doveadm_connection *conn, const char *line)
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)
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen return doveadm_director_commands[i].cmd(conn, args);
68f7668b9315dd6c9e3d61c04d6da08e1ac3624fTimo Sirainen i_error("doveadm sent unknown command: %s", line);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic void doveadm_connection_input(struct doveadm_connection *conn)
d2cadbf5445156fc12988506279d51d0e53b0449Timo Sirainen if ((line = i_stream_read_next_line(conn->input)) == NULL) {
d2cadbf5445156fc12988506279d51d0e53b0449Timo Sirainen if (conn->input->eof || conn->input->stream_errno != 0)
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen if (!version_string_verify(line, "director-doveadm",
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_error("doveadm not compatible with this server "
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen "(mixed old and new binaries?)");
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen while ((line = i_stream_read_next_line(conn->input)) != NULL && ret > 0) {
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen if (conn->input->eof || conn->input->stream_errno != 0 || ret < 0)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainenstatic void doveadm_connection_set_io(struct doveadm_connection *conn)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen conn->io = io_add(conn->fd, IO_READ, doveadm_connection_input, conn);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainendoveadm_connection_init(struct director *dir, int fd)
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);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(conn->output, DOVEADM_HANDSHAKE);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic void doveadm_connection_deinit(struct doveadm_connection **_conn)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen /* finish the move even if doveadm disconnected */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_error("close(doveadm connection) failed: %m");
9522aa5f33cc37fe8ccd0d647cc51dd3ba6a9b55Timo Sirainen master_service_client_connection_destroyed(master_service);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct doveadm_connection *conn = doveadm_connections;