doveadm-connection.c revision 6f5310d61cb7235ae5b3f42a3cd27605ace770c4
/* Copyright (c) 2010-2017 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.h"
#include "net.h"
#include "istream.h"
#include "ostream.h"
#include "array.h"
#include "str.h"
#include "strescape.h"
#include "llist.h"
#include "master-service.h"
#include "user-directory.h"
#include "mail-host.h"
#include "director.h"
#include "director-host.h"
#include "director-request.h"
#include "director-connection.h"
#include "doveadm-connection.h"
#include <unistd.h>
#define DOVEADM_PROTOCOL_VERSION_MAJOR 1
#define DOVEADM_HANDSHAKE "VERSION\tdirector-doveadm\t1\t0\n"
#define MAX_VALID_VHOST_COUNT 1000
#define DEFAULT_MAX_MOVING_USERS 100
enum doveadm_director_cmd_ret {
};
struct director_reset_cmd {
struct doveadm_connection *_conn;
struct director_user_iter *iter;
unsigned int host_idx, hosts_count;
unsigned int max_moving_users;
};
struct doveadm_connection {
int fd;
struct director_reset_cmd *reset_cmd;
bool handshaked:1;
};
static struct doveadm_connection *doveadm_connections;
static enum doveadm_director_cmd_ret
const char *const *args ATTR_UNUSED)
{
(*hostp)->user_count);
(long)(*hostp)->last_updown_change);
}
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
static enum doveadm_director_cmd_ret
const char *const *args ATTR_UNUSED)
{
struct mail_host_list *orig_hosts_list;
unsigned int i, j, orig_hosts_count, cur_hosts_count;
int ret;
NULL);
/* the hosts are sorted by IP */
for (i = j = 0; i < orig_hosts_count && j < cur_hosts_count; ) {
if (ret == 0)
i++, j++;
else if (ret > 0)
j++;
else {
i++;
}
}
for (; i < orig_hosts_count; i++)
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
{
if (!dir->ring_handshaked)
else if (dir->ring_synced)
else {
}
}
static void
{
else if (director_connection_is_synced(conn))
else
}
static void
const struct director_host *host,
{
else {
/* we might have a connection that is being connected */
struct director_connection *const *connp;
break;
}
}
}
}
static enum doveadm_director_cmd_ret
const char *const *args ATTR_UNUSED)
{
struct director_host *const *hostp;
const char *type;
type = "removed";
type = "self";
else if (left)
else if (right)
type = "right";
else
type = "";
(unsigned long)last_failed);
else
}
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
static enum doveadm_director_cmd_ret
const char *const *args)
{
struct director_host *host;
i_error("doveadm sent invalid DIRECTOR-ADD parameters");
return DOVEADM_DIRECTOR_CMD_RET_FAIL;
}
}
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
static enum doveadm_director_cmd_ret
const char *const *args)
{
struct director_host *host;
i_error("doveadm sent invalid DIRECTOR-REMOVE parameters");
return DOVEADM_DIRECTOR_CMD_RET_FAIL;
}
else {
}
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
static enum doveadm_director_cmd_ret
{
unsigned int vhost_count = UINT_MAX;
tag = "";
else
}
i_error("doveadm sent invalid %s parameters",
return DOVEADM_DIRECTOR_CMD_RET_FAIL;
}
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
if (update) {
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
return DOVEADM_DIRECTOR_CMD_RET_OK;
"host is already being updated - try again later\n");
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
if (vhost_count != UINT_MAX)
/* NOTE: we don't support changing a tag for an existing host.
it needs to be removed first. otherwise it would be a bit ugly to
handle. */
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
static enum doveadm_director_cmd_ret
{
}
static enum doveadm_director_cmd_ret
{
}
static enum doveadm_director_cmd_ret
const char *const *args)
{
i_error("doveadm sent invalid %s parameters: %s",
return DOVEADM_DIRECTOR_CMD_RET_FAIL;
}
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
;
"host is already being updated - try again later\n");
return DOVEADM_DIRECTOR_CMD_RET_OK;
} else {
}
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
static enum doveadm_director_cmd_ret
const char *const *args)
{
}
static enum doveadm_director_cmd_ret
const char *const *args)
{
}
static enum doveadm_director_cmd_ret
const char *const *args)
{
i_error("doveadm sent invalid HOST-REMOVE parameters");
return DOVEADM_DIRECTOR_CMD_RET_FAIL;
}
else {
}
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
static void
{
unsigned int total_user_count = 0;
}
i_warning("Flushed all backend hosts with %u users. This is an unsafe "
"operation and may cause the same users to end up in multiple backends.",
}
static enum doveadm_director_cmd_ret
{
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
i_error("doveadm sent invalid HOST-FLUSH parameters");
return DOVEADM_DIRECTOR_CMD_RET_FAIL;
}
else {
}
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
{
}
static bool
{
return FALSE;
continue;
} T_END;
break;
}
}
static bool
{
unsigned int count;
return FALSE;
}
}
return TRUE;
}
static enum doveadm_director_cmd_ret
const char *const *args)
{
struct director_reset_cmd *cmd;
unsigned int i = 0, count;
unsigned int max_moving_users = DEFAULT_MAX_MOVING_USERS;
i_error("doveadm sent invalid HOST-RESET-USERS parameters");
return DOVEADM_DIRECTOR_CMD_RET_FAIL;
}
i_error("doveadm sent invalid HOST-RESET-USERS ip: %s",
args[0]);
return DOVEADM_DIRECTOR_CMD_RET_FAIL;
}
for (i = 0; i < count; i++) {
break;
}
if (i == count) {
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
count = i+1;
}
if (!director_reset_cmd_run(cmd)) {
/* we still have work to do. don't handle any more doveadm
input until we're finished. */
}
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
static enum doveadm_director_cmd_ret
const char *const *args)
{
unsigned int username_hash;
username = "";
tag = "";
} else {
}
username, &username_hash)) {
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
}
/* get user's current host */
else {
}
/* get host if it wasn't in user directory */
else
/* get host with default configuration */
username_hash, tag);
else
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
static enum doveadm_director_cmd_ret
{
struct director_user_iter *iter;
i_error("doveadm sent invalid USER-LIST parameters");
return DOVEADM_DIRECTOR_CMD_RET_FAIL;
}
} else {
}
"%u\t%u\t%s\n",
} T_END;
}
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
static enum doveadm_director_cmd_ret
{
unsigned int username_hash;
i_error("doveadm sent invalid USER-MOVE parameters");
return DOVEADM_DIRECTOR_CMD_RET_FAIL;
}
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
args[0], &username_hash)) {
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
}
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
} else {
/* already the correct host. reset the user's timeout. */
}
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
static enum doveadm_director_cmd_ret
{
i_error("doveadm sent invalid USER-KICK parameters");
return DOVEADM_DIRECTOR_CMD_RET_FAIL;
}
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
static enum doveadm_director_cmd_ret
{
i_error("doveadm sent invalid USER-KICK-ALT parameters");
return DOVEADM_DIRECTOR_CMD_RET_FAIL;
}
return DOVEADM_DIRECTOR_CMD_RET_OK;
}
struct {
const char *name;
enum doveadm_director_cmd_ret (*cmd)
} doveadm_director_commands[] = {
{ "HOST-LIST", doveadm_cmd_host_list },
{ "HOST-LIST-REMOVED", doveadm_cmd_host_list_removed },
{ "DIRECTOR-LIST", doveadm_cmd_director_list },
{ "DIRECTOR-ADD", doveadm_cmd_director_add },
{ "DIRECTOR-REMOVE", doveadm_cmd_director_remove },
{ "HOST-SET", doveadm_cmd_host_set },
{ "HOST-UPDATE", doveadm_cmd_host_update },
{ "HOST-UP", doveadm_cmd_host_up },
{ "HOST-DOWN", doveadm_cmd_host_down },
{ "HOST-REMOVE", doveadm_cmd_host_remove },
{ "HOST-FLUSH", doveadm_cmd_host_flush },
{ "HOST-RESET-USERS", doveadm_cmd_host_reset_users },
{ "USER-LOOKUP", doveadm_cmd_user_lookup },
{ "USER-LIST", doveadm_cmd_user_list },
{ "USER-MOVE", doveadm_cmd_user_move },
{ "USER-KICK", doveadm_cmd_user_kick },
{ "USER-KICK-ALT", doveadm_cmd_user_kick_alt },
};
static enum doveadm_director_cmd_ret
{
i_error("doveadm sent empty command line");
return DOVEADM_DIRECTOR_CMD_RET_FAIL;
}
args++;
for (unsigned int i = 0; i < N_ELEMENTS(doveadm_director_commands); i++) {
}
return DOVEADM_DIRECTOR_CMD_RET_FAIL;
}
{
const char *line;
if (!conn->handshaked) {
return;
}
i_error("doveadm not compatible with this server "
"(mixed old and new binaries?)");
return;
}
}
T_BEGIN {
} T_END;
}
}
{
}
struct doveadm_connection *
{
struct doveadm_connection *conn;
return conn;
}
{
/* finish the move even if doveadm disconnected */
}
i_error("close(doveadm connection) failed: %m");
}
void doveadm_connections_deinit(void)
{
while (reset_cmds != NULL)
while (doveadm_connections != NULL) {
}
}
void doveadm_connections_continue_reset_cmds(void)
{
while (reset_cmds != NULL) {
if (!director_reset_cmd_run(reset_cmds))
break;
}
}