Mercurial > dovecot > core-2.2
changeset 18672:fea09ab164dc
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.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 13 May 2015 15:33:27 +0300 |
parents | 5614bc437643 |
children | f8f0a782213b |
files | src/director/main.c |
diffstat | 1 files changed, 116 insertions(+), 51 deletions(-) [+] |
line wrap: on
line diff
--- 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,60 +170,38 @@ 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; - } - - /* 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); + break; } } -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) { struct director_request *const *requestp; @@ -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[])