]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
anvil, doveadm: Add support for connection GUIDs
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Sun, 12 Dec 2021 23:22:31 +0000 (01:22 +0200)
committerTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 8 Feb 2022 09:48:24 +0000 (10:48 +0100)
These are anvil-specific GUIDs that can be used to refer to a specific
connection.

src/anvil/anvil-connection.c
src/anvil/connect-limit.c
src/anvil/connect-limit.h
src/doveadm/doveadm-who.c
src/doveadm/doveadm-who.h

index f9a26732682c7be2c3c5dc48e061c4c48deea841..cc1c932f2062b9e903d854f7ea9f5f3bea9bb88e 100644 (file)
@@ -68,6 +68,7 @@ anvil_connection_request(struct anvil_connection *conn,
                         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;
@@ -88,7 +89,15 @@ anvil_connection_request(struct anvil_connection *conn,
                        *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";
@@ -103,7 +112,15 @@ anvil_connection_request(struct anvil_connection *conn,
                        *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) {
index 4927c60bd72740dd10fc295e242041b6c39f10cd..310b62a15179b7075aeb8f5b082773fa78f0bbb0 100644 (file)
@@ -18,6 +18,7 @@ struct session {
        /* points to userip_hash keys */
        struct userip *userip;
        pid_t pid;
+       guid_128_t conn_guid;
        unsigned int refcount;
 };
 
@@ -50,12 +51,18 @@ static int userip_cmp(const struct userip *userip1,
 
 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)
@@ -103,7 +110,8 @@ unsigned int connect_limit_lookup(struct connect_limit *limit,
 }
 
 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;
@@ -131,11 +139,13 @@ void connect_limit_connect(struct connect_limit *limit, pid_t pid,
                .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 {
@@ -143,6 +153,11 @@ void connect_limit_connect(struct connect_limit *limit, pid_t pid,
        }
 }
 
+static void session_free(struct session *session)
+{
+       i_free(session);
+}
+
 static void
 userip_hash_unref(struct connect_limit *limit,
                  const struct userip *userip_lookup)
@@ -168,7 +183,8 @@ userip_hash_unref(struct connect_limit *limit,
 }
 
 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 = {
@@ -181,19 +197,20 @@ void connect_limit_disconnect(struct connect_limit *limit, pid_t pid,
                .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);
@@ -212,7 +229,7 @@ void connect_limit_disconnect_pid(struct connect_limit *limit, pid_t pid)
                        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);
@@ -237,6 +254,8 @@ void connect_limit_dump(struct connect_limit *limit, struct ostream *output)
                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;
index 0d24782d0e13826fd6de257f1acc83d2ce4cea3f..eb5300d27e2e82498ff3ac5153c8f852b8c48e1c 100644 (file)
@@ -2,6 +2,7 @@
 #define CONNECT_LIMIT_H
 
 #include "net.h"
+#include "guid.h"
 
 struct connect_limit_key {
        /* User's primary username */
@@ -19,9 +20,11 @@ unsigned int
 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);
 
index a562998b7303c4d568d3884f8d62d67b4dc89462..d1d4cf9fb392ab24523b6273853b8e42e86fa69f 100644 (file)
@@ -83,8 +83,8 @@ static int who_parse_line(const char *line, struct who_line *line_r)
        const char *const *args = t_strsplit_tabescaped(line);
        i_zero(line_r);
 
-       /* <pid> <refcount> <username> <service> <ip> */
-       if (str_array_length(args) < 5)
+       /* <pid> <refcount> <username> <service> <ip> <conn-guid> */
+       if (str_array_length(args) < 6)
                return -1;
 
        if (str_to_pid(args[0], &line_r->pid) < 0)
@@ -97,6 +97,10 @@ static int who_parse_line(const char *line, struct who_line *line_r)
                if (net_addr2ip(args[4], &line_r->ip) < 0)
                        return -1;
        }
+       if (args[5][0] != '\0') {
+               if (guid_128_from_string(args[5], line_r->conn_guid) < 0)
+                       return -1;
+       }
        return 0;
 }
 
index 57c663a95da70c08b81ed7a9974425d1afaded6a..121637e3c5dcd016272ebd91ebd51d36a38b208d 100644 (file)
@@ -1,9 +1,12 @@
 #ifndef DOVEADM_WHO_H
 #define DOVEADM_WHO_H
 
+#include "guid.h"
+
 struct who_line {
        const char *username;
        const char *service;
+       guid_128_t conn_guid;
        struct ip_addr ip;
        pid_t pid;
        unsigned int refcount;