bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen#include "common.h"
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen#include "llist.h"
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen#include "istream.h"
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen#include "ostream.h"
7a60e1dc9e93ef3f7c7fe1af6385a0bfa1e31bc3Timo Sirainen#include "strescape.h"
24ff367825286b52be4edb92df2fff0dd54cdf10Timo Sirainen#include "master-service.h"
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen#include "master-interface.h"
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen#include "connect-limit.h"
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen#include "penalty.h"
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen#include "anvil-connection.h"
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen#include <unistd.h>
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen#define MAX_INBUF_SIZE 1024
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen#define ANVIL_CLIENT_PROTOCOL_MAJOR_VERSION 1
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen#define ANVIL_CLIENT_PROTOCOL_MINOR_VERSION 0
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenstruct anvil_connection {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen struct anvil_connection *prev, *next;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen int fd;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen struct istream *input;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen struct ostream *output;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen struct io *io;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool version_received:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool handshaked:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool master:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool fifo:1;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen};
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
c2d398246d2a5bb42beb083370695484142295f6Phil Carmodystatic struct anvil_connection *anvil_connections = NULL;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenstatic const char *const *
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenanvil_connection_next_line(struct anvil_connection *conn)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen{
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen const char *line;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
12db7b091f9866c2f2e81205350d3bb452d31aa2Timo Sirainen line = i_stream_next_line(conn->input);
7a60e1dc9e93ef3f7c7fe1af6385a0bfa1e31bc3Timo Sirainen return line == NULL ? NULL : t_strsplit_tabescaped(line);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen}
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenstatic int
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenanvil_connection_request(struct anvil_connection *conn,
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen const char *const *args, const char **error_r)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen{
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen const char *cmd = args[0];
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen unsigned int value, checksum;
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen time_t stamp;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen pid_t pid;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen args++;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if (strcmp(cmd, "CONNECT") == 0) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if (args[0] == NULL || args[1] == NULL) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen *error_r = "CONNECT: Not enough parameters";
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return -1;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen }
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch if (str_to_pid(args[0], &pid) < 0) {
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch *error_r = "CONNECT: Invalid pid";
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch return -1;
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch }
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen connect_limit_connect(connect_limit, pid, args[1]);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen } else if (strcmp(cmd, "DISCONNECT") == 0) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if (args[0] == NULL || args[1] == NULL) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen *error_r = "DISCONNECT: Not enough parameters";
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return -1;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen }
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch if (str_to_pid(args[0], &pid) < 0) {
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch *error_r = "DISCONNECT: Invalid pid";
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch return -1;
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch }
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen connect_limit_disconnect(connect_limit, pid, args[1]);
fc0b7b7df3888ffd6292050d066919dd31e9c0ccTimo Sirainen } else if (strcmp(cmd, "CONNECT-DUMP") == 0) {
fc0b7b7df3888ffd6292050d066919dd31e9c0ccTimo Sirainen connect_limit_dump(connect_limit, conn->output);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen } else if (strcmp(cmd, "KILL") == 0) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if (args[0] == NULL) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen *error_r = "KILL: Not enough parameters";
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return -1;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen }
c405d7235ba2e21a306eacc9fc0f15e66f9ee718Timo Sirainen if (!conn->master) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen *error_r = "KILL sent by a non-master connection";
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return -1;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen }
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch if (str_to_pid(args[0], &pid) < 0) {
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch *error_r = "KILL: Invalid pid";
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch return -1;
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch }
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen connect_limit_disconnect_pid(connect_limit, pid);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen } else if (strcmp(cmd, "LOOKUP") == 0) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if (args[0] == NULL) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen *error_r = "LOOKUP: Not enough parameters";
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return -1;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen }
5dd73391f9dfb2396cf2060402017f6080c93dc7Timo Sirainen if (conn->output == NULL) {
5dd73391f9dfb2396cf2060402017f6080c93dc7Timo Sirainen *error_r = "LOOKUP on a FIFO, can't send reply";
5dd73391f9dfb2396cf2060402017f6080c93dc7Timo Sirainen return -1;
5dd73391f9dfb2396cf2060402017f6080c93dc7Timo Sirainen }
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen value = connect_limit_lookup(connect_limit, args[0]);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(conn->output,
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen t_strdup_printf("%u\n", value));
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen } else if (strcmp(cmd, "PENALTY-GET") == 0) {
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen if (args[0] == NULL) {
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen *error_r = "PENALTY-GET: Not enough parameters";
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen return -1;
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen }
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen value = penalty_get(penalty, args[0], &stamp);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(conn->output,
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen t_strdup_printf("%u %s\n", value, dec2str(stamp)));
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen } else if (strcmp(cmd, "PENALTY-INC") == 0) {
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen if (args[0] == NULL || args[1] == NULL || args[2] == NULL) {
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen *error_r = "PENALTY-INC: Not enough parameters";
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen return -1;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen }
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen if (str_to_uint(args[1], &checksum) < 0 ||
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen str_to_uint(args[2], &value) < 0 ||
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen value > PENALTY_MAX_VALUE ||
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen (value == 0 && checksum != 0)) {
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen *error_r = "PENALTY-INC: Invalid parameters";
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen return -1;
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen }
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen penalty_inc(penalty, args[0], checksum, value);
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen } else if (strcmp(cmd, "PENALTY-SET-EXPIRE-SECS") == 0) {
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen if (args[0] == NULL || str_to_uint(args[0], &value) < 0) {
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen *error_r = "PENALTY-SET-EXPIRE-SECS: "
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen "Invalid parameters";
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen return -1;
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen }
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen penalty_set_expire_secs(penalty, value);
8825740187b8aaca9c39c4fd6a0b79d480eb143fTimo Sirainen } else if (strcmp(cmd, "PENALTY-DUMP") == 0) {
8825740187b8aaca9c39c4fd6a0b79d480eb143fTimo Sirainen penalty_dump(penalty, conn->output);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen } else {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen *error_r = t_strconcat("Unknown command: ", cmd, NULL);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return -1;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen }
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen return 0;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen}
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainenstatic void anvil_connection_input(struct anvil_connection *conn)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen{
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen const char *line, *const *args, *error;
5dd73391f9dfb2396cf2060402017f6080c93dc7Timo Sirainen
12db7b091f9866c2f2e81205350d3bb452d31aa2Timo Sirainen switch (i_stream_read(conn->input)) {
12db7b091f9866c2f2e81205350d3bb452d31aa2Timo Sirainen case -2:
12db7b091f9866c2f2e81205350d3bb452d31aa2Timo Sirainen i_error("BUG: Anvil client connection sent too much data");
12db7b091f9866c2f2e81205350d3bb452d31aa2Timo Sirainen anvil_connection_destroy(conn);
12db7b091f9866c2f2e81205350d3bb452d31aa2Timo Sirainen return;
12db7b091f9866c2f2e81205350d3bb452d31aa2Timo Sirainen case -1:
12db7b091f9866c2f2e81205350d3bb452d31aa2Timo Sirainen anvil_connection_destroy(conn);
12db7b091f9866c2f2e81205350d3bb452d31aa2Timo Sirainen return;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen }
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if (!conn->version_received) {
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen if ((line = i_stream_next_line(conn->input)) == NULL)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen if (!version_string_verify(line, "anvil",
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen ANVIL_CLIENT_PROTOCOL_MAJOR_VERSION)) {
ab96e72a574ff5e579500513cd62f14ec142e467Timo Sirainen if (anvil_restarted && (conn->master || conn->fifo)) {
ab96e72a574ff5e579500513cd62f14ec142e467Timo Sirainen /* old pending data. ignore input until we get
ab96e72a574ff5e579500513cd62f14ec142e467Timo Sirainen the handshake. */
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainen anvil_connection_input(conn);
ad0df8e7d7519c0c0129723c860d06a1f84cdb89Timo Sirainen return;
ab96e72a574ff5e579500513cd62f14ec142e467Timo Sirainen }
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen i_error("Anvil client not compatible with this server "
ab96e72a574ff5e579500513cd62f14ec142e467Timo Sirainen "(mixed old and new binaries?) %s", line);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen anvil_connection_destroy(conn);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen }
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen conn->version_received = TRUE;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen }
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen while ((args = anvil_connection_next_line(conn)) != NULL) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if (args[0] != NULL) {
c87043283d789e8dc544162ca8e0ddf74a98fb3cTimo Sirainen if (anvil_connection_request(conn, args, &error) < 0) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen i_error("Anvil client input error: %s", error);
c87043283d789e8dc544162ca8e0ddf74a98fb3cTimo Sirainen anvil_connection_destroy(conn);
c87043283d789e8dc544162ca8e0ddf74a98fb3cTimo Sirainen break;
c87043283d789e8dc544162ca8e0ddf74a98fb3cTimo Sirainen }
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen }
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen }
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen}
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
5dd73391f9dfb2396cf2060402017f6080c93dc7Timo Sirainenstruct anvil_connection *
5dd73391f9dfb2396cf2060402017f6080c93dc7Timo Sirainenanvil_connection_create(int fd, bool master, bool fifo)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen{
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen struct anvil_connection *conn;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen conn = i_new(struct anvil_connection, 1);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen conn->fd = fd;
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi conn->input = i_stream_create_fd(fd, MAX_INBUF_SIZE);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (!fifo) {
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi conn->output = o_stream_create_fd(fd, (size_t)-1);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_set_no_error_handling(conn->output, TRUE);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen }
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen conn->io = io_add(fd, IO_READ, anvil_connection_input, conn);
c405d7235ba2e21a306eacc9fc0f15e66f9ee718Timo Sirainen conn->master = master;
d19fb2745f553746e283c6fc46c82fb402fc3e9bTimo Sirainen conn->fifo = fifo;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen DLLIST_PREPEND(&anvil_connections, conn);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return conn;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen}
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenvoid anvil_connection_destroy(struct anvil_connection *conn)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen{
d19fb2745f553746e283c6fc46c82fb402fc3e9bTimo Sirainen bool fifo = conn->fifo;
d19fb2745f553746e283c6fc46c82fb402fc3e9bTimo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen DLLIST_REMOVE(&anvil_connections, conn);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen io_remove(&conn->io);
12db7b091f9866c2f2e81205350d3bb452d31aa2Timo Sirainen i_stream_destroy(&conn->input);
be5773cb4d6edae8a5d9f300c3c7375cdd33826eJosef 'Jeff' Sipek o_stream_destroy(&conn->output);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if (close(conn->fd) < 0)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen i_error("close(anvil conn) failed: %m");
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen i_free(conn);
24ff367825286b52be4edb92df2fff0dd54cdf10Timo Sirainen
d19fb2745f553746e283c6fc46c82fb402fc3e9bTimo Sirainen if (!fifo)
d19fb2745f553746e283c6fc46c82fb402fc3e9bTimo Sirainen master_service_client_connection_destroyed(master_service);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen}
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenvoid anvil_connections_destroy_all(void)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen{
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen while (anvil_connections != NULL)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen anvil_connection_destroy(anvil_connections);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen}