main.c revision 47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4a
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2010-2017 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "ioloop.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "array.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "restrict-access.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "process-title.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "master-interface.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "master-service.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "master-service-settings.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "auth-connection.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "doveadm-connection.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "login-connection.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "notify-connection.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "user-directory.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "director.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "director-host.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "director-connection.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "director-request.h"
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen#include "mail-host.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen#include <stdio.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <unistd.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen#define AUTH_SOCKET_PATH "auth-login"
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen#define AUTH_USERDB_SOCKET_PATH "auth-userdb"
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainenenum director_socket_type {
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen DIRECTOR_SOCKET_TYPE_UNKNOWN = 0,
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen DIRECTOR_SOCKET_TYPE_AUTH,
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen DIRECTOR_SOCKET_TYPE_USERDB,
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen DIRECTOR_SOCKET_TYPE_AUTHREPLY,
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen DIRECTOR_SOCKET_TYPE_RING,
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen DIRECTOR_SOCKET_TYPE_DOVEADM
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen};
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainenstatic struct director *director;
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainenstatic struct notify_connection *notify_conn;
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainenstatic struct timeout *to_proctitle_refresh;
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainenstatic ARRAY(enum director_socket_type) listener_socket_types;
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainenstatic unsigned int director_total_users_count(void)
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen{
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen struct mail_tag *const *tagp;
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen unsigned int count = 0;
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen array_foreach(mail_hosts_get_tags(director->mail_hosts), tagp)
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen count += user_directory_count((*tagp)->users);
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen return count;
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen}
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainenstatic void director_refresh_proctitle_timeout(void *context ATTR_UNUSED)
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen{
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen static uint64_t prev_requests = 0, prev_input = 0, prev_output;
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen string_t *str;
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen str = t_str_new(64);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_printfa(str, "[%u users", director_total_users_count());
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (director->users_moving_count > 0)
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen str_printfa(str, ", %u moving", director->users_moving_count);
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen str_printfa(str, ", %"PRIu64" req/s",
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen director->num_requests - prev_requests);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_printfa(str, ", %"PRIu64"+%"PRIu64" kB/s",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (director->ring_traffic_input - prev_input)/1024,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (director->ring_traffic_output - prev_output)/1024);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append_c(str, ']');
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen prev_requests = director->num_requests;
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainen prev_input = director->ring_traffic_input;
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainen prev_output = director->ring_traffic_output;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen process_title_set(str_c(str));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainenstatic enum director_socket_type
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainendirector_socket_type_get_from_name(const char *path)
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen{
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen const char *name, *suffix;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen name = strrchr(path, '/');
e12648867876aaec17e06ee4caef0bb60363449dTimo Sirainen if (name == NULL)
e12648867876aaec17e06ee4caef0bb60363449dTimo Sirainen name = path;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen name++;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen suffix = strrchr(name, '-');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (suffix == NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen suffix = name;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen suffix++;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen if (strcmp(suffix, "auth") == 0)
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen return DIRECTOR_SOCKET_TYPE_AUTH;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else if (strcmp(suffix, "userdb") == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return DIRECTOR_SOCKET_TYPE_USERDB;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else if (strcmp(suffix, "authreply") == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return DIRECTOR_SOCKET_TYPE_AUTHREPLY;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else if (strcmp(suffix, "ring") == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return DIRECTOR_SOCKET_TYPE_RING;
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen else if (strcmp(suffix, "admin") == 0 ||
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen strcmp(suffix, "doveadm") == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return DIRECTOR_SOCKET_TYPE_DOVEADM;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return DIRECTOR_SOCKET_TYPE_UNKNOWN;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
2a909d051d11e67400b333904e24bf421e99cad7Timo Sirainenstatic enum director_socket_type
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenlistener_get_socket_type_fallback(int listen_fd)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen in_port_t local_port;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (net_getsockname(listen_fd, NULL, &local_port) == 0 &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen local_port != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* TCP/IP connection */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return DIRECTOR_SOCKET_TYPE_RING;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return DIRECTOR_SOCKET_TYPE_AUTH;
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void listener_sockets_init(struct ip_addr *listen_ip_r,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen in_port_t *listen_port_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *name;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int i, socket_count;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct ip_addr ip;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen in_port_t port;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum director_socket_type type;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *listen_port_r = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_array_init(&listener_socket_types, 8);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen socket_count = master_service_get_socket_count(master_service);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < socket_count; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int listen_fd = MASTER_LISTEN_FD_FIRST + i;
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen name = master_service_get_socket_name(master_service, listen_fd);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen type = director_socket_type_get_from_name(name);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (type == DIRECTOR_SOCKET_TYPE_UNKNOWN) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* mainly for backwards compatibility */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen type = listener_get_socket_type_fallback(listen_fd);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (type == DIRECTOR_SOCKET_TYPE_RING && *listen_port_r == 0 &&
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen net_getsockname(listen_fd, &ip, &port) == 0 && port > 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *listen_ip_r = ip;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *listen_port_r = port;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen array_idx_set(&listener_socket_types, listen_fd, &type);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int director_client_connected(int fd, const struct ip_addr *ip)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen struct director_host *host;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen host = director_host_lookup_ip(director, ip);
b9ce555e8624a5593b3bfd81b572b7d2e1e1fca5Timo Sirainen if (host == NULL || host->removed) {
b9ce555e8624a5593b3bfd81b572b7d2e1e1fca5Timo Sirainen i_warning("Connection from %s: Server not listed in "
b9ce555e8624a5593b3bfd81b572b7d2e1e1fca5Timo Sirainen "director_servers, dropping", net_ip2addr(ip));
b9ce555e8624a5593b3bfd81b572b7d2e1e1fca5Timo Sirainen return -1;
b9ce555e8624a5593b3bfd81b572b7d2e1e1fca5Timo Sirainen }
1b62b06d6fa688368f661b72d14de6518b5d1789Timo Sirainen
1b62b06d6fa688368f661b72d14de6518b5d1789Timo Sirainen (void)director_connection_init_in(director, fd, ip);
1b62b06d6fa688368f661b72d14de6518b5d1789Timo Sirainen return 0;
1b62b06d6fa688368f661b72d14de6518b5d1789Timo Sirainen}
1b62b06d6fa688368f661b72d14de6518b5d1789Timo Sirainen
1b62b06d6fa688368f661b72d14de6518b5d1789Timo Sirainenstatic void client_connected(struct master_service_connection *conn)
5c1a8aee989af87bddefd71e2aa83aa2bd695155Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct auth_connection *auth;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *socket_path;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const enum director_socket_type *typep;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen bool userdb;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6a1cb8bcac9b4dc7846ef19f2e7c53ecf37f1d55Timo Sirainen if (conn->fifo) {
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen if (notify_conn != NULL) {
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen i_error("Received another proxy-notify connection");
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen return;
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen }
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen master_service_client_connection_accept(conn);
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen notify_conn = notify_connection_init(director, conn->fd);
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen return;
633e6afa5de9ad8108ff8dbdee889ecf6170026eTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen typep = array_idx(&listener_socket_types, conn->listen_fd);
1b62b06d6fa688368f661b72d14de6518b5d1789Timo Sirainen switch (*typep) {
1b62b06d6fa688368f661b72d14de6518b5d1789Timo Sirainen case DIRECTOR_SOCKET_TYPE_UNKNOWN:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_unreached();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case DIRECTOR_SOCKET_TYPE_AUTH:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case DIRECTOR_SOCKET_TYPE_USERDB:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* a) userdb connection, probably for lmtp proxy
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen b) login connection
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen Both of them are handled exactly the same, except for which
5ec0ca7ff13595daf0d096c17100afb352e6294aTimo Sirainen auth socket they connect to. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen userdb = *typep == DIRECTOR_SOCKET_TYPE_USERDB;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen 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 ? LOGIN_CONNECTION_TYPE_USERDB :
LOGIN_CONNECTION_TYPE_AUTH);
break;
case DIRECTOR_SOCKET_TYPE_AUTHREPLY:
master_service_client_connection_accept(conn);
(void)login_connection_init(director, conn->fd, NULL,
LOGIN_CONNECTION_TYPE_AUTHREPLY);
break;
case DIRECTOR_SOCKET_TYPE_RING:
if (director_client_connected(conn->fd, &conn->remote_ip) == 0)
master_service_client_connection_accept(conn);
break;
case DIRECTOR_SOCKET_TYPE_DOVEADM:
master_service_client_connection_accept(conn);
(void)doveadm_connection_init(director, conn->fd);
break;
}
}
static void director_state_changed(struct director *dir)
{
struct director_request *const *requestp;
ARRAY(struct director_request *) new_requests;
bool ret;
if (!dir->ring_synced)
return;
/* if there are any pending client requests, finish them now */
t_array_init(&new_requests, 8);
array_foreach(&dir->pending_requests, requestp) {
ret = director_request_continue(*requestp);
if (!ret) {
/* a) request for a user being killed
b) user is weak */
array_append(&new_requests, requestp, 1);
}
}
array_clear(&dir->pending_requests);
array_append_array(&dir->pending_requests, &new_requests);
if (dir->to_request != NULL && array_count(&new_requests) == 0)
timeout_remove(&dir->to_request);
doveadm_connections_ring_synced();
}
static void main_preinit(void)
{
const struct director_settings *set;
struct ip_addr listen_ip;
in_port_t listen_port;
/* make sure we die with master even with shutdown_clients=no.
otherwise there will be two director processes and everything is
broken. it's only the login processes that need to stay alive. */
master_service_set_die_with_master(master_service, TRUE);
if (master_service_settings_get(master_service)->verbose_proctitle) {
to_proctitle_refresh =
timeout_add(1000, director_refresh_proctitle_timeout,
(void *)NULL);
}
set = master_service_settings_get_others(master_service)[0];
listener_sockets_init(&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)");
}
directors_init();
director = director_init(set, &listen_ip, listen_port,
director_state_changed);
director_host_add_from_string(director, set->director_servers);
director_find_self(director);
if (mail_hosts_parse_and_add(director->mail_hosts,
set->director_mail_servers) < 0)
i_fatal("Invalid value for director_mail_servers setting");
director->orig_config_hosts = mail_hosts_dup(director->mail_hosts);
restrict_access_by_env(NULL, FALSE);
restrict_access_allow_coredumps(TRUE);
}
static void main_deinit(void)
{
timeout_remove(&to_proctitle_refresh);
if (notify_conn != NULL)
notify_connection_deinit(&notify_conn);
/* deinit doveadm connections before director, so it can clean up
its pending work, such as abort user moves. */
doveadm_connections_deinit();
director_deinit(&director);
directors_deinit();
login_connections_deinit();
auth_connections_deinit();
array_free(&listener_socket_types);
}
int main(int argc, char *argv[])
{
const struct setting_parser_info *set_roots[] = {
&director_setting_parser_info,
NULL
};
const enum master_service_flags service_flags =
MASTER_SERVICE_FLAG_NO_IDLE_DIE;
in_port_t test_port = 0;
const char *error;
bool debug = FALSE;
int c;
master_service = master_service_init("director", service_flags,
&argc, &argv, "Dt:");
while ((c = master_getopt(master_service)) > 0) {
switch (c) {
case 'D':
debug = TRUE;
break;
case 't':
if (net_str2port(optarg, &test_port) < 0)
i_fatal("-t: Not a port number: %s", optarg);
break;
default:
return FATAL_DEFAULT;
}
}
if (master_service_settings_read_simple(master_service, set_roots,
&error) < 0)
i_fatal("Error reading configuration: %s", error);
master_service_init_log(master_service, "director: ");
main_preinit();
director->test_port = test_port;
director_debug = debug;
director_connect(director, "Initial connection");
if (director->test_port != 0) {
/* we're testing, possibly writing to same log file.
make it clear which director we are. */
master_service_init_log(master_service,
t_strdup_printf("director(%s): ",
net_ip2addr(&director->self_ip)));
}
master_service_init_finish(master_service);
master_service_run(master_service, client_connected);
main_deinit();
master_service_deinit(&master_service);
return 0;
}