bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "lib.h"
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen#include "md5.h"
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen#include "hash.h"
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen#include "str.h"
26f4264ece463fa14795c2d4a11fcc9875f544a1Timo Sirainen#include "strescape.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "net.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "istream.h"
8338066be35c696b59fa9aefdc07042cb0797197Timo Sirainen#include "write-full.h"
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen#include "master-service.h"
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen#include "auth-master.h"
e1550f6a31306246a8499f5c9ca876096cbbeae9Timo Sirainen#include "mail-user-hash.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "doveadm.h"
68787d48554f497e711ff66a087ab31f990a11e9Timo Sirainen#include "doveadm-print.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include <stdio.h>
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include <unistd.h>
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen#include <fcntl.h>
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstruct director_context {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen const char *socket_path;
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen const char *users_path;
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen const char *tag;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi const char *user;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi const char *host;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi const char *ip;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi const char *port;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi const char *vhost_count;
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen const char *passdb_field;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi struct istream *users_input;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct istream *input;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen bool explicit_socket_path;
db8ca445e2082fe0b17d593f1f842cf8c40dd6a2Timo Sirainen bool hash_map, user_map, force_flush;
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen int64_t max_parallel;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen};
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainenstruct user_list {
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen struct user_list *next;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen const char *name;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen};
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen
a75d470c9223a75801418fcdda258885c36317e0Timo SirainenHASH_TABLE_DEFINE_TYPE(user_list, void *, struct user_list *);
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomistatic void director_cmd_help(const struct doveadm_cmd_ver2 *);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomistatic int director_get_host(const char *host, struct ip_addr **ips_r,
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi unsigned int *ips_count_r) ATTR_WARN_UNUSED_RESULT;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic void
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainendirector_send(struct director_context *ctx, const char *data)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
8338066be35c696b59fa9aefdc07042cb0797197Timo Sirainen if (write_full(i_stream_get_fd(ctx->input), data, strlen(data)) < 0)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_fatal("write(%s) failed: %m", ctx->socket_path);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic void director_connect(struct director_context *ctx)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen#define DIRECTOR_HANDSHAKE "VERSION\tdirector-doveadm\t1\t0\n"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen const char *line;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen int fd;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen fd = doveadm_connect(ctx->socket_path);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen net_set_nonblock(fd, FALSE);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
bace943c67e6cd14ce6c994f533d82a3caad5bf1Timo Sirainen ctx->input = i_stream_create_fd_autoclose(&fd, (size_t)-1);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen director_send(ctx, DIRECTOR_HANDSHAKE);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
224414073c72d77a09a77b4dd71500ada5690802Timo Sirainen alarm(5);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen line = i_stream_read_next_line(ctx->input);
224414073c72d77a09a77b4dd71500ada5690802Timo Sirainen alarm(0);
224414073c72d77a09a77b4dd71500ada5690802Timo Sirainen if (line == NULL) {
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen if (ctx->input->stream_errno != 0) {
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen i_fatal("read(%s) failed: %s", ctx->socket_path,
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen i_stream_get_error(ctx->input));
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen } else if (ctx->input->eof) {
224414073c72d77a09a77b4dd71500ada5690802Timo Sirainen i_fatal("%s disconnected", ctx->socket_path);
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen } else {
224414073c72d77a09a77b4dd71500ada5690802Timo Sirainen i_fatal("read(%s) timed out (is director configured?)",
224414073c72d77a09a77b4dd71500ada5690802Timo Sirainen ctx->socket_path);
224414073c72d77a09a77b4dd71500ada5690802Timo Sirainen }
224414073c72d77a09a77b4dd71500ada5690802Timo Sirainen }
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen if (!version_string_verify(line, "director-doveadm", 1)) {
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen i_fatal_status(EX_PROTOCOL,
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen "%s not a compatible director-doveadm socket",
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen ctx->socket_path);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic void director_disconnect(struct director_context *ctx)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
e256ae453eb7b4495b3491062bce7c66f2fb1d81Timo Sirainen if (ctx->input != NULL) {
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen if (ctx->input->stream_errno != 0) {
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen i_fatal("read(%s) failed: %s", ctx->socket_path,
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen i_stream_get_error(ctx->input));
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen }
e256ae453eb7b4495b3491062bce7c66f2fb1d81Timo Sirainen i_stream_destroy(&ctx->input);
e256ae453eb7b4495b3491062bce7c66f2fb1d81Timo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic struct director_context *
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomicmd_director_init(struct doveadm_cmd_context *cctx)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct director_context *ctx;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen ctx = t_new(struct director_context, 1);
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi if (!doveadm_cmd_param_str(cctx, "socket-path", &(ctx->socket_path)))
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi ctx->socket_path = t_strconcat(doveadm_settings->base_dir,
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi "/director-admin", NULL);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi else
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi ctx->explicit_socket_path = TRUE;
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi if (!doveadm_cmd_param_bool(cctx, "user-map", &(ctx->user_map)))
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi ctx->user_map = FALSE;
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi if (!doveadm_cmd_param_bool(cctx, "hash-map", &(ctx->hash_map)))
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi ctx->hash_map = FALSE;
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi if (!doveadm_cmd_param_bool(cctx, "force-flush", &(ctx->force_flush)))
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi ctx->force_flush = FALSE;
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi if (!doveadm_cmd_param_istream(cctx, "users-file", &(ctx->users_input)))
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi ctx->users_input = NULL;
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi if (!doveadm_cmd_param_str(cctx, "tag", &(ctx->tag)))
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi ctx->tag = NULL;
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi if (!doveadm_cmd_param_str(cctx, "user", &(ctx->user)))
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi ctx->user = NULL;
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi if (!doveadm_cmd_param_str(cctx, "host", &(ctx->host)))
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi ctx->host = NULL;
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi if (!doveadm_cmd_param_str(cctx, "ip", &(ctx->ip)))
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi ctx->ip = NULL;
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi if (!doveadm_cmd_param_str(cctx, "port", &(ctx->port)))
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi ctx->port = NULL;
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi if (!doveadm_cmd_param_str(cctx, "vhost-count", &(ctx->vhost_count)))
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi ctx->vhost_count = NULL;
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen if (!doveadm_cmd_param_str(cctx, "passdb-field", &(ctx->passdb_field)))
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen ctx->passdb_field = NULL;
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen if (!doveadm_cmd_param_int64(cctx, "max-parallel", &(ctx->max_parallel)))
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen ctx->max_parallel = 0;
e256ae453eb7b4495b3491062bce7c66f2fb1d81Timo Sirainen if (!ctx->user_map)
e256ae453eb7b4495b3491062bce7c66f2fb1d81Timo Sirainen director_connect(ctx);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return ctx;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainenstatic void director_disconnected(struct director_context *ctx)
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen{
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen i_assert(ctx->input->eof);
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen if (ctx->input->stream_errno != 0) {
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen i_error("read(%s) failed: %s", ctx->socket_path,
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen i_stream_get_error(ctx->input));
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen } else {
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen i_error("%s unexpectedly disconnected", ctx->socket_path);
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen }
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen}
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainenstatic void
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomicmd_director_status_user(struct director_context *ctx)
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen{
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen const char *line, *const *args;
20b6e495f623955c680db65447e3f6a8b4c6222fTimo Sirainen time_t expires;
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi director_send(ctx, t_strdup_printf("USER-LOOKUP\t%s\t%s\n", ctx->user,
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi ctx->tag != NULL ? ctx->tag : ""));
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen line = i_stream_read_next_line(ctx->input);
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen if (line == NULL) {
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen director_disconnected(ctx);
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen return;
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen }
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen
7a60e1dc9e93ef3f7c7fe1af6385a0bfa1e31bc3Timo Sirainen args = t_strsplit_tabescaped(line);
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen if (str_array_length(args) != 4 ||
20b6e495f623955c680db65447e3f6a8b4c6222fTimo Sirainen str_to_time(args[1], &expires) < 0) {
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen i_error("Invalid reply from director");
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_exit_code = EX_PROTOCOL;
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen return;
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen }
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print_init(DOVEADM_PRINT_TYPE_FORMATTED);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print_header_simple("status");
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print_header_simple("expires");
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print_header_simple("hashed");
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print_header_simple("initial-config");
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print_formatted_set_format("Current: %{status} (expires %{expires})\n" \
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi "Hashed: %{hashed}\n" \
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi "Initial config: %{initial-config}\n");
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen if (args[0][0] != '\0') {
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print(args[0]);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print(unixdate2str(expires));
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen } else {
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print("n/a");
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print("-1");
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen }
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print(args[2]);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print(args[3]);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen director_disconnect(ctx);
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen}
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomistatic void cmd_director_status(struct doveadm_cmd_context *cctx)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct director_context *ctx;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen const char *line, *const *args;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi ctx = cmd_director_init(cctx);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (ctx->user != NULL) {
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi cmd_director_status_user(ctx);
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen return;
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen }
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen
68787d48554f497e711ff66a087ab31f990a11e9Timo Sirainen doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE);
68787d48554f497e711ff66a087ab31f990a11e9Timo Sirainen doveadm_print_header_simple("mail server ip");
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen doveadm_print_header_simple("tag");
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen doveadm_print_header_simple("vhosts");
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen doveadm_print_header_simple("state");
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen doveadm_print_header("state-changed", "state changed", 0);
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen doveadm_print_header_simple("users");
68787d48554f497e711ff66a087ab31f990a11e9Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen director_send(ctx, "HOST-LIST\n");
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen while ((line = i_stream_read_next_line(ctx->input)) != NULL) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (*line == '\0')
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen break;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen T_BEGIN {
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen unsigned int arg_count;
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen time_t ts;
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen
7a60e1dc9e93ef3f7c7fe1af6385a0bfa1e31bc3Timo Sirainen args = t_strsplit_tabescaped(line);
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen arg_count = str_array_length(args);
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen if (arg_count >= 6) {
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen /* ip vhosts users tag updown updown-ts */
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen doveadm_print(args[0]);
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen doveadm_print(args[3]);
68787d48554f497e711ff66a087ab31f990a11e9Timo Sirainen doveadm_print(args[1]);
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen doveadm_print(args[4][0] == 'D' ? "down" : "up");
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen if (str_to_time(args[5], &ts) < 0 ||
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen ts <= 0)
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen doveadm_print("-");
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen else
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen doveadm_print(unixdate2str(ts));
68787d48554f497e711ff66a087ab31f990a11e9Timo Sirainen doveadm_print(args[2]);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen } T_END;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen if (line == NULL)
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen director_disconnected(ctx);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen director_disconnect(ctx);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainenstatic bool user_hash_expand(const char *username, unsigned int *hash_r)
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen{
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen const char *error;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (!mail_user_hash(username, doveadm_settings->director_username_hash,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen hash_r, &error)) {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen i_error("Failed to expand director_username_hash=%s: %s",
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen doveadm_settings->director_username_hash, error);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen return FALSE;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen }
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen return TRUE;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen}
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainenstatic void
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainenuser_list_add(const char *username, pool_t pool,
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen HASH_TABLE_TYPE(user_list) users)
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen{
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen struct user_list *user, *old_user;
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen unsigned int user_hash;
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (!user_hash_expand(username, &user_hash))
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen return;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen user = p_new(pool, struct user_list, 1);
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen user->name = p_strdup(pool, username);
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen old_user = hash_table_lookup(users, POINTER_CAST(user_hash));
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen if (old_user != NULL)
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen user->next = old_user;
c224fff79d18480a65e9b4504b891b8ea176f5b1Timo Sirainen hash_table_update(users, POINTER_CAST(user_hash), user);
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen}
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainenstatic void ATTR_NULL(1)
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainenuserdb_get_user_list(const char *auth_socket_path, pool_t pool,
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen HASH_TABLE_TYPE(user_list) users)
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen{
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen struct auth_master_user_list_ctx *ctx;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen struct auth_master_connection *conn;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen const char *username;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen if (auth_socket_path == NULL) {
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen auth_socket_path = t_strconcat(doveadm_settings->base_dir,
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen "/auth-userdb", NULL);
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen }
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen conn = auth_master_init(auth_socket_path, 0);
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen ctx = auth_master_user_list_init(conn, "", NULL);
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen while ((username = auth_master_user_list_next(ctx)) != NULL)
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen user_list_add(username, pool, users);
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen if (auth_master_user_list_deinit(&ctx) < 0) {
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen i_error("user listing failed");
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen }
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen auth_master_deinit(&conn);
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen}
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainenstatic void
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomiuser_file_get_user_list(struct istream *input, pool_t pool,
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen HASH_TABLE_TYPE(user_list) users)
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen{
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen const char *username;
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen while ((username = i_stream_read_next_line(input)) != NULL)
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen user_list_add(username, pool, users);
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen}
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomistatic int director_get_host(const char *host, struct ip_addr **ips_r,
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen unsigned int *ips_count_r)
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen{
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen struct ip_addr ip;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi int ret = 0;
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen if (net_addr2ip(host, &ip) == 0) {
eee73872e8d975f7b2d48a5a1b34a94588331ec5Timo Sirainen *ips_r = t_new(struct ip_addr, 1);
eee73872e8d975f7b2d48a5a1b34a94588331ec5Timo Sirainen **ips_r = ip;
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen *ips_count_r = 1;
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen } else {
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen ret = net_gethostbyname(host, ips_r, ips_count_r);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen if (ret != 0) {
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi i_error("gethostname(%s) failed: %s", host,
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen net_gethosterror(ret));
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_exit_code = EX_TEMPFAIL;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi return ret;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen }
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen }
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi return ret;
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen}
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainenstatic bool ip_find(const struct ip_addr *ips, unsigned int ips_count,
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen const struct ip_addr *match_ip)
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen{
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen unsigned int i;
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen for (i = 0; i < ips_count; i++) {
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen if (net_ip_compare(&ips[i], match_ip))
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen return TRUE;
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen }
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen return FALSE;
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen}
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomistatic void cmd_director_map(struct doveadm_cmd_context *cctx)
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen{
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen struct director_context *ctx;
f6bf269b74e128decd45b6ab01f425e5d3c13894Timo Sirainen const char *line, *const *args;
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen struct ip_addr *ips, user_ip;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen pool_t pool;
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen HASH_TABLE_TYPE(user_list) users;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen struct user_list *user;
20b6e495f623955c680db65447e3f6a8b4c6222fTimo Sirainen unsigned int ips_count, user_hash;
20b6e495f623955c680db65447e3f6a8b4c6222fTimo Sirainen time_t expires;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi ctx = cmd_director_init(cctx);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi
0896246f4648151fe846215190ee92cefbcfb8b8Timo Sirainen if ((ctx->hash_map || ctx->user_map) && ctx->host == NULL) {
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi director_cmd_help(cctx->cmd);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi return;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi }
3957200d949c6e96c4184db2395444d723950583Timo Sirainen
3957200d949c6e96c4184db2395444d723950583Timo Sirainen if (ctx->user_map) {
3957200d949c6e96c4184db2395444d723950583Timo Sirainen /* user -> hash mapping */
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (user_hash_expand(ctx->host, &user_hash)) {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen doveadm_print_header("hash", "hash", DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen doveadm_print(t_strdup_printf("%u", user_hash));
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen }
3957200d949c6e96c4184db2395444d723950583Timo Sirainen director_disconnect(ctx);
3957200d949c6e96c4184db2395444d723950583Timo Sirainen return;
3957200d949c6e96c4184db2395444d723950583Timo Sirainen }
3957200d949c6e96c4184db2395444d723950583Timo Sirainen
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (ctx->host == NULL || ctx->hash_map)
3957200d949c6e96c4184db2395444d723950583Timo Sirainen ips_count = 0;
ccf5e99d0285da8679dee6e0b68fa9ea99a4ddfaTimo Sirainen else if (director_get_host(ctx->host, &ips, &ips_count) != 0) {
ccf5e99d0285da8679dee6e0b68fa9ea99a4ddfaTimo Sirainen director_disconnect(ctx);
ccf5e99d0285da8679dee6e0b68fa9ea99a4ddfaTimo Sirainen return;
ccf5e99d0285da8679dee6e0b68fa9ea99a4ddfaTimo Sirainen }
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen pool = pool_alloconly_create("director map users", 1024*128);
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen hash_table_create_direct(&users, pool, 0);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (ctx->users_input == NULL)
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen userdb_get_user_list(NULL, pool, users);
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen else
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi user_file_get_user_list(ctx->users_input, pool, users);
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen
3957200d949c6e96c4184db2395444d723950583Timo Sirainen if (ctx->hash_map) {
3957200d949c6e96c4184db2395444d723950583Timo Sirainen /* hash -> usernames mapping */
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (str_to_uint(ctx->host, &user_hash) < 0)
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi i_fatal("Invalid username hash: %s", ctx->host);
3957200d949c6e96c4184db2395444d723950583Timo Sirainen
3957200d949c6e96c4184db2395444d723950583Timo Sirainen doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE);
3957200d949c6e96c4184db2395444d723950583Timo Sirainen doveadm_print_header("user", "user", DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
3957200d949c6e96c4184db2395444d723950583Timo Sirainen user = hash_table_lookup(users, POINTER_CAST(user_hash));
3957200d949c6e96c4184db2395444d723950583Timo Sirainen for (; user != NULL; user = user->next)
3957200d949c6e96c4184db2395444d723950583Timo Sirainen doveadm_print(user->name);
3957200d949c6e96c4184db2395444d723950583Timo Sirainen goto deinit;
3957200d949c6e96c4184db2395444d723950583Timo Sirainen }
3957200d949c6e96c4184db2395444d723950583Timo Sirainen
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE);
6176f3618240943f3cb41cb7063ecef56b1dd7dfTimo Sirainen doveadm_print_header("user", "user", DOVEADM_PRINT_HEADER_FLAG_EXPAND);
cac19595c35d7477f7b911805da60a7f6c898bcbTimo Sirainen doveadm_print_header_simple("hash");
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen doveadm_print_header_simple("mail server ip");
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen doveadm_print_header_simple("expire time");
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen if (ips_count != 1)
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen director_send(ctx, "USER-LIST\n");
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen else {
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen director_send(ctx, t_strdup_printf(
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen "USER-LIST\t%s\n", net_ip2addr(&ips[0])));
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen }
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen while ((line = i_stream_read_next_line(ctx->input)) != NULL) {
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen if (*line == '\0')
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen break;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen T_BEGIN {
7a60e1dc9e93ef3f7c7fe1af6385a0bfa1e31bc3Timo Sirainen args = t_strsplit_tabescaped(line);
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen if (str_array_length(args) < 3 ||
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen str_to_uint(args[0], &user_hash) < 0 ||
20b6e495f623955c680db65447e3f6a8b4c6222fTimo Sirainen str_to_time(args[1], &expires) < 0 ||
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen net_addr2ip(args[2], &user_ip) < 0) {
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen i_error("Invalid USER-LIST reply: %s", line);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_exit_code = EX_PROTOCOL;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen } else if (ips_count == 0 ||
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen ip_find(ips, ips_count, &user_ip)) {
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen user = hash_table_lookup(users,
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen POINTER_CAST(user_hash));
f6bf269b74e128decd45b6ab01f425e5d3c13894Timo Sirainen if (user == NULL) {
f6bf269b74e128decd45b6ab01f425e5d3c13894Timo Sirainen doveadm_print("<unknown>");
cac19595c35d7477f7b911805da60a7f6c898bcbTimo Sirainen doveadm_print(args[0]);
f6bf269b74e128decd45b6ab01f425e5d3c13894Timo Sirainen doveadm_print(args[2]);
f6bf269b74e128decd45b6ab01f425e5d3c13894Timo Sirainen doveadm_print(unixdate2str(expires));
f6bf269b74e128decd45b6ab01f425e5d3c13894Timo Sirainen }
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen for (; user != NULL; user = user->next) {
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen doveadm_print(user->name);
cac19595c35d7477f7b911805da60a7f6c898bcbTimo Sirainen doveadm_print(args[0]);
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen doveadm_print(args[2]);
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen doveadm_print(unixdate2str(expires));
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen }
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen }
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen } T_END;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen }
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen if (line == NULL)
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen director_disconnected(ctx);
3957200d949c6e96c4184db2395444d723950583Timo Sirainendeinit:
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen director_disconnect(ctx);
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen hash_table_destroy(&users);
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen pool_unref(&pool);
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen}
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainenstatic void
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomicmd_director_add_or_update(struct doveadm_cmd_context *cctx, bool update)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
e307e0fcc31ab7b3d062f6ff4b7d48d8b1b2f7b8Timo Sirainen const char *director_cmd = update ? "HOST-UPDATE" : "HOST-SET";
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct director_context *ctx;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct ip_addr *ips;
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen unsigned int i, ips_count, vhost_count = UINT_MAX;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi const char *line, *host;
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen string_t *cmd;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi ctx = cmd_director_init(cctx);
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen if (ctx->tag != NULL && ctx->tag[0] == '\0')
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen ctx->tag = NULL;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (ctx->host == NULL) {
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi director_cmd_help(cctx->cmd);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi return;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi }
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (ctx->vhost_count != NULL) {
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (str_to_uint(ctx->vhost_count, &vhost_count) < 0) {
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi director_cmd_help(cctx->cmd);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi return;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi }
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi } else if (update) {
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi director_cmd_help(cctx->cmd);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi return;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi }
91879fbefda4e049ae37e6443a7806b0afddda86Timo Sirainen if (str_to_uint(ctx->host, &i) == 0) {
521c0460fe705f32ea6899c8b1f101043fe0898cTimo Sirainen /* host is a number. this would translate to an IP address,
521c0460fe705f32ea6899c8b1f101043fe0898cTimo Sirainen which is probably a mistake. */
91879fbefda4e049ae37e6443a7806b0afddda86Timo Sirainen i_error("Invalid host '%s'", ctx->host);
521c0460fe705f32ea6899c8b1f101043fe0898cTimo Sirainen director_cmd_help(cctx->cmd);
521c0460fe705f32ea6899c8b1f101043fe0898cTimo Sirainen return;
521c0460fe705f32ea6899c8b1f101043fe0898cTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi host = ctx->host;
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen if (ctx->tag == NULL) {
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi ctx->tag = strchr(ctx->host, '@');
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen if (ctx->tag != NULL)
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi host = t_strdup_until(ctx->host, ctx->tag++);
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen }
ccf5e99d0285da8679dee6e0b68fa9ea99a4ddfaTimo Sirainen if (director_get_host(host, &ips, &ips_count) != 0) {
ccf5e99d0285da8679dee6e0b68fa9ea99a4ddfaTimo Sirainen director_disconnect(ctx);
ccf5e99d0285da8679dee6e0b68fa9ea99a4ddfaTimo Sirainen return;
ccf5e99d0285da8679dee6e0b68fa9ea99a4ddfaTimo Sirainen }
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen cmd = t_str_new(128);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen for (i = 0; i < ips_count; i++) {
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen str_truncate(cmd, 0);
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen str_printfa(cmd, "%s\t%s", director_cmd, net_ip2addr(&ips[i]));
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen if (ctx->tag != NULL)
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen str_printfa(cmd, "@%s", ctx->tag);
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen if (vhost_count != UINT_MAX)
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen str_printfa(cmd, "\t%u", vhost_count);
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen str_append_c(cmd, '\n');
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen director_send(ctx, str_c(cmd));
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen for (i = 0; i < ips_count; i++) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen line = i_stream_read_next_line(ctx->input);
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen if (line == NULL)
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen director_disconnected(ctx);
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen else if (strcmp(line, "OK") != 0) {
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi i_error("%s: %s\n", net_ip2addr(&ips[i]),
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen strcmp(line, "NOTFOUND") == 0 ?
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen "doesn't exist" : line);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen } else if (doveadm_verbose) {
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi i_info("%s: OK\n", net_ip2addr(&ips[i]));
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen director_disconnect(ctx);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomistatic void cmd_director_add(struct doveadm_cmd_context *cctx)
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen{
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi cmd_director_add_or_update(cctx, FALSE);
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen}
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomistatic void cmd_director_update(struct doveadm_cmd_context *cctx)
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen{
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi cmd_director_add_or_update(cctx, TRUE);
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen}
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainenstatic void
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomicmd_director_ipcmd(const char *cmd_name, const char *success_result,
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi struct doveadm_cmd_context *cctx)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct director_context *ctx;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct ip_addr *ips;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen unsigned int i, ips_count;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen const char *host, *line;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi ctx = cmd_director_init(cctx);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi host = ctx->host;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (host == NULL) {
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi director_cmd_help(cctx->cmd);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi return;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
ccf5e99d0285da8679dee6e0b68fa9ea99a4ddfaTimo Sirainen if (director_get_host(host, &ips, &ips_count) != 0) {
ccf5e99d0285da8679dee6e0b68fa9ea99a4ddfaTimo Sirainen director_disconnect(ctx);
ccf5e99d0285da8679dee6e0b68fa9ea99a4ddfaTimo Sirainen return;
ccf5e99d0285da8679dee6e0b68fa9ea99a4ddfaTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen for (i = 0; i < ips_count; i++) {
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen director_send(ctx, t_strdup_printf(
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen "%s\t%s\n", cmd_name, net_ip2addr(&ips[i])));
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen for (i = 0; i < ips_count; i++) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen line = i_stream_read_next_line(ctx->input);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen if (line != NULL && strcmp(line, "NOTFOUND") == 0) {
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi i_error("%s: doesn't exist\n",
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen net_ip2addr(&ips[i]));
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen if (doveadm_exit_code == 0)
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_exit_code = DOVEADM_EX_NOTFOUND;
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen } else if (line == NULL) {
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen director_disconnected(ctx);
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen } else if (strcmp(line, "OK") != 0) {
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen i_error("%s: %s\n", net_ip2addr(&ips[i]), line);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen } else if (doveadm_verbose) {
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi i_info("%s: %s\n", net_ip2addr(&ips[i]), success_result);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen director_disconnect(ctx);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomistatic void cmd_director_remove(struct doveadm_cmd_context *cctx)
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen{
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi cmd_director_ipcmd("HOST-REMOVE", "removed", cctx);
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen}
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomistatic void cmd_director_up(struct doveadm_cmd_context *cctx)
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen{
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi cmd_director_ipcmd("HOST-UP", "up", cctx);
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen}
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomistatic void cmd_director_down(struct doveadm_cmd_context *cctx)
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen{
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi cmd_director_ipcmd("HOST-DOWN", "down", cctx);
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen}
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomistatic void cmd_director_move(struct doveadm_cmd_context *cctx)
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen{
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen struct director_context *ctx;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen struct ip_addr *ips;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen unsigned int ips_count, user_hash;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi const char *line, *ip_str;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi ctx = cmd_director_init(cctx);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (ctx->user == NULL || ctx->host == NULL) {
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi director_cmd_help(cctx->cmd);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi return;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi }
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (!user_hash_expand(ctx->user, &user_hash) ||
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen director_get_host(ctx->host, &ips, &ips_count) != 0) {
ccf5e99d0285da8679dee6e0b68fa9ea99a4ddfaTimo Sirainen director_disconnect(ctx);
ccf5e99d0285da8679dee6e0b68fa9ea99a4ddfaTimo Sirainen return;
ccf5e99d0285da8679dee6e0b68fa9ea99a4ddfaTimo Sirainen }
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen ip_str = net_ip2addr(&ips[0]);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen director_send(ctx, t_strdup_printf(
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen "USER-MOVE\t%u\t%s\n", user_hash, ip_str));
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen line = i_stream_read_next_line(ctx->input);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen if (line == NULL) {
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen director_disconnected(ctx);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen } else if (strcmp(line, "OK") == 0) {
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen if (doveadm_verbose)
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi i_info("User hash %u moved to %s\n", user_hash, ip_str);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen } else if (strcmp(line, "NOTFOUND") == 0) {
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen i_error("Host '%s' doesn't exist", ip_str);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_exit_code = DOVEADM_EX_NOTFOUND;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen } else if (strcmp(line, "TRYAGAIN") == 0) {
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen i_error("User is already being moved, "
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen "wait a while for it to be finished");
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen } else {
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen i_error("failed: %s", line);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen }
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen director_disconnect(ctx);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen}
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomistatic void cmd_director_kick(struct doveadm_cmd_context *cctx)
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen{
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen struct director_context *ctx;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi const char *line;
26f4264ece463fa14795c2d4a11fcc9875f544a1Timo Sirainen string_t *cmd = t_str_new(64);
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi ctx = cmd_director_init(cctx);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (ctx->user == NULL) {
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi director_cmd_help(cctx->cmd);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi return;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi }
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen if (ctx->passdb_field == NULL) {
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen str_append(cmd, "USER-KICK\t");
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen str_append_tabescaped(cmd, ctx->user);
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen str_append_c(cmd, '\n');
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen } else {
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen str_append(cmd, "USER-KICK-ALT\t");
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen str_append_tabescaped(cmd, ctx->passdb_field);
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen str_append_c(cmd, '\t');
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen str_append_tabescaped(cmd, ctx->user);
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen str_append_c(cmd, '\n');
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen }
26f4264ece463fa14795c2d4a11fcc9875f544a1Timo Sirainen director_send(ctx, str_c(cmd));
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen line = i_stream_read_next_line(ctx->input);
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen if (line == NULL) {
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen director_disconnected(ctx);
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen } else if (strcmp(line, "OK") == 0) {
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen if (doveadm_verbose)
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi i_info("User %s kicked", ctx->user);
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen } else {
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen i_error("failed: %s", line);
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen }
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen director_disconnect(ctx);
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen}
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainenstatic void cmd_director_flush_all(struct director_context *ctx)
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen{
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen const char *line;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen if (ctx->force_flush)
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen line = "HOST-FLUSH\n";
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen else if (ctx->max_parallel > 0) {
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen line = t_strdup_printf("HOST-RESET-USERS\t\t%lld\n",
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen (long long)ctx->max_parallel);
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen } else {
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen line = "HOST-RESET-USERS\n";
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen }
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen director_send(ctx, line);
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen line = i_stream_read_next_line(ctx->input);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen if (line == NULL) {
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen director_disconnected(ctx);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen } else if (strcmp(line, "OK") != 0) {
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen i_error("failed: %s", line);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen } else if (doveadm_verbose)
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi i_info("flushed");
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen director_disconnect(ctx);
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen}
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomistatic void cmd_director_flush(struct doveadm_cmd_context *cctx)
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen{
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen struct director_context *ctx;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen struct ip_addr *ips;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen unsigned int i, ips_count;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen struct ip_addr ip;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi const char *line;
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen string_t *cmd;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi ctx = cmd_director_init(cctx);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (ctx->host == NULL) {
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi director_cmd_help(cctx->cmd);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi return;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi }
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (strcmp(ctx->host, "all") == 0) {
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen cmd_director_flush_all(ctx);
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen return;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen }
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (net_addr2ip(ctx->host, &ip) == 0) {
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen ips = &ip;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen ips_count = 1;
ccf5e99d0285da8679dee6e0b68fa9ea99a4ddfaTimo Sirainen } else if (director_get_host(ctx->host, &ips, &ips_count) != 0) {
ccf5e99d0285da8679dee6e0b68fa9ea99a4ddfaTimo Sirainen director_disconnect(ctx);
ccf5e99d0285da8679dee6e0b68fa9ea99a4ddfaTimo Sirainen return;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen }
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen cmd = t_str_new(64);
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen for (i = 0; i < ips_count; i++) {
351233c8101128366f83c6f9688f0f67538f7c9eAki Tuomi ip = ips[i];
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen str_truncate(cmd, 0);
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen if (ctx->force_flush)
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen str_printfa(cmd, "HOST-FLUSH\t%s\n", net_ip2addr(&ip));
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen else {
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen str_printfa(cmd, "HOST-RESET-USERS\t%s", net_ip2addr(&ip));
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen if (ctx->max_parallel > 0) {
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen str_printfa(cmd, "\t%lld",
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen (long long)ctx->max_parallel);
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen }
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen str_append_c(cmd, '\n');
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen }
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen director_send(ctx, str_c(cmd));
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen }
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen for (i = 0; i < ips_count; i++) {
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen line = i_stream_read_next_line(ctx->input);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen if (line != NULL && strcmp(line, "NOTFOUND") == 0) {
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi i_warning("%s: doesn't exist",
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen net_ip2addr(&ips[i]));
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen if (doveadm_exit_code == 0)
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_exit_code = DOVEADM_EX_NOTFOUND;
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen } else if (line == NULL) {
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen director_disconnected(ctx);
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen } else if (strcmp(line, "OK") != 0) {
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen i_warning("%s: %s", net_ip2addr(&ips[i]), line);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen } else if (doveadm_verbose) {
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi i_info("%s: flushed", net_ip2addr(&ips[i]));
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen }
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen }
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen director_disconnect(ctx);
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen}
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomistatic void cmd_director_dump(struct doveadm_cmd_context *cctx)
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen{
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen struct director_context *ctx;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen const char *line, *const *args;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi ctx = cmd_director_init(cctx);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print_init(DOVEADM_PRINT_TYPE_FORMATTED);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (ctx->explicit_socket_path)
3cbc0cb7c454ad5132dd335a7ae47bd6f5da2aa6Timo Sirainen doveadm_print_formatted_set_format("doveadm director %{command} -a %{socket-path} %{host} %{vhost_count}\n");
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi else
3cbc0cb7c454ad5132dd335a7ae47bd6f5da2aa6Timo Sirainen doveadm_print_formatted_set_format("doveadm director %{command} %{host} %{vhost_count}\n");
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print_header_simple("command");
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print_header_simple("socket-path");
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print_header_simple("host");
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print_header_simple("vhost_count");
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen director_send(ctx, "HOST-LIST\n");
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen while ((line = i_stream_read_next_line(ctx->input)) != NULL) {
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen if (*line == '\0')
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen break;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen T_BEGIN {
7a60e1dc9e93ef3f7c7fe1af6385a0bfa1e31bc3Timo Sirainen args = t_strsplit_tabescaped(line);
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen if (str_array_length(args) >= 2) {
a2532003186d63337e1cbf9ba8f8f7ec401dea58Aki Tuomi const char *host = args[0];
5898bb384d351ea32f1714da072485c71ca909adAki Tuomi const char *tag = args[3];
a2532003186d63337e1cbf9ba8f8f7ec401dea58Aki Tuomi /* this is guaranteed to be at least NULL */
5898bb384d351ea32f1714da072485c71ca909adAki Tuomi if (tag != NULL &&
5898bb384d351ea32f1714da072485c71ca909adAki Tuomi *tag != '\0')
a2532003186d63337e1cbf9ba8f8f7ec401dea58Aki Tuomi host = t_strdup_printf("%s@%s", host,
5898bb384d351ea32f1714da072485c71ca909adAki Tuomi tag);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print("add");
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print(ctx->socket_path);
a2532003186d63337e1cbf9ba8f8f7ec401dea58Aki Tuomi doveadm_print(host);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print(args[1]);
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen }
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen } T_END;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen }
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen director_send(ctx, "HOST-LIST-REMOVED\n");
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen while ((line = i_stream_read_next_line(ctx->input)) != NULL) {
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen if (*line == '\0')
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen break;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print("remove");
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print(ctx->socket_path);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print(line);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print("");
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen }
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen if (line == NULL)
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen director_disconnected(ctx);
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen director_disconnect(ctx);
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen}
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainenstatic void director_read_ok_reply(struct director_context *ctx)
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen{
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen const char *line;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen line = i_stream_read_next_line(ctx->input);
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen if (line == NULL) {
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen director_disconnected(ctx);
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen } else if (strcmp(line, "NOTFOUND") == 0) {
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen i_error("Not found");
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen doveadm_exit_code = DOVEADM_EX_NOTFOUND;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen } else if (strcmp(line, "OK") != 0) {
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen i_error("Failed: %s", line);
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen }
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen}
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomistatic void cmd_director_ring_add(struct doveadm_cmd_context *cctx)
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen{
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen struct director_context *ctx;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen struct ip_addr ip;
009217abb57a24a4076092e8e4e165545747839eStephan Bosch in_port_t port = 0;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen string_t *str = t_str_new(64);
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi ctx = cmd_director_init(cctx);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (ctx->ip == NULL ||
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi net_addr2ip(ctx->ip, &ip) < 0 ||
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen (ctx->port != 0 && net_str2port(ctx->port, &port) < 0)) {
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi director_cmd_help(cctx->cmd);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi return;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi }
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen str_printfa(str, "DIRECTOR-ADD\t%s", net_ip2addr(&ip));
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen if (port != 0)
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen str_printfa(str, "\t%u", port);
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen str_append_c(str, '\n');
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen director_send(ctx, str_c(str));
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen director_read_ok_reply(ctx);
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen director_disconnect(ctx);
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen}
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomistatic void cmd_director_ring_remove(struct doveadm_cmd_context *cctx)
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen{
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen struct director_context *ctx;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen struct ip_addr ip;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen string_t *str = t_str_new(64);
009217abb57a24a4076092e8e4e165545747839eStephan Bosch in_port_t port = 0;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi ctx = cmd_director_init(cctx);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (ctx->ip == NULL ||
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi net_addr2ip(ctx->ip, &ip) < 0 ||
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi (ctx->port != NULL && net_str2port(ctx->port, &port) < 0)) {
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi director_cmd_help(cctx->cmd);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi return;
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi }
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen str_printfa(str, "DIRECTOR-REMOVE\t%s", net_ip2addr(&ip));
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen if (port != 0)
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen str_printfa(str, "\t%u", port);
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen str_append_c(str, '\n');
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen director_send(ctx, str_c(str));
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen director_read_ok_reply(ctx);
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen director_disconnect(ctx);
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen}
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomistatic void cmd_director_ring_status(struct doveadm_cmd_context *cctx)
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen{
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen struct director_context *ctx;
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen const char *line, *const *args;
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi ctx = cmd_director_init(cctx);
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE);
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen doveadm_print_header_simple("director ip");
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen doveadm_print_header_simple("port");
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen doveadm_print_header_simple("type");
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen doveadm_print_header_simple("last failed");
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen doveadm_print_header_simple("status");
cb3f509b91af4e9cb65ce7acbbba8a335494d6d6Timo Sirainen doveadm_print_header_simple("ping ms");
cb3f509b91af4e9cb65ce7acbbba8a335494d6d6Timo Sirainen doveadm_print_header_simple("input");
cb3f509b91af4e9cb65ce7acbbba8a335494d6d6Timo Sirainen doveadm_print_header_simple("output");
cb3f509b91af4e9cb65ce7acbbba8a335494d6d6Timo Sirainen doveadm_print_header_simple("buffered");
cb3f509b91af4e9cb65ce7acbbba8a335494d6d6Timo Sirainen doveadm_print_header_simple("buffered peak");
cb3f509b91af4e9cb65ce7acbbba8a335494d6d6Timo Sirainen doveadm_print_header_simple("last read");
cb3f509b91af4e9cb65ce7acbbba8a335494d6d6Timo Sirainen doveadm_print_header_simple("last write");
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen director_send(ctx, "DIRECTOR-LIST\n");
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen while ((line = i_stream_read_next_line(ctx->input)) != NULL) {
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen if (*line == '\0')
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen break;
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen T_BEGIN {
cb3f509b91af4e9cb65ce7acbbba8a335494d6d6Timo Sirainen unsigned int i;
20b6e495f623955c680db65447e3f6a8b4c6222fTimo Sirainen time_t ts;
20b6e495f623955c680db65447e3f6a8b4c6222fTimo Sirainen
7a60e1dc9e93ef3f7c7fe1af6385a0bfa1e31bc3Timo Sirainen args = t_strsplit_tabescaped(line);
cb3f509b91af4e9cb65ce7acbbba8a335494d6d6Timo Sirainen for (i = 0; i < 12 && args[i] != NULL; i++) {
cb3f509b91af4e9cb65ce7acbbba8a335494d6d6Timo Sirainen if ((i == 3 || i == 10 || i == 11) &&
cb3f509b91af4e9cb65ce7acbbba8a335494d6d6Timo Sirainen str_to_time(args[i], &ts) == 0) {
cb3f509b91af4e9cb65ce7acbbba8a335494d6d6Timo Sirainen if (ts == 0)
cb3f509b91af4e9cb65ce7acbbba8a335494d6d6Timo Sirainen doveadm_print("never");
cb3f509b91af4e9cb65ce7acbbba8a335494d6d6Timo Sirainen else
cb3f509b91af4e9cb65ce7acbbba8a335494d6d6Timo Sirainen doveadm_print(unixdate2str(ts));
cb3f509b91af4e9cb65ce7acbbba8a335494d6d6Timo Sirainen } else {
cb3f509b91af4e9cb65ce7acbbba8a335494d6d6Timo Sirainen doveadm_print(args[i]);
cb3f509b91af4e9cb65ce7acbbba8a335494d6d6Timo Sirainen }
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen }
cb3f509b91af4e9cb65ce7acbbba8a335494d6d6Timo Sirainen for (; i < 12; i++)
cb3f509b91af4e9cb65ce7acbbba8a335494d6d6Timo Sirainen doveadm_print("-");
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen } T_END;
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen }
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen if (line == NULL)
c300d63f279be299ed07d749c4de7a3443278117Timo Sirainen director_disconnected(ctx);
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen director_disconnect(ctx);
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen}
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomistruct doveadm_cmd_ver2 doveadm_cmd_director[] = {
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi{
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .name = "director status",
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .cmd = cmd_director_status,
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .usage = "[-a <director socket path>] [<user>] [<tag>]",
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_START
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('a', "socket-path", CMD_PARAM_STR, 0)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('\0', "user", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('\0', "tag", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_END
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi},
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi{
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .name = "director map",
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .cmd = cmd_director_map,
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .usage = "[-a <director socket path>] [-f <users file>] [-h | -u] [<host>]",
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_START
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('a', "socket-path", CMD_PARAM_STR, 0)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('f', "users-file", CMD_PARAM_ISTREAM, 0)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('h', "hash-map", CMD_PARAM_BOOL, 0)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('u', "user-map", CMD_PARAM_BOOL, 0)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('\0', "host", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_END
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi},
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi{
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .name = "director add",
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .cmd = cmd_director_add,
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .usage = "[-a <director socket path>] [-t <tag>] <host> [<vhost count>]",
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_START
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('a', "socket-path", CMD_PARAM_STR, 0)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('t', "tag", CMD_PARAM_STR, 0)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('\0', "host", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('\0', "vhost-count", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_END
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi},
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi{
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .name = "director update",
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .cmd = cmd_director_update,
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .usage = "[-a <director socket path>] <host> <vhost count>",
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_START
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('a', "socket-path", CMD_PARAM_STR, 0)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('\0', "host", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('\0', "vhost-count", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_END
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi},
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi{
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .name = "director up",
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .cmd = cmd_director_up,
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .usage = "[-a <director socket path>] <host>",
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_START
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('a', "socket-path", CMD_PARAM_STR, 0)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('\0', "host", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_END
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi},
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi{
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .name = "director down",
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .cmd = cmd_director_down,
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .usage = "[-a <director socket path>] <host>",
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_START
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('a', "socket-path", CMD_PARAM_STR, 0)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('\0', "host", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_END
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi},
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi{
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .name = "director remove",
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .cmd = cmd_director_remove,
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .usage = "[-a <director socket path>] <host>",
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_START
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('a', "socket-path", CMD_PARAM_STR, 0)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('\0', "host", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_END
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi},
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi{
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .name = "director move",
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .cmd = cmd_director_move,
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .usage = "[-a <director socket path>] <user> <host>",
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_START
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('a', "socket-path", CMD_PARAM_STR, 0)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('\0', "user", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('\0', "host", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_END
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi},
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi{
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .name = "director kick",
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .cmd = cmd_director_kick,
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen .usage = "[-a <director socket path>] [-f <passdb field>] <user>",
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_START
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('a', "socket-path", CMD_PARAM_STR, 0)
44a31b74084a66492154dd03f349b73c8aa57c7dTimo SirainenDOVEADM_CMD_PARAM('f', "passdb-field", CMD_PARAM_STR, 0)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('\0', "user", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_END
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi},
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi{
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .name = "director flush",
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .cmd = cmd_director_flush,
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo Sirainen .usage = "[-a <director socket path>] [-F] [--max-parallel <n>] <host>|all",
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_START
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('a', "socket-path", CMD_PARAM_STR, 0)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('F', "force-flush", CMD_PARAM_BOOL, 0)
b79120aa36d1b7935c9aef8b0a7cf3f1045a36caTimo SirainenDOVEADM_CMD_PARAM('\0', "max-parallel", CMD_PARAM_INT64, 0)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('\0', "host", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_END
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi},
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi{
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .name = "director dump",
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .cmd = cmd_director_dump,
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .usage = "[-a <director socket path>]",
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_START
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('a', "socket-path", CMD_PARAM_STR, 0)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_END
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi},
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi{
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .name = "director ring add",
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .cmd = cmd_director_ring_add,
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .usage = "[-a <director socket path>] <ip> [<port>]",
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_START
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('a', "socket-path", CMD_PARAM_STR, 0)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('\0', "ip", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('\0', "port", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_END
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi},
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi{
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .name = "director ring remove",
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .cmd = cmd_director_ring_remove,
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .usage = "[-a <director socket path>] <ip> [<port>]",
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_START
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('a', "socket-path", CMD_PARAM_STR, 0)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('\0', "ip", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('\0', "port", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_END
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi},
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi{
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .name = "director ring status",
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .cmd = cmd_director_ring_status,
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .usage = "[-a <director socket path>]",
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_START
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAM('a', "socket-path", CMD_PARAM_STR, 0)
264a0f242067fb14df778d2fef181ad0045ad0eaAki TuomiDOVEADM_CMD_PARAMS_END
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen};
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomistatic void director_cmd_help(const struct doveadm_cmd_ver2 *cmd)
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen{
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen unsigned int i;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_cmd_director); i++) {
3d76809be2f9f3b5b4110e58eae8613e7c1d6fb7Timo Sirainen if (doveadm_cmd_director[i].cmd == cmd->cmd)
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi help_ver2(&doveadm_cmd_director[i]);
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen }
3d76809be2f9f3b5b4110e58eae8613e7c1d6fb7Timo Sirainen i_unreached();
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenvoid doveadm_register_director_commands(void)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen unsigned int i;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_cmd_director); i++)
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_cmd_register_ver2(&doveadm_cmd_director[i]);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}