master.c revision 087939d3fa9c4056419386c9d6c81f147de534cd
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic unsigned int master_tag_counter;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic unsigned int master_pos;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic char master_buf[sizeof(struct master_login_reply)];
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void client_call_master_callback(struct client *client,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void request_handle(struct master_login_reply *reply)
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 client = hash_lookup(master_requests, POINTER_CAST(reply->tag));
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_fatal("Master sent reply with unknown tag %u", reply->tag);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen hash_remove(master_requests, POINTER_CAST(reply->tag));
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* NOTE: client may be destroyed now */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenvoid master_request_login(struct client *client, master_callback_t *callback,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const unsigned char *data;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen data = i_stream_get_data(client->input, &size);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen cmd_tag_size = client->auth_command_tag == NULL ? 0 :
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen buf = buffer_create_dynamic(pool_datastack_create(),
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#if (LOGIN_MAX_INBUF_SIZE*2) != MASTER_LOGIN_MAX_DATA_SIZE
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_assert(req->data_size <= LOGIN_MAX_INBUF_SIZE);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen ret = fd_send(master_fd, client->fd, buf->data, buf->used);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_fatal("fd_send(%d) failed: %m", client->fd);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen hash_insert(master_requests, POINTER_CAST(req->tag), client);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenvoid master_request_abort(struct client *client)
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 reply.status = MASTER_LOGIN_STATUS_INTERNAL_ERROR;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenvoid master_notify_state_change(enum master_login_state state)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* sending -1 as fd does the notification */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (fd_send(master_fd, -1, &req, sizeof(req)) != sizeof(req))
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* may call this function again through main_unref() */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_fatal("master_exec: dup2(%d, 0) failed: %m", fd);
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m",
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen /* read environment variable lines until empty line comes */
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen i_fatal("EOF while reading environment from master");
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen i_fatal("Too large environment line from master");
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen while ((line = i_stream_next_line(input)) != NULL &&
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen i_fatal("Can't connect to master UNIX socket %s: %m",
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen /* need to create it */
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen i_fatal("Can't create master UNIX socket %s: %m", path);
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainen i_fatal("Couldn't use/create UNIX socket %s", path);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen i_fatal("Login group name too large: %s", group_name);
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 if (write_full(fd, group_name, strlen(group_name)) < 0)
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainenstatic void master_input(void *context ATTR_UNUSED)
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen ret = net_receive(master_fd, master_buf + master_pos,
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen /* master died, kill all clients logging in */
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen /* reply is now read */
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen master_requests = hash_create(system_pool, system_pool,