main.c revision 958e5ae51a755558b6d022a39b194614726b4225
a8c5a86d183db25a57bf193c06b41e092ec2e151Timo Sirainen/* Copyright (c) 2010-2016 Dovecot authors, see the included COPYING file */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "lib.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "ioloop.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "array.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "str.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "restrict-access.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "process-title.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "master-interface.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "master-service.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "master-service-settings.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "auth-connection.h"
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen#include "doveadm-connection.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "login-connection.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "notify-connection.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "user-directory.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "director.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "director-host.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "director-connection.h"
ae46f6ba5bb9eee8900254d3042e89d490023be0Timo Sirainen#include "director-request.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "mail-host.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
3f3ad16ff74d694796d22501250a9a29997c0729Timo Sirainen#include <stdio.h>
b4ddb5b3c3722620a8fef387dd8c47bb411a5643Timo Sirainen#include <unistd.h>
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#define AUTH_SOCKET_PATH "auth-login"
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen#define AUTH_USERDB_SOCKET_PATH "auth-userdb"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenenum director_socket_type {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen DIRECTOR_SOCKET_TYPE_UNKNOWN = 0,
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen DIRECTOR_SOCKET_TYPE_AUTH,
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen DIRECTOR_SOCKET_TYPE_USERDB,
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen DIRECTOR_SOCKET_TYPE_AUTHREPLY,
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen DIRECTOR_SOCKET_TYPE_RING,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen DIRECTOR_SOCKET_TYPE_DOVEADM
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen};
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic struct director *director;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic struct notify_connection *notify_conn;
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainenstatic struct timeout *to_proctitle_refresh;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic ARRAY(enum director_socket_type) listener_socket_types;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic void director_refresh_proctitle_timeout(void *context ATTR_UNUSED)
db693bf6fcae96d834567f1782257517b7207655Timo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen static uint64_t prev_requests = 0, prev_input = 0, prev_output;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen string_t *str;
faec0abfd648c647030027e86de2ce8911df683bTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen str = t_str_new(64);
5801ce4da7d807ab85d02051ece5969e7175eebaTimo Sirainen str_printfa(str, "[%u users", user_directory_count(director->users));
b4ddb5b3c3722620a8fef387dd8c47bb411a5643Timo Sirainen str_printfa(str, ", %lu req/s",
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen (unsigned long)(director->num_requests - prev_requests));
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen str_printfa(str, ", %llu+%llu kB/s",
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen (unsigned long long)(director->ring_traffic_input - prev_input)/1024,
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen (unsigned long long)(director->ring_traffic_output - prev_output)/1024);
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen str_append_c(str, ']');
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen
db693bf6fcae96d834567f1782257517b7207655Timo Sirainen prev_requests = director->num_requests;
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen prev_input = director->ring_traffic_input;
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen prev_output = director->ring_traffic_output;
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen process_title_set(str_c(str));
5801ce4da7d807ab85d02051ece5969e7175eebaTimo Sirainen}
5801ce4da7d807ab85d02051ece5969e7175eebaTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic enum director_socket_type
861f53be0cc2fa5665f3c107a7576e2a53bb2eb0Timo Sirainendirector_socket_type_get_from_name(const char *path)
5801ce4da7d807ab85d02051ece5969e7175eebaTimo Sirainen{
db693bf6fcae96d834567f1782257517b7207655Timo Sirainen const char *name, *suffix;
861f53be0cc2fa5665f3c107a7576e2a53bb2eb0Timo Sirainen
861f53be0cc2fa5665f3c107a7576e2a53bb2eb0Timo Sirainen name = strrchr(path, '/');
861f53be0cc2fa5665f3c107a7576e2a53bb2eb0Timo Sirainen if (name == NULL)
861f53be0cc2fa5665f3c107a7576e2a53bb2eb0Timo Sirainen name = path;
861f53be0cc2fa5665f3c107a7576e2a53bb2eb0Timo Sirainen else
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen name++;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen suffix = strrchr(name, '-');
faec0abfd648c647030027e86de2ce8911df683bTimo Sirainen if (suffix == NULL)
faec0abfd648c647030027e86de2ce8911df683bTimo Sirainen suffix = name;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen else
db693bf6fcae96d834567f1782257517b7207655Timo Sirainen suffix++;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
b4ddb5b3c3722620a8fef387dd8c47bb411a5643Timo Sirainen if (strcmp(suffix, "auth") == 0)
b4ddb5b3c3722620a8fef387dd8c47bb411a5643Timo Sirainen return DIRECTOR_SOCKET_TYPE_AUTH;
b4ddb5b3c3722620a8fef387dd8c47bb411a5643Timo Sirainen else if (strcmp(suffix, "userdb") == 0)
b4ddb5b3c3722620a8fef387dd8c47bb411a5643Timo Sirainen return DIRECTOR_SOCKET_TYPE_USERDB;
b4ddb5b3c3722620a8fef387dd8c47bb411a5643Timo Sirainen else if (strcmp(suffix, "authreply") == 0)
b4ddb5b3c3722620a8fef387dd8c47bb411a5643Timo Sirainen return DIRECTOR_SOCKET_TYPE_AUTHREPLY;
b4ddb5b3c3722620a8fef387dd8c47bb411a5643Timo Sirainen else if (strcmp(suffix, "ring") == 0)
faec0abfd648c647030027e86de2ce8911df683bTimo Sirainen return DIRECTOR_SOCKET_TYPE_RING;
fb35b9f2c80954da842c20d5128b5e506835d93eTimo Sirainen else if (strcmp(suffix, "admin") == 0 ||
b4ddb5b3c3722620a8fef387dd8c47bb411a5643Timo Sirainen strcmp(suffix, "doveadm") == 0)
b4ddb5b3c3722620a8fef387dd8c47bb411a5643Timo Sirainen return DIRECTOR_SOCKET_TYPE_DOVEADM;
b4ddb5b3c3722620a8fef387dd8c47bb411a5643Timo Sirainen else
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen return DIRECTOR_SOCKET_TYPE_UNKNOWN;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
b4ddb5b3c3722620a8fef387dd8c47bb411a5643Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic enum director_socket_type
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenlistener_get_socket_type_fallback(int listen_fd)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
fa87f0ef3636fa52ce42513533ee500c0bf29910Timo Sirainen in_port_t local_port;
fa87f0ef3636fa52ce42513533ee500c0bf29910Timo Sirainen
fa87f0ef3636fa52ce42513533ee500c0bf29910Timo Sirainen if (net_getsockname(listen_fd, NULL, &local_port) == 0 &&
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen local_port != 0) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* TCP/IP connection */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return DIRECTOR_SOCKET_TYPE_RING;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return DIRECTOR_SOCKET_TYPE_AUTH;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
fa87f0ef3636fa52ce42513533ee500c0bf29910Timo Sirainenstatic void listener_sockets_init(struct ip_addr *listen_ip_r,
fa87f0ef3636fa52ce42513533ee500c0bf29910Timo Sirainen in_port_t *listen_port_r)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen const char *name;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen unsigned int i, socket_count;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct ip_addr ip;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen in_port_t port;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen enum director_socket_type type;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen *listen_port_r = 0;
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_array_init(&listener_socket_types, 8);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen socket_count = master_service_get_socket_count(master_service);
242abe3ad2423776e9cf05e1304eb8fda4831b23Timo Sirainen for (i = 0; i < socket_count; i++) {
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen int listen_fd = MASTER_LISTEN_FD_FIRST + i;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen name = master_service_get_socket_name(master_service, listen_fd);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen type = director_socket_type_get_from_name(name);
2efe19d9045768d985a3bd549cff12f65ba40cc8Timo Sirainen if (type == DIRECTOR_SOCKET_TYPE_UNKNOWN) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* mainly for backwards compatibility */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen type = listener_get_socket_type_fallback(listen_fd);
2efe19d9045768d985a3bd549cff12f65ba40cc8Timo Sirainen }
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen if (type == DIRECTOR_SOCKET_TYPE_RING && *listen_port_r == 0 &&
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen net_getsockname(listen_fd, &ip, &port) == 0 && port > 0) {
2efe19d9045768d985a3bd549cff12f65ba40cc8Timo Sirainen *listen_ip_r = ip;
2efe19d9045768d985a3bd549cff12f65ba40cc8Timo Sirainen *listen_port_r = port;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen array_idx_set(&listener_socket_types, listen_fd, &type);
2efe19d9045768d985a3bd549cff12f65ba40cc8Timo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
5b4d189a01d248458496068f838128f1bafdcf2eTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic int director_client_connected(int fd, const struct ip_addr *ip)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct director_host *host;
7ee226c2a66aa4dce7f13e8b17687db285c981bdTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen host = director_host_lookup_ip(director, ip);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (host == NULL || host->removed) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_warning("Connection from %s: Server not listed in "
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen "director_servers, dropping", net_ip2addr(ip));
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return -1;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
fa87f0ef3636fa52ce42513533ee500c0bf29910Timo Sirainen (void)director_connection_init_in(director, fd, ip);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return 0;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic void client_connected(struct master_service_connection *conn)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct auth_connection *auth;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen const char *socket_path;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen const enum director_socket_type *typep;
c4900d31385344bfadaee53a897daeafdb3063d8Timo Sirainen bool userdb;
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen if (conn->fifo) {
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen if (notify_conn != NULL) {
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen i_error("Received another proxy-notify connection");
69b22a0c0c84087e5bdeec71faae7ea77295240fTimo Sirainen return;
69b22a0c0c84087e5bdeec71faae7ea77295240fTimo Sirainen }
69b22a0c0c84087e5bdeec71faae7ea77295240fTimo Sirainen master_service_client_connection_accept(conn);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen notify_conn = notify_connection_init(director, conn->fd);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
8dd76854cc680053986142d5f5e823f637447929Timo Sirainen typep = array_idx(&listener_socket_types, conn->listen_fd);
8dd76854cc680053986142d5f5e823f637447929Timo Sirainen switch (*typep) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen case DIRECTOR_SOCKET_TYPE_UNKNOWN:
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_unreached();
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen case DIRECTOR_SOCKET_TYPE_AUTH:
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen case DIRECTOR_SOCKET_TYPE_USERDB:
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* a) userdb connection, probably for lmtp proxy
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen b) login connection
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen Both of them are handled exactly the same, except for which
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen auth socket they connect to. */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen userdb = *typep == DIRECTOR_SOCKET_TYPE_USERDB;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen socket_path = userdb ? AUTH_USERDB_SOCKET_PATH :
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen AUTH_SOCKET_PATH;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen auth = auth_connection_init(socket_path);
412b772c337428b72149605c1410524c2353e5d4Timo Sirainen if (auth_connection_connect(auth) < 0) {
412b772c337428b72149605c1410524c2353e5d4Timo Sirainen auth_connection_deinit(&auth);
412b772c337428b72149605c1410524c2353e5d4Timo Sirainen break;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen master_service_client_connection_accept(conn);
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen (void)login_connection_init(director, conn->fd, auth,
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen userdb ? LOGIN_CONNECTION_TYPE_USERDB :
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen LOGIN_CONNECTION_TYPE_AUTH);
412b772c337428b72149605c1410524c2353e5d4Timo Sirainen break;
f9f77e06a148fd0816004e0e1b0f585307148a7dTimo Sirainen case DIRECTOR_SOCKET_TYPE_AUTHREPLY:
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen master_service_client_connection_accept(conn);
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen (void)login_connection_init(director, conn->fd, NULL,
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen LOGIN_CONNECTION_TYPE_AUTHREPLY);
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen break;
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen case DIRECTOR_SOCKET_TYPE_RING:
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen if (director_client_connected(conn->fd, &conn->remote_ip) == 0)
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen master_service_client_connection_accept(conn);
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen break;
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen case DIRECTOR_SOCKET_TYPE_DOVEADM:
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen master_service_client_connection_accept(conn);
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen (void)doveadm_connection_init(director, conn->fd);
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen break;
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic void director_state_changed(struct director *dir)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct director_request *const *requestp;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen ARRAY(struct director_request *) new_requests;
7ee226c2a66aa4dce7f13e8b17687db285c981bdTimo Sirainen bool ret;
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen
1df39b899804fd1dbc560f75382364822935c857Timo Sirainen if (!dir->ring_synced || !mail_hosts_have_usable(dir->mail_hosts))
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen return;
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen /* if there are any pending client requests, finish them now */
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen t_array_init(&new_requests, 8);
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen array_foreach(&dir->pending_requests, requestp) {
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen ret = director_request_continue(*requestp);
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen if (!ret) {
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen /* a) request for a user being killed
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen b) user is weak */
d6b3cfd855c0eebed68be50d3111de1b5a6afeb0Timo Sirainen array_append(&new_requests, requestp, 1);
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen array_clear(&dir->pending_requests);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen array_append_array(&dir->pending_requests, &new_requests);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (dir->to_request != NULL && array_count(&new_requests) == 0)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen timeout_remove(&dir->to_request);
}
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)
{
if (to_proctitle_refresh != NULL)
timeout_remove(&to_proctitle_refresh);
if (notify_conn != NULL)
notify_connection_deinit(&notify_conn);
director_deinit(&director);
directors_deinit();
doveadm_connections_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);
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;
}