diff --git a/src/doveadm/doveadm-proxy.c b/src/doveadm/doveadm-proxy.c index 244f065555..aba622240e 100644 --- a/src/doveadm/doveadm-proxy.c +++ b/src/doveadm/doveadm-proxy.c @@ -41,21 +41,59 @@ cmd_proxy_init(int argc, char *argv[], const char *getopt_args, return ctx; } +static void cmd_proxy_list_header(const char *const *args) +{ + struct { + const char *key; + const char *title; + } header_map[] = { + { "service", "proto" }, + { "src-ip", "src ip" }, + { "dest-ip", "dest ip" }, + { "dest-port", "port" }, + }; + for (unsigned int i = 0; args[i] != NULL; i++) { + const char *arg = args[i]; + + if (strcmp(arg, "username") == 0 || + strncmp(arg, "user_", 5) == 0) { + doveadm_print_header(arg, arg, + DOVEADM_PRINT_HEADER_FLAG_EXPAND); + continue; + } + const char *title = arg; + for (unsigned int j = 0; j < N_ELEMENTS(header_map); j++) { + if (strcmp(header_map[j].key, arg) == 0) { + title = header_map[j].title; + break; + } + } + doveadm_print_header(arg, title, 0); + } +} + static void cmd_proxy_list_callback(enum ipc_client_cmd_state state, - const char *data, void *context ATTR_UNUSED) + const char *data, void *context) { + bool *seen_header = context; + switch (state) { - case IPC_CLIENT_CMD_STATE_REPLY: - T_BEGIN { - const char *const *args = t_strsplit_tab(data); + case IPC_CLIENT_CMD_STATE_REPLY: { + const char *const *args = t_strsplit_tab(data); + + if (!*seen_header) { + cmd_proxy_list_header(args); + *seen_header = TRUE; + } else { for (; *args != NULL; args++) doveadm_print(*args); - } T_END; + } return; + } case IPC_CLIENT_CMD_STATE_OK: break; case IPC_CLIENT_CMD_STATE_ERROR: - i_error("LIST failed: %s", data); + i_error("LIST-FULL failed: %s", data); break; } io_loop_stop(current_ioloop); @@ -64,19 +102,15 @@ static void cmd_proxy_list_callback(enum ipc_client_cmd_state state, static void cmd_proxy_list(int argc, char *argv[]) { struct proxy_context *ctx; + bool seen_header = FALSE; ctx = cmd_proxy_init(argc, argv, "a:", cmd_proxy_list); doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE); - doveadm_print_header("username", "username", DOVEADM_PRINT_HEADER_FLAG_EXPAND); - doveadm_print_header("service", "proto", 0); - doveadm_print_header("src-ip", "src ip", 0); - doveadm_print_header("dest-ip", "dest ip", 0); - doveadm_print_header("dest-port", "port", 0); io_loop_set_running(current_ioloop); - ipc_client_cmd(ctx->ipc, "proxy\t*\tLIST", - cmd_proxy_list_callback, NULL); + ipc_client_cmd(ctx->ipc, "proxy\t*\tLIST-FULL", + cmd_proxy_list_callback, &seen_header); if (io_loop_is_running(current_ioloop)) io_loop_run(current_ioloop); ipc_client_deinit(&ctx->ipc); diff --git a/src/login-common/login-proxy.c b/src/login-common/login-proxy.c index 7ccf1558e9..8f587c26d0 100644 --- a/src/login-common/login-proxy.c +++ b/src/login-common/login-proxy.c @@ -5,7 +5,9 @@ #include "istream.h" #include "ostream.h" #include "llist.h" +#include "array.h" #include "str.h" +#include "strescape.h" #include "str-sanitize.h" #include "time-util.h" #include "master-service.h" @@ -915,30 +917,51 @@ login_proxy_cmd_kick_director_hash(struct ipc_cmd *cmd, const char *const *args) } static void -login_proxy_cmd_list_reply(struct ipc_cmd *cmd, +login_proxy_cmd_list_reply(struct ipc_cmd *cmd, string_t *str, struct login_proxy *proxy) { - T_BEGIN { - const char *reply; + unsigned int i, alt_count = array_count(&global_alt_usernames); - reply = t_strdup_printf("%s\t%s\t%s\t%s\t%u", - proxy->client->virtual_user, - login_binary->protocol, - net_ip2addr(&proxy->client->ip), - net_ip2addr(&proxy->ip), proxy->port); - ipc_cmd_send(cmd, reply); - } T_END; + str_truncate(str, 0); + str_append_tabescaped(str, proxy->client->virtual_user); + str_append_c(str, '\t'); + i = 0; + if (proxy->client->alt_usernames != NULL) { + for (; proxy->client->alt_usernames[i] != NULL; i++) { + str_append_tabescaped(str, proxy->client->alt_usernames[i]); + str_append_c(str, '\t'); + } + i_assert(i <= alt_count); + } + for (; i < alt_count; i++) + str_append_c(str, '\t'); + + str_printfa(str, "%s\t%s\t%s\t%u", login_binary->protocol, + net_ip2addr(&proxy->client->ip), + net_ip2addr(&proxy->ip), proxy->port); + ipc_cmd_send(cmd, str_c(str)); } static void login_proxy_cmd_list(struct ipc_cmd *cmd, const char *const *args ATTR_UNUSED) { struct login_proxy *proxy; + char *const *fieldp; + string_t *str = t_str_new(64); + + str_append(str, "username\t"); + array_foreach(&global_alt_usernames, fieldp) { + str_append_tabescaped(str, *fieldp); + str_append_c(str, '\t'); + } + str_append(str, "service\tsrc-ip\tdest-ip\tdest-port"); + + ipc_cmd_send(cmd, str_c(str)); for (proxy = login_proxies; proxy != NULL; proxy = proxy->next) - login_proxy_cmd_list_reply(cmd, proxy); + login_proxy_cmd_list_reply(cmd, str, proxy); for (proxy = login_proxies_pending; proxy != NULL; proxy = proxy->next) - login_proxy_cmd_list_reply(cmd, proxy); + login_proxy_cmd_list_reply(cmd, str, proxy); ipc_cmd_success(&cmd); } @@ -952,7 +975,7 @@ static void login_proxy_ipc_cmd(struct ipc_cmd *cmd, const char *line) login_proxy_cmd_kick(cmd, args); else if (strcmp(name, "KICK-DIRECTOR-HASH") == 0) login_proxy_cmd_kick_director_hash(cmd, args); - else if (strcmp(name, "LIST") == 0) + else if (strcmp(name, "LIST-FULL") == 0) login_proxy_cmd_list(cmd, args); else ipc_cmd_fail(&cmd, "Unknown command");