unsigned int refcount;
};
+/* Track only non-proxying sessions for mail_max_userip_connections. Otherwise
+ if the same server is acting as both proxy and backend the connection could
+ be counted twice. */
+#define SESSION_TRACK_USERIP(session) \
+ ((session)->dest_ip.family == 0)
+
struct connect_limit {
struct str_table *strings;
/* username => struct session linked list */
HASH_TABLE(char *, struct session *) user_hash;
- /* userip => unsigned int refcount */
+ /* userip => unsigned int refcount. Only track for sessions where
+ SESSION_TRACK_USERIP() returns TRUE. */
HASH_TABLE(struct userip *, void *) userip_hash;
/* conn_guid => struct session */
HASH_TABLE(const uint8_t *, struct session *) session_hash;
first_user_session = NULL;
}
+ session = i_new(struct session, 1);
+ guid_128_copy(session->conn_guid, conn_guid);
+ if (dest_ip != NULL)
+ session->dest_ip = *dest_ip;
+ T_BEGIN {
+ session_set_alt_usernames(limit, session, alt_usernames);
+ } T_END;
+
struct userip userip_lookup = {
.username = username,
.service = key->service,
.ip = key->ip,
};
- if (!hash_table_lookup_full(limit->userip_hash, &userip_lookup,
+
+ if (!SESSION_TRACK_USERIP(session) ||
+ !hash_table_lookup_full(limit->userip_hash, &userip_lookup,
&userip, &value)) {
userip = i_new(struct userip, 1);
userip->username = username;
userip->service = str_table_ref(limit->strings, key->service);
userip->ip = key->ip;
value = POINTER_CAST(1);
- hash_table_insert(limit->userip_hash, userip, value);
+ if (SESSION_TRACK_USERIP(session))
+ hash_table_insert(limit->userip_hash, userip, value);
} else {
value = POINTER_CAST(POINTER_CAST_TO(value, unsigned int) + 1);
hash_table_update(limit->userip_hash, userip, value);
}
-
- session = i_new(struct session, 1);
session->userip = userip;
- guid_128_copy(session->conn_guid, conn_guid);
- if (dest_ip != NULL)
- session->dest_ip = *dest_ip;
- T_BEGIN {
- session_set_alt_usernames(limit, session, alt_usernames);
- } T_END;
session_link_process(limit, session, pid, kick_type);
const uint8_t *conn_guid_p = session->conn_guid;
hash_table_update(limit->user_hash, username, session);
}
+static void userip_free(struct connect_limit *limit, struct userip *userip)
+{
+ str_table_unref(limit->strings, &userip->service);
+ i_free(userip);
+}
+
static void
-session_free(struct connect_limit *limit, struct session *session)
+userip_hash_unref(struct connect_limit *limit, struct session *session)
{
struct userip *userip = session->userip;
- struct session *first_user_session;
- const char *username = userip->username;
- char *orig_username;
void *value;
unsigned int new_refcount;
hash_table_update(limit->userip_hash, userip, value);
} else {
hash_table_remove(limit->userip_hash, userip);
- str_table_unref(limit->strings, &userip->service);
- i_free(userip);
+ userip_free(limit, userip);
}
+}
+
+static void
+session_free(struct connect_limit *limit, struct session *session)
+{
+ struct session *first_user_session;
+ char *orig_username;
+ const char *username = session->userip->username;
+
+ if (SESSION_TRACK_USERIP(session))
+ userip_hash_unref(limit, session);
+ else
+ userip_free(limit, session->userip);
if (!hash_table_lookup_full(limit->user_hash, username,
&orig_username, &first_user_session))
struct ip_addr dest_ip;
i_zero(&dest_ip);
test_assert(net_addr2ip("1.2.3.4", &key.ip) == 0);
- test_assert(net_addr2ip("55.44.33.22", &dest_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"\t55.44.33.22\n"
+#define TEST_SESSION1_STR "501\tuser1\tservice1\t1.2.3.4\t"SESSION1_HEX"\t\n"
test_session_dump(limit, TEST_SESSION1_STR);
test_assert(connect_limit_lookup(limit, &key) == 1);
#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);
test_assert(connect_limit_lookup(limit, &key) == 2);
- test_assert(connect_limit_lookup(limit, &key3) == 1);
+ test_assert(connect_limit_lookup(limit, &key3) == 0);
/* duplicate conn-guid */
struct connect_limit_key key4 = {