master.c revision 087939d3fa9c4056419386c9d6c81f147de534cd
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "common.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "hash.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "buffer.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "ioloop.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "network.h"
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen#include "fdpass.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "istream.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "env-util.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "write-full.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "master.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "client-common.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen#include <unistd.h>
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic int master_fd;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic struct io *io_master;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic struct hash_table *master_requests;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic unsigned int master_tag_counter;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic unsigned int master_pos;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic char master_buf[sizeof(struct master_login_reply)];
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic struct client destroyed_client;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void client_call_master_callback(struct client *client,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const struct master_login_reply *reply)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen master_callback_t *master_callback;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen master_callback = client->master_callback;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client->master_tag = 0;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client->master_callback = NULL;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen master_callback(client, reply);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void request_handle(struct master_login_reply *reply)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct client *client;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (reply->tag == 0 && !process_per_connection) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* this means we have to start listening again.
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen we've reached maximum number of login processes. */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen main_listen_start();
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client = hash_lookup(master_requests, POINTER_CAST(reply->tag));
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (client == NULL)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_fatal("Master sent reply with unknown tag %u", reply->tag);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen hash_remove(master_requests, POINTER_CAST(reply->tag));
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (client != &destroyed_client) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client_call_master_callback(client, reply);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* NOTE: client may be destroyed now */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenvoid master_request_login(struct client *client, master_callback_t *callback,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen unsigned int auth_pid, unsigned int auth_id)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen buffer_t *buf;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct master_login_request *req;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct stat st;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const unsigned char *data;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen size_t size;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen ssize_t ret;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen unsigned int cmd_tag_size;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_assert(auth_pid != 0);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen data = i_stream_get_data(client->input, &size);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen cmd_tag_size = client->auth_command_tag == NULL ? 0 :
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen strlen(client->auth_command_tag);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen buf = buffer_create_dynamic(pool_datastack_create(),
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen sizeof(*req) + size + cmd_tag_size);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen buffer_write(buf, sizeof(*req), client->auth_command_tag, cmd_tag_size);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen buffer_write(buf, sizeof(*req) + cmd_tag_size, data, size);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen req = buffer_get_space_unsafe(buf, 0, sizeof(*req));
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen req->version = MASTER_LOGIN_PROTOCOL_VERSION;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen req->tag = ++master_tag_counter;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (req->tag == 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen req->tag = ++master_tag_counter;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen req->auth_pid = auth_pid;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen req->auth_id = auth_id;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen req->local_ip = client->local_ip;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen req->remote_ip = client->ip;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen req->cmd_tag_size = cmd_tag_size;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen req->data_size = req->cmd_tag_size + size;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#if (LOGIN_MAX_INBUF_SIZE*2) != MASTER_LOGIN_MAX_DATA_SIZE
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen# error buffer max sizes unsynced
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#endif
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_assert(req->data_size <= LOGIN_MAX_INBUF_SIZE);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (fstat(client->fd, &st) < 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_fatal("fstat(client) failed: %m");
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen req->ino = st.st_ino;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen ret = fd_send(master_fd, client->fd, buf->data, buf->used);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (ret < 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_fatal("fd_send(%d) failed: %m", client->fd);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if ((size_t)ret != buf->used) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_fatal("fd_send() sent only %d of %d bytes",
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen (int)ret, (int)buf->used);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client->master_tag = req->tag;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client->master_callback = callback;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen hash_insert(master_requests, POINTER_CAST(req->tag), client);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenvoid master_request_abort(struct client *client)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct master_login_reply reply;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* we're still going to get the reply from the master, so just
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen remember that we want to ignore it */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen hash_update(master_requests, POINTER_CAST(client->master_tag),
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen &destroyed_client);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen memset(&reply, 0, sizeof(reply));
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen reply.status = MASTER_LOGIN_STATUS_INTERNAL_ERROR;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client_call_master_callback(client, &reply);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenvoid master_notify_state_change(enum master_login_state state)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct master_login_request req;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (io_master == NULL)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen memset(&req, 0, sizeof(req));
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen req.version = MASTER_LOGIN_PROTOCOL_VERSION;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen req.tag = state;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen req.ino = (ino_t)-1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* sending -1 as fd does the notification */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (fd_send(master_fd, -1, &req, sizeof(req)) != sizeof(req))
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_fatal("fd_send(-1) failed: %m");
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenvoid master_close(void)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (io_master == NULL)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen io_remove(&io_master);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (close(master_fd) < 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_fatal("close(master) failed: %m");
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen master_fd = -1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen closing_down = TRUE;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen main_listen_stop();
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen main_unref();
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* may call this function again through main_unref() */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen clients_destroy_all();
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void master_exec(int fd)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen static char dovecot[] = "dovecot";
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen char *argv[] = { dovecot, NULL };
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen switch (fork()) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen case -1:
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_fatal("fork() failed: %m");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case 0:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (dup2(fd, 0) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_fatal("master_exec: dup2(%d, 0) failed: %m", fd);
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen (void)close(fd);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (setsid() < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_fatal("setsid() failed: %m");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen env_put("DOVECOT_INETD=1");
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen execv(SBINDIR"/dovecot", argv);
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen SBINDIR"/dovecot");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen default:
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen (void)close(fd);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void master_read_env(int fd)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct istream *input;
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen const char *line;
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen env_clean();
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen /* read environment variable lines until empty line comes */
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen input = i_stream_create_fd(fd, 8192, FALSE);
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen do {
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen switch (i_stream_read(input)) {
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen case -1:
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen i_fatal("EOF while reading environment from master");
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen case -2:
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen i_fatal("Too large environment line from master");
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen }
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen while ((line = i_stream_next_line(input)) != NULL &&
cbf7138b49d32fce0645dc6523fbb42cc07cb2faTimo Sirainen *line != '\0')
cbf7138b49d32fce0645dc6523fbb42cc07cb2faTimo Sirainen env_put(line);
b9b48aaaebf6f72dfab567cda073cde8a7b26598Timo Sirainen } while (line == NULL);
b9b48aaaebf6f72dfab567cda073cde8a7b26598Timo Sirainen
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen i_stream_destroy(&input);
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenint master_connect(const char *group_name)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen const char *path = PKG_RUNDIR"/master";
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int i, fd = -1;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen for (i = 0; i < 5 && fd == -1; i++) {
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen fd = net_connect_unix(path);
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen if (fd != -1)
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (errno == ECONNREFUSED) {
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen if (unlink(path) < 0)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen i_error("unlink(%s) failed: %m", path);
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen } else if (errno != ENOENT) {
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen i_fatal("Can't connect to master UNIX socket %s: %m",
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen path);
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen }
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen /* need to create it */
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen fd = net_listen_unix(path, 16);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen if (fd != -1) {
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen master_exec(fd);
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen fd = -1;
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen } else if (errno != EADDRINUSE) {
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen i_fatal("Can't create master UNIX socket %s: %m", path);
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainen }
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainen }
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainen
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainen if (fd == -1)
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainen i_fatal("Couldn't use/create UNIX socket %s", path);
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainen
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainen if (group_name[0] == '\0')
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainen i_fatal("No login group name set");
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen if (strlen(group_name) >= 256)
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen i_fatal("Login group name too large: %s", group_name);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen /* group_name length is now guaranteed to be in range of 1..255 so we
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen can send <length byte><name> */
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen group_name = t_strdup_printf("%c%s", (unsigned char)strlen(group_name),
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen group_name);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen if (write_full(fd, group_name, strlen(group_name)) < 0)
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen i_fatal("write_full(master_fd) failed: %m");
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen master_read_env(fd);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen return fd;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen}
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainenstatic void master_input(void *context ATTR_UNUSED)
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen{
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen int ret;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen ret = net_receive(master_fd, master_buf + master_pos,
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen sizeof(master_buf) - master_pos);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen if (ret < 0) {
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen /* master died, kill all clients logging in */
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen master_close();
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen return;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen }
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen master_pos += ret;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen if (master_pos < sizeof(master_buf))
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen return;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen /* reply is now read */
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen request_handle((void *)master_buf);
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainen master_pos = 0;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen}
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainenvoid master_init(int fd)
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen{
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen main_ref();
0db4290d60bfa00774f628276d38654c56abd68cTimo Sirainen
0db4290d60bfa00774f628276d38654c56abd68cTimo Sirainen master_fd = fd;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen master_requests = hash_create(system_pool, system_pool,
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen 0, NULL, NULL);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen master_pos = 0;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen io_master = io_add(master_fd, IO_READ, master_input, NULL);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen}
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainenvoid master_deinit(void)
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen{
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen hash_destroy(&master_requests);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen if (io_master != NULL)
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen io_remove(&io_master);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen}
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen