struct hash_iterate_context *iter;
struct session *session;
const uint8_t *conn_guid;
+ const struct alt_username_field *alt_field;
+ unsigned int alt_idx;
string_t *str = str_new(default_pool, 256);
ssize_t ret = 0;
+ /* Send list of alt usernames in the header */
+ array_foreach(&limit->alt_username_fields, alt_field) {
+ if (str_len(str) > 0)
+ str_append_c(str, '\t');
+ str_append_tabescaped(str, alt_field->name);
+ }
+ str_append_c(str, '\n');
+ o_stream_nsend(output, str_data(str), str_len(str));
+
+ /* Send all sessions */
iter = hash_table_iterate_init(limit->session_hash);
while (ret >= 0 &&
hash_table_iterate(iter, limit->session_hash,
str_append_c(str, '\t');
if (session->dest_ip.family != 0)
str_append(str, net_ip2addr(&session->dest_ip));
+ for (alt_idx = 0; alt_idx < session->alt_usernames_count; alt_idx++) {
+ str_append_c(str, '\t');
+ if (session->alt_usernames[alt_idx].alt_username != NULL) {
+ str_append_tabescaped(str,
+ session->alt_usernames[alt_idx].alt_username);
+ }
+ }
str_append_c(str, '\n');
ret = o_stream_send(output, str_data(str), str_len(str));
} T_END;
#define SESSION3_HEX "300000000000000000000000000000f3"
static void
-test_session_dump(struct connect_limit *limit, const char *expected_dump)
+test_session_dump(struct connect_limit *limit, const char *expected_altnames,
+ const char *expected_dump)
{
string_t *str = str_new(default_pool, 128);
struct ostream *output = o_stream_create_buffer(str);
str_free(&str);
return;
}
+
+ /* check the alt usernames header */
+ const char *p = strchr(str_c(str), '\n');
+ if (p == NULL) {
+ test_assert(str_len(str) == 0);
+ test_assert_strcmp(expected_altnames, "");
+ } else {
+ test_assert_strcmp(expected_altnames,
+ t_strndup(str_c(str), p - str_c(str)));
+ str_delete(str, 0, p - str_c(str) + 1);
+ }
+
/* The output comes from hash table, so the order isn't stable.
Sort the lines so we can test it. */
const char **lines = t_strsplit(str_c(str), "\n");
unsigned int lines_count = str_array_length(lines);
i_qsort(lines, lines_count, sizeof(const char *), i_strcmp_p);
- string_t *new_str = t_str_new(str_len(str));
+ string_t *new_str = str_new(default_pool, str_len(str));
/* the output ends with \n\n and they're sorted first */
i_assert(lines_count >= 2);
i_assert(lines[0][0] == '\0');
str_append_c(new_str, '\n');
}
test_assert_strcmp(str_c(new_str), expected_dump);
+ str_free(&new_str);
o_stream_destroy(&output);
str_free(&str);
test_assert(net_addr2ip("1.2.3.4", &key.ip) == 0);
connect_limit_connect(limit, 501, &key, session1_guid, KICK_TYPE_NONE,
&dest_ip, alt_usernames1);
-#define TEST_SESSION1_STR "501\tuser1\tservice1\t1.2.3.4\t"SESSION1_HEX"\t\n"
- test_session_dump(limit, TEST_SESSION1_STR);
+#define TEST_SESSION1_STR "501\tuser1\tservice1\t1.2.3.4\t"SESSION1_HEX"\t\taltvalueA\taltvalueB\n"
+ test_session_dump(limit, "altkey1\taltkey2", TEST_SESSION1_STR);
test_assert(connect_limit_lookup(limit, &key) == 1);
/* same userip and pid */
i_zero(&dest_ip);
connect_limit_connect(limit, 501, &key2, session2_guid, KICK_TYPE_NONE,
&dest_ip, alt_usernames2);
-#define TEST_SESSION2_STR "501\tuser1\tservice1\t1.2.3.4\t"SESSION2_HEX"\t\n"
- test_session_dump(limit, TEST_SESSION1_STR TEST_SESSION2_STR);
+#define TEST_SESSION2_STR "501\tuser1\tservice1\t1.2.3.4\t"SESSION2_HEX"\t\taltvalueA\taltvalueC\taltvalueA\n"
+ test_session_dump(limit, "altkey1\taltkey2\taltkey3",
+ TEST_SESSION1_STR TEST_SESSION2_STR);
test_assert(connect_limit_lookup(limit, &key) == 2);
/* different user */
test_assert(net_addr2ip("1.0.0.2", &dest_ip) == 0);
connect_limit_connect(limit, 600, &key3, session3_guid, KICK_TYPE_SIGNAL,
&dest_ip, alt_usernames3);
-#define TEST_SESSION3_STR "600\tuser2\tservice2\t4.3.2.1\t"SESSION3_HEX"\t1.0.0.2\n"
- test_session_dump(limit, TEST_SESSION1_STR TEST_SESSION2_STR TEST_SESSION3_STR);
+#define TEST_SESSION3_STR "600\tuser2\tservice2\t4.3.2.1\t"SESSION3_HEX"\t1.0.0.2\taltvalueA\taltvalueC\t\taltvalueD\n"
+ test_session_dump(limit, "altkey1\taltkey2\taltkey3\taltkey4",
+ TEST_SESSION1_STR TEST_SESSION2_STR TEST_SESSION3_STR);
test_assert(connect_limit_lookup(limit, &key) == 2);
test_assert(connect_limit_lookup(limit, &key3) == 0);
connect_limit_connect(limit, 600, &key4, session2_guid, KICK_TYPE_SIGNAL,
&dest_ip, alt_usernames3);
test_expect_no_more_errors();
- test_session_dump(limit, TEST_SESSION1_STR TEST_SESSION2_STR TEST_SESSION3_STR);
+ test_session_dump(limit, "altkey1\taltkey2\taltkey3\taltkey4",
+ TEST_SESSION1_STR TEST_SESSION2_STR TEST_SESSION3_STR);
/* test user iteration for user1 */
struct connect_limit_iter *iter =
/* disconnect a single session */
connect_limit_disconnect(limit, 600, &key3, session3_guid);
- test_session_dump(limit, TEST_SESSION1_STR TEST_SESSION2_STR);
+ test_session_dump(limit, "altkey1\taltkey2\taltkey3\taltkey4",
+ TEST_SESSION1_STR TEST_SESSION2_STR);
test_assert(connect_limit_lookup(limit, &key) == 2);
test_assert(connect_limit_lookup(limit, &key3) == 0);
/* disconnect all sessions from a process */
connect_limit_disconnect_pid(limit, 501);
- test_session_dump(limit, "");
+ test_session_dump(limit, "altkey1\taltkey2\taltkey3\taltkey4", "");
test_assert(connect_limit_lookup(limit, &key3) == 0);
connect_limit_deinit(&limit);
struct doveadm_who_iter {
struct istream *input;
pool_t pool, line_pool;
+
+ unsigned int alt_username_fields_count;
+ const char **alt_username_fields;
+
bool failed;
};
const char *const *args = t_strsplit_tabescaped(line);
i_zero(line_r);
- /* <pid> <username> <service> <ip> <conn-guid> <dest-ip> */
+ /* <pid> <username> <service> <ip> <conn-guid> <dest-ip>
+ [alt usernames] */
if (str_array_length(args) < 6)
return -1;
if (net_addr2ip(args[5], &line_r->dest_ip) < 0)
return -1;
}
+ line_r->alt_usernames = p_strarray_dup(iter->line_pool, args + 6);
return 0;
}
if ((line = i_stream_read_next_line(iter->input)) == NULL) {
i_error("anvil didn't send header line");
iter->failed = TRUE;
+ } else {
+ iter->alt_username_fields =
+ (const char **)p_strsplit_tabescaped(iter->pool, line);
+ iter->alt_username_fields_count =
+ str_array_length(iter->alt_username_fields);
}
return iter;
}
return TRUE;
}
-static void who_print_line(struct who_context *ctx,
- const struct who_line *line)
+static void
+who_print_line(struct who_context *ctx, struct doveadm_who_iter *iter,
+ const struct who_line *line)
{
+ unsigned int alt_idx;
+
if (!who_line_filter_match(line, &ctx->filter))
return;
doveadm_print(dec2str(line->pid));
doveadm_print(net_ip2addr(&line->ip));
doveadm_print(net_ip2addr(&line->dest_ip));
+
+ for (alt_idx = 0; line->alt_usernames[alt_idx] != NULL; alt_idx++)
+ doveadm_print(line->alt_usernames[alt_idx]);
+ for (; alt_idx < iter->alt_username_fields_count; alt_idx++)
+ doveadm_print("");
}
static void cmd_who(struct doveadm_cmd_context *cctx)
doveadm_print_header_simple("pid");
doveadm_print_header_simple("ip");
doveadm_print_header_simple("dest_ip");
+ for (unsigned int i = 0; i < iter->alt_username_fields_count; i++)
+ doveadm_print_header_simple(iter->alt_username_fields[i]);
while (doveadm_who_iter_next(iter, &who_line))
- who_print_line(&ctx, &who_line);
+ who_print_line(&ctx, iter, &who_line);
}
if (doveadm_who_iter_deinit(&iter) < 0)
doveadm_exit_code = EX_TEMPFAIL;