]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
doveadm kick: Add -h <dest-host> parameter
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Mon, 17 Jan 2022 11:18:00 +0000 (12:18 +0100)
committerTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 8 Feb 2022 09:48:24 +0000 (10:48 +0100)
src/doveadm/doveadm-kick.c
src/doveadm/doveadm-who.c
src/doveadm/doveadm-who.h

index 2966c803337f1667c4bb921a9cd5be36978399fb..2f23e03403dee762dd7cd00d0a55832c90b7fd2e 100644 (file)
@@ -101,22 +101,30 @@ static void kick_users_via_anvil(struct kick_context *ctx)
 
 static void cmd_kick(struct doveadm_cmd_context *cctx)
 {
-       const char *passdb_field, *const *masks;
+       const char *passdb_field, *dest_host, *const *masks = NULL;
        struct kick_context ctx;
+       struct ip_addr dest_ip;
 
        i_zero(&ctx);
        if (!doveadm_cmd_param_str(cctx, "socket-path", &(ctx.who.anvil_path)))
                ctx.who.anvil_path = t_strconcat(doveadm_settings->base_dir, "/anvil", NULL);
        if (!doveadm_cmd_param_str(cctx, "passdb-field", &passdb_field))
                passdb_field = NULL;
-       if (!doveadm_cmd_param_array(cctx, "mask", &masks)) {
+
+       if (!doveadm_cmd_param_str(cctx, "dest-host", &dest_host))
+               i_zero(&dest_ip);
+       else if (net_addr2ip(dest_host, &dest_ip) < 0)
+               i_fatal("dest-host isn't a valid IP address");
+
+       if (!doveadm_cmd_param_array(cctx, "mask", &masks) &&
+           dest_ip.family == 0) {
                help_ver2(&doveadm_cmd_kick_ver2);
                return;
        }
        ctx.conn_type = cctx->conn_type;
        ctx.who.pool = pool_alloconly_create("kick pids", 10240);
 
-       if (who_parse_args(&ctx.who, passdb_field, masks) != 0) {
+       if (who_parse_args(&ctx.who, passdb_field, &dest_ip, masks) != 0) {
                pool_unref(&ctx.who.pool);
                return;
        }
@@ -126,6 +134,7 @@ static void cmd_kick(struct doveadm_cmd_context *cctx)
        doveadm_print_header_simple("count");
 
        if (ctx.who.filter.net_bits == 0 &&
+           ctx.who.filter.dest_ip.family == 0 &&
            strpbrk(ctx.who.filter.username, "*?") == NULL) {
                /* kick a single [alternative] user's all connections */
                p_array_init(&ctx.kicks, ctx.who.pool, 1);
@@ -144,10 +153,11 @@ static void cmd_kick(struct doveadm_cmd_context *cctx)
 struct doveadm_cmd_ver2 doveadm_cmd_kick_ver2 = {
        .name = "kick",
        .cmd = cmd_kick,
-       .usage = "[-a <anvil socket path>] [-f <passdb field>] <user mask>[|]<ip/bits>",
+       .usage = "[-a <anvil socket path>] [-f <passdb field>] [-h <dest host>] <user mask>[|]<ip/bits>",
 DOVEADM_CMD_PARAMS_START
 DOVEADM_CMD_PARAM('a',"socket-path",CMD_PARAM_STR,0)
 DOVEADM_CMD_PARAM('f',"passdb-field",CMD_PARAM_STR,0)
+DOVEADM_CMD_PARAM('h',"dest-host",CMD_PARAM_STR,0)
 DOVEADM_CMD_PARAM('\0',"mask",CMD_PARAM_ARRAY,CMD_PARAM_FLAG_POSITIONAL)
 DOVEADM_CMD_PARAMS_END
 };
index 959cd7925f8f0541847f88d7d501fb9087b7afef..93cc9188a09e41c3a0e4ce4f5991457c7af53efa 100644 (file)
@@ -156,8 +156,8 @@ static void who_aggregate_line(struct who_context *ctx,
                array_push_back(&user->pids, &line->pid);
 }
 
-int who_parse_args(struct who_context *ctx, const char *alt_username_field,
-                  const char *const *masks)
+static int
+who_parse_masks(struct who_context *ctx, const char *const *masks)
 {
        struct ip_addr net_ip;
        unsigned int i, net_bits;
@@ -181,6 +181,19 @@ int who_parse_args(struct who_context *ctx, const char *alt_username_field,
                        ctx->filter.username = masks[i];
                }
        }
+       return 0;
+}
+
+int who_parse_args(struct who_context *ctx, const char *alt_username_field,
+                  const struct ip_addr *dest_ip, const char *const *masks)
+{
+       if (dest_ip != NULL)
+               ctx->filter.dest_ip = *dest_ip;
+
+       if (masks != NULL) {
+               if (who_parse_masks(ctx, masks) < 0)
+                       return -1;
+       }
        if (alt_username_field != NULL && ctx->filter.username == NULL) {
                i_error("Username must be given with passdb-field parameter");
                doveadm_exit_code = EX_USAGE;
@@ -397,6 +410,10 @@ bool who_line_filter_match(const struct who_line *line,
                                       filter->net_bits))
                        return FALSE;
        }
+       if (filter->dest_ip.family != 0) {
+               if (!net_ip_compare(&line->dest_ip, &filter->dest_ip))
+                       return FALSE;
+       }
        return TRUE;
 }
 
@@ -438,7 +455,7 @@ static void cmd_who(struct doveadm_cmd_context *cctx)
        hash_table_create(&ctx.users, ctx.pool, 0, who_user_hash, who_user_cmp);
 
        if (doveadm_cmd_param_array(cctx, "mask", &masks)) {
-               if (who_parse_args(&ctx, passdb_field, masks) != 0) {
+               if (who_parse_args(&ctx, passdb_field, NULL, masks) != 0) {
                        hash_table_destroy(&ctx.users);
                        pool_unref(&ctx.pool);
                        return;
index c24c23ffb0bc7f126cb0f385af13cb3d062f1d64..429a39ca8cfba42b157c689373fa57cb900049b4 100644 (file)
@@ -20,6 +20,8 @@ struct who_filter {
        const char *alt_username_field;
        unsigned int alt_username_idx;
 
+       struct ip_addr dest_ip;
+
        struct ip_addr net_ip;
        unsigned int net_bits;
 };
@@ -36,7 +38,7 @@ typedef void who_callback_t(struct who_context *ctx,
                            const struct who_line *line);
 
 int who_parse_args(struct who_context *ctx, const char *alt_username_field,
-                  const char *const *masks);
+                  const struct ip_addr *dest_ip, const char *const *masks);
 
 bool who_line_filter_match(const struct who_line *line,
                           const struct who_filter *filter);