const char *const *args, const char **error_r)
{
const char *cmd = args[0];
+ guid_128_t conn_guid;
struct connect_limit_key key;
unsigned int value, checksum;
time_t stamp;
*error_r = "CONNECT: Invalid ident string";
return -1;
}
- connect_limit_connect(connect_limit, pid, &key);
+ if (args[0] == NULL) {
+ *error_r = "CONNECT: Missing conn-guid";
+ return -1;
+ }
+ if (guid_128_from_string(args[0], conn_guid) < 0) {
+ *error_r = "CONNECT: Invalid conn-guid";
+ return -1;
+ }
+ connect_limit_connect(connect_limit, pid, &key, conn_guid);
} else if (strcmp(cmd, "DISCONNECT") == 0) {
if (args[0] == NULL || args[1] == NULL) {
*error_r = "DISCONNECT: Not enough parameters";
*error_r = "DISCONNECT: Invalid ident string";
return -1;
}
- connect_limit_disconnect(connect_limit, pid, &key);
+ if (args[0] == NULL) {
+ *error_r = "DISCONNECT: Missing conn-guid";
+ return -1;
+ }
+ if (guid_128_from_string(args[0], conn_guid) < 0) {
+ *error_r = "DISCONNECT: Invalid conn-guid";
+ return -1;
+ }
+ connect_limit_disconnect(connect_limit, pid, &key, conn_guid);
} else if (strcmp(cmd, "CONNECT-DUMP") == 0) {
connect_limit_dump(connect_limit, conn->output);
} else if (strcmp(cmd, "KILL") == 0) {
/* points to userip_hash keys */
struct userip *userip;
pid_t pid;
+ guid_128_t conn_guid;
unsigned int refcount;
};
static unsigned int session_hash(const struct session *session)
{
- return userip_hash(session->userip) ^ session->pid;
+ return userip_hash(session->userip) ^
+ guid_128_hash(session->conn_guid) ^ session->pid;
}
static int session_cmp(const struct session *session1,
const struct session *session2)
{
+ /* conn-guids should be unique, but only if they're not empty */
+ int ret = guid_128_cmp(session1->conn_guid, session2->conn_guid);
+ if (ret != 0)
+ return ret;
+
if (session1->pid < session2->pid)
return -1;
else if (session1->pid > session2->pid)
}
void connect_limit_connect(struct connect_limit *limit, pid_t pid,
- const struct connect_limit_key *key)
+ const struct connect_limit_key *key,
+ const guid_128_t conn_guid)
{
struct session *session;
struct userip *userip;
.userip = userip,
.pid = pid,
};
+ guid_128_copy(session_lookup.conn_guid, conn_guid);
session = hash_table_lookup(limit->session_hash, &session_lookup);
if (session == NULL) {
session = i_new(struct session, 1);
session->userip = userip;
session->pid = pid;
+ guid_128_copy(session->conn_guid, conn_guid);
session->refcount = 1;
hash_table_insert(limit->session_hash, session, session);
} else {
}
}
+static void session_free(struct session *session)
+{
+ i_free(session);
+}
+
static void
userip_hash_unref(struct connect_limit *limit,
const struct userip *userip_lookup)
}
void connect_limit_disconnect(struct connect_limit *limit, pid_t pid,
- const struct connect_limit_key *key)
+ const struct connect_limit_key *key,
+ const guid_128_t conn_guid)
{
struct session *session;
struct userip userip_lookup = {
.userip = &userip_lookup,
.pid = pid,
};
+ guid_128_copy(session_lookup.conn_guid, conn_guid);
session = hash_table_lookup(limit->session_hash, &session_lookup);
if (session == NULL) {
i_error("connect limit: disconnection for unknown "
- "(pid=%s, user=%s, service=%s, ip=%s)",
+ "(pid=%s, user=%s, service=%s, ip=%s, conn_guid=%s)",
dec2str(pid), key->username, key->service,
- net_ip2addr(&key->ip));
+ net_ip2addr(&key->ip), guid_128_to_string(conn_guid));
return;
}
if (--session->refcount == 0) {
hash_table_remove(limit->session_hash, session);
- i_free(session);
+ session_free(session);
}
userip_hash_unref(limit, &userip_lookup);
hash_table_remove(limit->session_hash, session);
for (; session->refcount > 0; session->refcount--)
userip_hash_unref(limit, session->userip);
- i_free(session);
+ session_free(session);
}
}
hash_table_iterate_deinit(&iter);
str_append_c(str, '\t');
if (session->userip->ip.family != 0)
str_append(str, net_ip2addr(&session->userip->ip));
+ str_append_c(str, '\t');
+ str_append_tabescaped(str, guid_128_to_string(session->conn_guid));
str_append_c(str, '\n');
ret = o_stream_send(output, str_data(str), str_len(str));
} T_END;
#define CONNECT_LIMIT_H
#include "net.h"
+#include "guid.h"
struct connect_limit_key {
/* User's primary username */
connect_limit_lookup(struct connect_limit *limit,
const struct connect_limit_key *key);
void connect_limit_connect(struct connect_limit *limit, pid_t pid,
- const struct connect_limit_key *key);
+ const struct connect_limit_key *key,
+ const guid_128_t conn_guid);
void connect_limit_disconnect(struct connect_limit *limit, pid_t pid,
- const struct connect_limit_key *key);
+ const struct connect_limit_key *key,
+ const guid_128_t conn_guid);
void connect_limit_disconnect_pid(struct connect_limit *limit, pid_t pid);
void connect_limit_dump(struct connect_limit *limit, struct ostream *output);