dovecot-2.2: director: Cleanup for director socket type configur...

dovecot at dovecot.org dovecot at dovecot.org
Wed May 13 12:35:39 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/fea09ab164dc
changeset: 18672:fea09ab164dc
user:      Timo Sirainen <tss at iki.fi>
date:      Wed May 13 15:33:27 2015 +0300
description:
director: Cleanup for director socket type configuration.
It's now possible to use any type of a socket for inet listeners by
specifying the name for the listener. The available types are: auth
(default), userdb, ring (= director<->director connection), admin/doveadm.
This change should be backwards compatible with previous configuration.
This setting also deprecates director_doveadm_port setting.

diffstat:

 src/director/main.c |  167 ++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 116 insertions(+), 51 deletions(-)

diffs (219 lines):

diff -r 5614bc437643 -r fea09ab164dc src/director/main.c
--- a/src/director/main.c	Wed May 13 15:32:54 2015 +0300
+++ b/src/director/main.c	Wed May 13 15:33:27 2015 +0300
@@ -26,9 +26,18 @@
 #define AUTH_SOCKET_PATH "auth-login"
 #define AUTH_USERDB_SOCKET_PATH "auth-userdb"
 
+enum director_socket_type {
+	DIRECTOR_SOCKET_TYPE_UNKNOWN = 0,
+	DIRECTOR_SOCKET_TYPE_AUTH,
+	DIRECTOR_SOCKET_TYPE_USERDB,
+	DIRECTOR_SOCKET_TYPE_RING,
+	DIRECTOR_SOCKET_TYPE_DOVEADM
+};
+
 static struct director *director;
 static struct notify_connection *notify_conn;
 static struct timeout *to_proctitle_refresh;
+static ARRAY(enum director_socket_type) listener_socket_types;
 
 static void director_refresh_proctitle_timeout(void *context ATTR_UNUSED)
 {
@@ -51,6 +60,84 @@
 	process_title_set(str_c(str));
 }
 
+static enum director_socket_type
+director_socket_type_get_from_name(const char *path)
+{
+	const char *name, *suffix;
+
+	name = strrchr(path, '/');
+	if (name == NULL)
+		name = path;
+	else
+		name++;
+
+	suffix = strrchr(name, '-');
+	if (suffix == NULL)
+		suffix = name;
+	else
+		suffix++;
+
+	if (strcmp(suffix, "auth") == 0)
+		return DIRECTOR_SOCKET_TYPE_AUTH;
+	else if (strcmp(suffix, "userdb") == 0)
+		return DIRECTOR_SOCKET_TYPE_USERDB;
+	else if (strcmp(suffix, "ring") == 0)
+		return DIRECTOR_SOCKET_TYPE_RING;
+	else if (strcmp(suffix, "admin") == 0 ||
+		 strcmp(suffix, "doveadm") == 0)
+		return DIRECTOR_SOCKET_TYPE_DOVEADM;
+	else
+		return DIRECTOR_SOCKET_TYPE_UNKNOWN;
+}
+
+static enum director_socket_type
+listener_get_socket_type_fallback(const struct director_settings *set,
+				  int listen_fd)
+{
+	unsigned int local_port;
+
+	if (net_getsockname(listen_fd, NULL, &local_port) == 0) {
+		/* TCP/IP connection */
+		if (local_port == set->director_doveadm_port)
+			return DIRECTOR_SOCKET_TYPE_DOVEADM;
+		else
+			return DIRECTOR_SOCKET_TYPE_RING;
+	}
+	return DIRECTOR_SOCKET_TYPE_AUTH;
+}
+
+static void listener_sockets_init(const struct director_settings *set,
+				  struct ip_addr *listen_ip_r,
+				  unsigned int *listen_port_r)
+{
+	const char *name;
+	unsigned int i, socket_count, port;
+	struct ip_addr ip;
+	enum director_socket_type type;
+
+	*listen_port_r = 0;
+
+	i_array_init(&listener_socket_types, 8);
+	socket_count = master_service_get_socket_count(master_service);
+	for (i = 0; i < socket_count; i++) {
+		int listen_fd = MASTER_LISTEN_FD_FIRST + i;
+
+		name = master_service_get_socket_name(master_service, listen_fd);
+		type = director_socket_type_get_from_name(name);
+		if (type == DIRECTOR_SOCKET_TYPE_UNKNOWN) {
+			/* mainly for backwards compatibility */
+			type = listener_get_socket_type_fallback(set, listen_fd);
+		}
+		if (type == DIRECTOR_SOCKET_TYPE_RING && *listen_port_r == 0 &&
+		    net_getsockname(listen_fd, &ip, &port) == 0 && port > 0) {
+			i_warning("listen port = %d", port);
+			*listen_ip_r = ip;
+			*listen_port_r = port;
+		}
+		array_idx_set(&listener_socket_types, listen_fd, &type);
+	}
+}
+
 static int director_client_connected(int fd, const struct ip_addr *ip)
 {
 	struct director_host *host;
@@ -70,8 +157,7 @@
 {
 	struct auth_connection *auth;
 	const char *socket_path;
-	struct ip_addr ip;
-	unsigned int local_port, len;
+	const enum director_socket_type *typep;
 	bool userdb;
 
 	if (conn->fifo) {
@@ -84,58 +170,36 @@
 		return;
 	}
 
-	if (net_getpeername(conn->fd, &ip, NULL) == 0 &&
-	    net_getsockname(conn->fd, NULL, &local_port) == 0 &&
-	    (IPADDR_IS_V4(&ip) || IPADDR_IS_V6(&ip))) {
-		/* TCP/IP connection */
-		if (local_port == director->set->director_doveadm_port) {
+	typep = array_idx(&listener_socket_types, conn->listen_fd);
+	switch (*typep) {
+	case DIRECTOR_SOCKET_TYPE_UNKNOWN:
+		i_unreached();
+	case DIRECTOR_SOCKET_TYPE_AUTH:
+	case DIRECTOR_SOCKET_TYPE_USERDB:
+		/* a) userdb connection, probably for lmtp proxy
+		   b) login connection
+		   Both of them are handled exactly the same, except for which
+		   auth socket they connect to. */
+		userdb = *typep == DIRECTOR_SOCKET_TYPE_USERDB;
+		socket_path = userdb ? AUTH_USERDB_SOCKET_PATH :
+			AUTH_SOCKET_PATH;
+		auth = auth_connection_init(socket_path);
+		if (auth_connection_connect(auth) < 0) {
+			auth_connection_deinit(&auth);
+			break;
+		}
+		master_service_client_connection_accept(conn);
+		(void)login_connection_init(director, conn->fd, auth, userdb);
+		break;
+	case DIRECTOR_SOCKET_TYPE_RING:
+		if (director_client_connected(conn->fd, &conn->remote_ip) == 0)
 			master_service_client_connection_accept(conn);
-			(void)doveadm_connection_init(director, conn->fd);
-		} else {
-			if (director_client_connected(conn->fd, &ip) == 0)
-				master_service_client_connection_accept(conn);
-		}
-		return;
-	}
-
-	len = strlen(conn->name);
-	if (len > 6 && strcmp(conn->name + len - 6, "-admin") == 0) {
-		/* doveadm connection */
+		break;
+	case DIRECTOR_SOCKET_TYPE_DOVEADM:
 		master_service_client_connection_accept(conn);
 		(void)doveadm_connection_init(director, conn->fd);
-		return;
+		break;
 	}
-
-	/* a) userdb connection, probably for lmtp proxy
-	   b) login connection
-	   Both of them are handled exactly the same, except for which
-	   auth socket they connect to. */
-	userdb = len > 7 && strcmp(conn->name + len - 7, "-userdb") == 0;
-	socket_path = userdb ? AUTH_USERDB_SOCKET_PATH : AUTH_SOCKET_PATH;
-	auth = auth_connection_init(socket_path);
-	if (auth_connection_connect(auth) == 0) {
-		master_service_client_connection_accept(conn);
-		(void)login_connection_init(director, conn->fd, auth, userdb);
-	} else {
-		auth_connection_deinit(&auth);
-	}
-}
-
-static unsigned int
-find_inet_listener_port(struct ip_addr *ip_r,
-			const struct director_settings *set)
-{
-	unsigned int i, socket_count, port;
-
-	socket_count = master_service_get_socket_count(master_service);
-	for (i = 0; i < socket_count; i++) {
-		int fd = MASTER_LISTEN_FD_FIRST + i;
-
-		if (net_getsockname(fd, ip_r, &port) == 0 && port > 0 &&
-		    port != set->director_doveadm_port)
-			return port;
-	}
-	return 0;
 }
 
 static void director_state_changed(struct director *dir)
@@ -177,7 +241,7 @@
 	}
 	set = master_service_settings_get_others(master_service)[0];
 
-	listen_port = find_inet_listener_port(&listen_ip, set);
+	listener_sockets_init(set, &listen_ip, &listen_port);
 	if (listen_port == 0 && *set->director_servers != '\0') {
 		i_fatal("No inet_listeners defined for director service "
 			"(for standalone keep director_servers empty)");
@@ -206,6 +270,7 @@
 	doveadm_connections_deinit();
 	login_connections_deinit();
 	auth_connections_deinit();
+	array_free(&listener_socket_types);
 }
 
 int main(int argc, char *argv[])


More information about the dovecot-cvs mailing list