changeset 21924:2f1a7c1007d7

doveadm who: Don't aggregate empty usernames with different IPs We'll assume that in that case anvil is used to track IP addresses rather than usernames. (Dovecot core doesn't currently use this.)
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Wed, 05 Apr 2017 12:52:14 +0300
parents a4eaf4ba3f90
children eb3ae53f8ac0
files src/doveadm/doveadm-who.c
diffstat 1 files changed, 29 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/doveadm/doveadm-who.c	Fri Apr 07 09:28:55 2017 +0300
+++ b/src/doveadm/doveadm-who.c	Wed Apr 05 12:52:14 2017 +0300
@@ -22,9 +22,28 @@
 	unsigned int connection_count;
 };
 
+static void who_user_ip(const struct who_user *user, struct ip_addr *ip_r)
+{
+	if (array_count(&user->ips) == 0)
+		i_zero(ip_r);
+	else {
+		const struct ip_addr *ip = array_idx(&user->ips, 0);
+		*ip_r = *ip;
+	}
+}
+
 static unsigned int who_user_hash(const struct who_user *user)
 {
-	return str_hash(user->username) + str_hash(user->service);
+	struct ip_addr ip;
+	unsigned int hash = str_hash(user->service);
+
+	if (user->username[0] != '\0')
+		hash += str_hash(user->username);
+	else {
+		who_user_ip(user, &ip);
+		hash += net_ip_hash(&ip);
+	}
+	return hash;
 }
 
 static int who_user_cmp(const struct who_user *user1,
@@ -34,6 +53,15 @@
 		return 1;
 	if (strcmp(user1->service, user2->service) != 0)
 		return 1;
+
+	if (user1->username[0] == '\0') {
+		/* tracking only IP addresses, not usernames */
+		struct ip_addr ip1, ip2;
+
+		who_user_ip(user1, &ip1);
+		who_user_ip(user2, &ip2);
+		return net_ip_cmp(&ip1, &ip2);
+	}
 	return 0;
 }