# List of IPs or hostnames to all director servers, including ourself.
# Ports can be specified as ip:port. The default port is the same as
# what director service's inet_listener is using.
-director_servers =
+#director_servers =
# List of IPs or hostnames to all backend mail servers. Ranges are allowed
# too, like 10.0.0.10-10.0.0.30.
-director_mail_servers =
+#director_mail_servers =
# How long to redirect users to a specific server after it no longer has
# any connections.
-director_user_expire = 15 min
+#director_user_expire = 15 min
-# To enable director service, uncomment the mode and assign a port.
+# To enable director service, uncomment the modes and assign a port.
service director {
unix_listener login/director {
#mode = 0666
}
+ fifo_listener login/proxy-notify {
+ #mode = 0666
+ }
inet_listener {
#port =
}
doveadm-connection.c \
login-connection.c \
mail-host.c \
+ notify-connection.c \
user-directory.c
noinst_HEADERS = \
doveadm-connection.h \
login-connection.h \
mail-host.h \
+ notify-connection.h \
user-directory.h
director_unix_listeners,
sizeof(director_unix_listeners), { 0, }
};
+static struct file_listener_settings director_fifo_listeners_array[] = {
+ { "login/proxy-notify", 0, "", "" }
+};
+static struct file_listener_settings *director_fifo_listeners[] = {
+ &director_fifo_listeners_array[0]
+};
+static buffer_t director_fifo_listeners_buf = {
+ director_fifo_listeners,
+ sizeof(director_fifo_listeners), { 0, }
+};
/* </settings checks> */
struct service_settings director_service_settings = {
.unix_listeners = { { &director_unix_listeners_buf,
sizeof(director_unix_listeners[0]) } },
- .fifo_listeners = ARRAY_INIT,
+ .fifo_listeners = { { &director_fifo_listeners_buf,
+ sizeof(director_fifo_listeners[0]) } },
.inet_listeners = ARRAY_INIT
};
#undef DEF
static void login_host_callback(const struct ip_addr *ip, void *context)
{
struct login_host_request *request = context;
+ struct director *dir = request->conn->dir;
const char *line;
+ unsigned int secs;
T_BEGIN {
if (ip != NULL) {
- line = t_strconcat(request->line, "\thost=",
- net_ip2addr(ip), NULL);
+ secs = dir->set->director_user_expire / 2;
+ line = t_strdup_printf("%s\thost=%s\tproxy_refresh=%u",
+ request->line, net_ip2addr(ip),
+ secs);
} else {
i_assert(strncmp(request->line, "OK\t", 3) == 0);
line = t_strconcat("FAIL\t",
#include "auth-connection.h"
#include "doveadm-connection.h"
#include "login-connection.h"
+#include "notify-connection.h"
#include "director.h"
#include "director-host.h"
#include "director-connection.h"
#define AUTH_SOCKET_PATH "login/login"
static struct director *director;
+static struct notify_connection *notify_conn;
static char *auth_socket_path;
static int director_client_connected(int fd, const struct ip_addr *ip)
struct ip_addr ip;
unsigned int port, len;
+ if (conn->fifo) {
+ if (notify_conn != NULL) {
+ i_error("Received another proxy-notify connection");
+ (void)close(conn->fd);
+ return;
+ }
+ notify_conn = notify_connection_init(director, conn->fd);
+ return;
+ }
+
if (net_getpeername(conn->fd, &ip, &port) == 0 &&
(IPADDR_IS_V4(&ip) || IPADDR_IS_V6(&ip))) {
/* TCP/IP connection - this is another director */
static void main_deinit(void)
{
+ notify_connection_deinit(¬ify_conn);
director_deinit(&director);
doveadm_connections_deinit();
login_connections_deinit();
--- /dev/null
+/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "ioloop.h"
+#include "istream.h"
+#include "director.h"
+#include "user-directory.h"
+#include "notify-connection.h"
+
+#include <unistd.h>
+
+struct notify_connection {
+ int fd;
+ struct io *io;
+ struct istream *input;
+ struct director *dir;
+};
+
+static void notify_connection_input(struct notify_connection *conn)
+{
+ struct user *user;
+ const char *line;
+ unsigned int hash;
+
+ while ((line = i_stream_read_next_line(conn->input)) != NULL) {
+ hash = user_directory_get_username_hash(line);
+ user = user_directory_lookup(conn->dir->users, hash);
+ if (user != NULL) {
+ user_directory_refresh(conn->dir->users, user);
+ director_update_user(conn->dir, conn->dir->self_host,
+ user);
+ }
+ }
+ if (conn->input->eof || conn->input->stream_errno != 0)
+ notify_connection_deinit(&conn);
+}
+
+struct notify_connection *
+notify_connection_init(struct director *dir, int fd)
+{
+ struct notify_connection *conn;
+
+ conn = i_new(struct notify_connection, 1);
+ conn->fd = fd;
+ conn->dir = dir;
+ conn->input = i_stream_create_fd(conn->fd, 1024, FALSE);
+ conn->io = io_add(conn->fd, IO_READ, notify_connection_input, conn);
+ return conn;
+}
+
+void notify_connection_deinit(struct notify_connection **_conn)
+{
+ struct notify_connection *conn = *_conn;
+
+ *_conn = NULL;
+
+ io_remove(&conn->io);
+ i_stream_unref(&conn->input);
+ if (close(conn->fd) < 0)
+ i_error("close(notify connection) failed: %m");
+ i_free(conn);
+}
--- /dev/null
+#ifndef NOTIFY_CONNECTION_H
+#define NOTIFY_CONNECTION_H
+
+struct director;
+
+struct notify_connection *notify_connection_init(struct director *dir, int fd);
+void notify_connection_deinit(struct notify_connection **conn);
+
+#endif