doveadm-director.c revision bfef6891565ff9018ac92add6eae401e9352c657
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2009-2016 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;
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;
e256ae453eb7b4495b3491062bce7c66f2fb1d81Timo Sirainen if (!ctx->user_map)
e256ae453eb7b4495b3491062bce7c66f2fb1d81Timo Sirainen director_connect(ctx);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return ctx;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainenstatic void
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomicmd_director_status_user(struct director_context *ctx)
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen{
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen const char *line, *const *args;
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen unsigned int 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) {
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen i_error("Lookup failed");
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen return;
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen }
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen
3c296d819c54e21ce05c3d2eeeedc79be42ac593Timo Sirainen args = t_strsplit_tab(line);
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen if (str_array_length(args) != 4 ||
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen str_to_uint(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
3c296d819c54e21ce05c3d2eeeedc79be42ac593Timo Sirainen args = t_strsplit_tab(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 }
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen if (line == NULL) {
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen i_error("Director disconnected unexpectedly");
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen director_disconnect(ctx);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo 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
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen user = p_new(pool, struct user_list, 1);
0591dbf3c6edb9ad502df0e57a0a458896e632a1Timo Sirainen user->name = p_strdup(pool, username);
e1550f6a31306246a8499f5c9ca876096cbbeae9Timo Sirainen user_hash = mail_user_hash(username, doveadm_settings->director_username_hash);
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;
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen unsigned int ips_count, user_hash, expires;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen
5d16ff58f96527093b49597e8d6168f833e0a52eAki Tuomi ctx = cmd_director_init(cctx);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi 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 */
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi user_hash = mail_user_hash(ctx->host, doveadm_settings->director_username_hash);
3957200d949c6e96c4184db2395444d723950583Timo Sirainen doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE);
3957200d949c6e96c4184db2395444d723950583Timo Sirainen doveadm_print_header("hash", "hash", DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
3957200d949c6e96c4184db2395444d723950583Timo Sirainen doveadm_print(t_strdup_printf("%u", user_hash));
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;
2ea9c5da50bbcb67de03c91ef4cf7778d1e57a22Timo Sirainen else
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (director_get_host(ctx->host, &ips, &ips_count) != 0) return;
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 {
3c296d819c54e21ce05c3d2eeeedc79be42ac593Timo Sirainen args = t_strsplit_tab(line);
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen if (str_array_length(args) < 3 ||
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen str_to_uint(args[0], &user_hash) < 0 ||
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen str_to_uint(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 }
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen if (line == NULL) {
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen i_error("Director disconnected unexpectedly");
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen }
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 }
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 }
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (director_get_host(host, &ips, &ips_count) != 0) return;
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);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (line == NULL || strcmp(line, "OK") != 0) {
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi i_error("%s: %s\n", net_ip2addr(&ips[i]),
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen line == NULL ? "failed" :
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
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (director_get_host(host, &ips, &ips_count) != 0) return;
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;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen } else if (line == NULL || strcmp(line, "OK") != 0) {
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi i_error("%s: %s\n", net_ip2addr(&ips[i]),
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen line == NULL ? "failed" : 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
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi user_hash = mail_user_hash(ctx->user, doveadm_settings->director_username_hash);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (director_get_host(ctx->host, &ips, &ips_count) != 0) return;
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) {
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen i_error("failed");
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
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) {
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen i_error("failed");
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
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
db8ca445e2082fe0b17d593f1f842cf8c40dd6a2Timo Sirainen director_send(ctx, ctx->force_flush ?
db8ca445e2082fe0b17d593f1f842cf8c40dd6a2Timo Sirainen "HOST-FLUSH\n" : "HOST-RESET-USERS\n");
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen line = i_stream_read_next_line(ctx->input);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen if (line == NULL) {
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen i_error("failed");
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
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;
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;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen } else {
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (director_get_host(ctx->host, &ips, &ips_count) != 0) return;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen }
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen for (i = 0; i < ips_count; i++) {
db8ca445e2082fe0b17d593f1f842cf8c40dd6a2Timo Sirainen director_send(ctx, t_strdup_printf("%s\t%s\n",
db8ca445e2082fe0b17d593f1f842cf8c40dd6a2Timo Sirainen ctx->force_flush ? "HOST-FLUSH" : "HOST-RESET-USERS",
db8ca445e2082fe0b17d593f1f842cf8c40dd6a2Timo Sirainen net_ip2addr(&ip)));
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;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen } else if (line == NULL || strcmp(line, "OK") != 0) {
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi i_warning("%s: %s", net_ip2addr(&ips[i]),
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen line == NULL ? "failed" : 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)
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print_formatted_set_format("doveadm director %{command} -a %{socket-path} %{host} %{vhost_count}");
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi else
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print_formatted_set_format("doveadm director %{command} %{host} %{vhost_count}");
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 {
3c296d819c54e21ce05c3d2eeeedc79be42ac593Timo Sirainen args = t_strsplit_tab(line);
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen if (str_array_length(args) >= 2) {
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print("add");
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print(ctx->socket_path);
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi doveadm_print(args[0]);
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 }
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen if (line == NULL) {
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen i_error("Director disconnected unexpectedly");
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen }
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) {
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen i_error("Director disconnected unexpectedly");
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
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 unsigned long l;
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");
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 {
3c296d819c54e21ce05c3d2eeeedc79be42ac593Timo Sirainen args = t_strsplit_tab(line);
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen if (str_array_length(args) >= 5 &&
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen str_to_ulong(args[3], &l) == 0) {
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen doveadm_print(args[0]);
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen doveadm_print(args[1]);
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen doveadm_print(args[2]);
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen if (l == 0)
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen doveadm_print("never");
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen else
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen doveadm_print(unixdate2str(l));
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen doveadm_print(args[4]);
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen }
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen } T_END;
d3af9043837e4bf0e87a9150fedc9e94908e6f82Timo Sirainen }
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen if (line == NULL) {
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen i_error("Director disconnected unexpectedly");
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen }
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)
bfef6891565ff9018ac92add6eae401e9352c657Timo SirainenDOVEADM_CMD_PARAM('\0', "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,
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi .usage = "[-a <director socket path>] [-F] <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)
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++) {
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi if (doveadm_cmd_director+i == cmd)
264a0f242067fb14df778d2fef181ad0045ad0eaAki Tuomi help_ver2(&doveadm_cmd_director[i]);
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen }
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}