director-test.c revision cca4ba2a504d70a9fe9fee37f8433997359de52c
/*
This program accepts incoming unauthenticated IMAP connections from
port 14300. If the same user is connecting to multiple different local IPs,
it logs an error (i.e. director is not working right then).
This program also accepts incoming director connections on port 9091 and
forwards them to local_ip:9090. To make this work properly, director
executable must be given -t 9091 parameter. The idea is that this test tool
hooks between all director connections and can then add delays or break the
connections.
Finally, this program connects to director-admin socket where it adds
and removes mail hosts.
*/
#include "lib.h"
#include "ioloop.h"
#include "istream.h"
#include "ostream.h"
#include "write-full.h"
#include "hash.h"
#include "llist.h"
#include "imap-parser.h"
#include "master-service.h"
#include "master-service-settings.h"
#include "director-settings.h"
#include <stdlib.h>
#include <unistd.h>
#define IMAP_PORT 14300
#define DIRECTOR_IN_PORT 9091
#define DIRECTOR_OUT_PORT 9090
#define ADMIN_RANDOM_TIMEOUT_MSECS 500
#define DIRECTOR_CONN_MAX_DELAY_MSECS 100
#define DIRECTOR_DISCONNECT_TIMEOUT_SECS 10
struct host {
int refcount;
unsigned int vhost_count;
};
struct user {
char *username;
unsigned int connections;
};
struct imap_client {
int fd;
struct imap_parser *parser;
char *username;
};
struct director_connection {
};
struct admin_connection {
char *path;
int fd;
bool pending_command;
};
static struct imap_client *imap_clients;
static struct director_connection *director_connections;
static struct admin_connection *admin;
static struct timeout *to_disconnect;
{
return;
}
{
i_fatal("net_getsockname() failed: %m");
i_error("User logging into unknown host %s",
net_ip2addr(&local_ip));
}
i_error("user %s: old connection from %s, new from %s. "
"%u old connections, last was %u secs ago",
}
user->connections++;
}
{
}
{
int ret;
if (ret < 0) {
if (ret == -2)
return 0;
return -1;
}
return -1;
args++;
return -1;
args++;
return -1;
return -1;
"* BYE Out.\r\n",
return 0;
t_strconcat("* CAPABILITY IMAP4rev1\r\n",
} else {
}
return 1;
}
{
int ret;
case -2:
i_error("imap: Too much input");
return;
case -1:
return;
default:
break;
}
if (ret < 0) {
i_error("imap: Invalid input");
}
}
static void imap_client_create(int fd)
{
struct imap_client *client;
"* OK [CAPABILITY IMAP4rev1] director-test ready.\r\n");
}
{
if (--user->connections == 0) {
user);
}
}
}
static void
{
const unsigned char *data;
return;
}
}
}
{
}
{
}
{
}
static void
{
struct director_connection *conn;
int out_fd;
if (out_fd == -1) {
i_close_fd(&in_fd);
return;
}
}
{
}
{
unsigned int local_port;
i_fatal("net_getsockname() failed: %m");
if (local_port == IMAP_PORT)
else if (local_port == DIRECTOR_IN_PORT)
else {
return;
}
}
static void
{
}
{
const char *line;
}
i_fatal("director-doveadm: Connection lost");
}
{
unsigned int i, count;
if (conn->pending_command)
return;
}
{
#define DIRECTOR_ADMIN_HANDSHAKE "VERSION\tdirector-doveadm\t1\t0\n"
struct admin_connection *conn;
const char *line;
i_fatal("%s not a compatible director-doveadm socket",
}
return conn;
}
{
}
{
const char *line;
if (*line == '\0')
break;
/* ip vhost-count user-count */
T_BEGIN {
i_fatal("host list broken");
} T_END;
}
i_fatal("Couldn't read hosts list");
}
static void ATTR_NULL(1)
{
struct director_connection *conn;
unsigned int i, count = 0;
count++;
if (count != 0) {
i++;
}
}
}
static void main_init(const char *admin_path)
{
director_connection_disconnect_timeout, (void *)NULL);
}
static void main_deinit(void)
{
struct hash_iterate_context *iter;
char *username;
while (imap_clients != NULL) {
}
while (director_connections != NULL) {
}
host_unref(&host);
}
{
const char *admin_path;
if (master_getopt(master_service) > 0)
return FATAL_DEFAULT;
if (admin_path == NULL)
i_fatal("director-doveadm socket path missing");
main_deinit();
return 0;
}