From: Timo Sirainen Date: Mon, 2 Jun 2014 01:00:19 +0000 (+0300) Subject: doveadm director kick command added. X-Git-Tag: 2.2.14.rc1~452 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=550d2fe097e95f12e8fa60ef52753ea7fe53d4ea;p=thirdparty%2Fdovecot%2Fcore.git doveadm director kick command added. The kick gets sent to all the proxies within the director ring. --- diff --git a/src/director/director-connection.c b/src/director/director-connection.c index a1018e9359..e9c9ed5b11 100644 --- a/src/director/director-connection.c +++ b/src/director/director-connection.c @@ -938,6 +938,25 @@ director_cmd_user_move(struct director_connection *conn, return TRUE; } +static bool +director_cmd_user_kick(struct director_connection *conn, + const char *const *args) +{ + struct director_host *dir_host; + int ret; + + if ((ret = director_cmd_is_seen(conn, &args, &dir_host)) != 0) + return ret > 0; + + if (str_array_length(args) != 1) { + director_cmd_error(conn, "Invalid parameters"); + return FALSE; + } + + director_kick_user(conn->dir, conn->host, dir_host, args[0]); + return TRUE; +} + static bool director_cmd_user_killed(struct director_connection *conn, const char *const *args) @@ -1316,6 +1335,8 @@ director_connection_handle_cmd(struct director_connection *conn, return director_cmd_host_flush(conn, args); if (strcmp(cmd, "USER-MOVE") == 0) return director_cmd_user_move(conn, args); + if (strcmp(cmd, "USER-KICK") == 0) + return director_cmd_user_kick(conn, args); if (strcmp(cmd, "USER-KILLED") == 0) return director_cmd_user_killed(conn, args); if (strcmp(cmd, "USER-KILLED-EVERYWHERE") == 0) diff --git a/src/director/director.c b/src/director/director.c index 9757a8a121..e02e2ab967 100644 --- a/src/director/director.c +++ b/src/director/director.c @@ -756,6 +756,32 @@ void director_move_user(struct director *dir, struct director_host *src, user->username_hash, net_ip2addr(&user->host->ip))); } +static void +director_kick_user_callback(enum ipc_client_cmd_state state ATTR_UNUSED, + const char *data ATTR_UNUSED, + void *context ATTR_UNUSED) +{ +} + +void director_kick_user(struct director *dir, struct director_host *src, + struct director_host *orig_src, const char *username) +{ + const char *cmd; + + cmd = t_strdup_printf("proxy\t*\tKICK\t%s", username); + ipc_client_cmd(dir->ipc_proxy, cmd, + director_kick_user_callback, (void *)NULL); + + if (orig_src == NULL) { + orig_src = dir->self_host; + orig_src->last_seq++; + } + cmd = t_strdup_printf("USER-KICK\t%s\t%u\t%u\t%s\n", + net_ip2addr(&orig_src->ip), orig_src->port, orig_src->last_seq, + username); + director_update_send_version(dir, src, DIRECTOR_VERSION_USER_KICK, cmd); +} + void director_user_killed(struct director *dir, unsigned int username_hash) { struct user *user; diff --git a/src/director/director.h b/src/director/director.h index 1b97cbf4b4..87f789a14f 100644 --- a/src/director/director.h +++ b/src/director/director.h @@ -6,14 +6,16 @@ #define DIRECTOR_VERSION_NAME "director" #define DIRECTOR_VERSION_MAJOR 1 -#define DIRECTOR_VERSION_MINOR 3 +#define DIRECTOR_VERSION_MINOR 4 -/* weak users supported in protocol v1.1+ */ +/* weak users supported in protocol */ #define DIRECTOR_VERSION_WEAK_USERS 1 -/* director removes supported in v1.2+ */ +/* director ring remove supported */ #define DIRECTOR_VERSION_RING_REMOVE 2 -/* quit reason supported in v1.3+ */ +/* quit reason supported */ #define DIRECTOR_VERSION_QUIT 3 +/* user-kick supported */ +#define DIRECTOR_VERSION_USER_KICK 4 /* Minimum time between even attempting to communicate with a director that failed due to a protocol error. */ @@ -131,6 +133,9 @@ void director_move_user(struct director *dir, struct director_host *src, struct director_host *orig_src, unsigned int username_hash, struct mail_host *host) ATTR_NULL(3); +void director_kick_user(struct director *dir, struct director_host *src, + struct director_host *orig_src, const char *username) + ATTR_NULL(3); void director_user_killed(struct director *dir, unsigned int username_hash); void director_user_killed_everywhere(struct director *dir, struct director_host *src, diff --git a/src/director/doveadm-connection.c b/src/director/doveadm-connection.c index 66bf568348..02442d8df9 100644 --- a/src/director/doveadm-connection.c +++ b/src/director/doveadm-connection.c @@ -380,6 +380,22 @@ doveadm_cmd_user_move(struct doveadm_connection *conn, const char *line) return TRUE; } +static bool +doveadm_cmd_user_kick(struct doveadm_connection *conn, const char *line) +{ + const char *const *args; + + args = t_strsplit_tab(line); + if (args[0] == NULL) { + i_error("doveadm sent invalid USER-KICK parameters: %s", line); + return FALSE; + } + + director_kick_user(conn->dir, conn->dir->self_host, NULL, args[0]); + o_stream_nsend(conn->output, "OK\n", 3); + return TRUE; +} + static void doveadm_connection_input(struct doveadm_connection *conn) { const char *line, *cmd, *args; @@ -434,6 +450,8 @@ static void doveadm_connection_input(struct doveadm_connection *conn) ret = doveadm_cmd_user_list(conn, args); else if (strcmp(cmd, "USER-MOVE") == 0) ret = doveadm_cmd_user_move(conn, args); + else if (strcmp(cmd, "USER-KICK") == 0) + ret = doveadm_cmd_user_kick(conn, args); else { i_error("doveadm sent unknown command: %s", line); ret = FALSE; diff --git a/src/doveadm/doveadm-director.c b/src/doveadm/doveadm-director.c index 6aff6d0010..65c6730467 100644 --- a/src/doveadm/doveadm-director.c +++ b/src/doveadm/doveadm-director.c @@ -500,6 +500,32 @@ static void cmd_director_move(int argc, char *argv[]) director_disconnect(ctx); } +static void cmd_director_kick(int argc, char *argv[]) +{ + struct director_context *ctx; + const char *username, *line; + + ctx = cmd_director_init(argc, argv, "a:", cmd_director_kick); + if (argv[optind] == NULL || argv[optind+1] != NULL) + director_cmd_help(cmd_director_kick); + + username = argv[optind]; + + director_send(ctx, t_strdup_printf("USER-KICK\t%s\n", username)); + line = i_stream_read_next_line(ctx->input); + if (line == NULL) { + i_error("failed"); + doveadm_exit_code = EX_TEMPFAIL; + } else if (strcmp(line, "OK") == 0) { + if (doveadm_verbose) + printf("User %s kicked\n", username); + } else { + i_error("failed: %s", line); + doveadm_exit_code = EX_TEMPFAIL; + } + director_disconnect(ctx); +} + static void cmd_director_flush_all(struct director_context *ctx) { const char *line; @@ -729,6 +755,8 @@ struct doveadm_cmd doveadm_cmd_director[] = { "[-a ] " }, { cmd_director_move, "director move", "[-a ] " }, + { cmd_director_kick, "director kick", + "[-a ] " }, { cmd_director_flush, "director flush", "[-a ] |all" }, { cmd_director_dump, "director dump",