#include "master-service.h"
#include "doveadm-protocol.h"
#include "doveadm-client.h"
+#include "dns-lookup.h"
+
+#include <sysexits.h>
#define DOVEADM_LOG_CHANNEL_ID 'L'
#define MAX_INBUF_SIZE (1024*32)
+#define DOVEADM_CLIENT_DNS_TIMEOUT_MSECS (1000*10)
+
enum doveadm_client_reply_state {
DOVEADM_CLIENT_REPLY_STATE_DONE = 0,
DOVEADM_CLIENT_REPLY_STATE_PRINT,
pool_t pool;
struct timeout *to_destroy;
+ struct timeout *to_create_failed;
struct io *io_log;
struct istream *log_input;
struct ssl_iostream *ssl_iostream;
struct doveadm_client_cmd_settings delayed_set;
doveadm_client_cmd_callback_t *callback;
+ struct dns_lookup *dns_lookup;
unsigned int ips_count;
struct ip_addr *ips;
dest_r->ip = src->ip;
dest_r->port = src->port;
+ dest_r->dns_client_socket_path = src->dns_client_socket_path != NULL ?
+ p_strdup(pool, src->dns_client_socket_path) : "";
+
dest_r->username = p_strdup(pool, src->username);
dest_r->password = p_strdup(pool, src->password);
.client_connect_timeout_msecs = DOVEADM_TCP_CONNECT_TIMEOUT_SECS*1000,
};
+struct doveadm_client_dns_lookup_context {
+ struct doveadm_client *conn;
+ const char *error;
+};
+
static void doveadm_client_connect_init(struct doveadm_client *conn)
{
connection_init_client_ip(doveadm_clients, &conn->conn,
return 0;
}
+static void
+doveadm_client_create_failed(struct doveadm_client_dns_lookup_context *ctx)
+{
+ struct doveadm_client *conn = ctx->conn;
+ timeout_remove(&conn->to_create_failed);
+
+ struct doveadm_server_reply reply = {
+ .exit_code = EX_DATAERR,
+ .error = ctx->error,
+ };
+ doveadm_client_callback(conn, &reply);
+ pool_unref(&conn->pool);
+}
+
+static void
+doveadm_client_dns_lookup_callback(const struct dns_lookup_result *result,
+ struct doveadm_client_dns_lookup_context *ctx)
+{
+ struct doveadm_client *conn = ctx->conn;
+ const char *error;
+
+ if (result->error != NULL) {
+ ctx->error = p_strdup_printf(conn->pool,
+ "dns_lookup(%s) failed: %s",
+ conn->set.hostname, result->error);
+ conn->to_create_failed =
+ timeout_add_short(0, doveadm_client_create_failed, ctx);
+ return;
+ }
+
+ i_assert(result->ips_count > 0);
+ conn->ips = p_new(conn->pool, struct ip_addr, 1);
+ conn->ips[0] = result->ips[0];
+ conn->ips_count = 1;
+
+ doveadm_client_connect_init(conn);
+ if (doveadm_client_connect(conn, &error) < 0) {
+ ctx->error = p_strdup(conn->pool, error);
+ conn->to_create_failed =
+ timeout_add_short(0, doveadm_client_create_failed, ctx);
+ }
+}
+
+static int doveadm_client_dns_lookup(struct doveadm_client *conn,
+ const char **error_r)
+{
+ struct doveadm_client_dns_lookup_context *ctx =
+ p_new(conn->pool, struct doveadm_client_dns_lookup_context, 1);
+ struct dns_lookup_settings dns_set;
+
+ i_zero(&dns_set);
+ dns_set.dns_client_socket_path = conn->set.dns_client_socket_path;
+ dns_set.timeout_msecs = DOVEADM_CLIENT_DNS_TIMEOUT_MSECS;
+ dns_set.event_parent = conn->conn.event;
+
+ ctx->conn = conn;
+
+ if (dns_lookup(conn->set.hostname, &dns_set,
+ doveadm_client_dns_lookup_callback, ctx,
+ &conn->dns_lookup) != 0) {
+ *error_r = t_strdup(ctx->error);
+ return -1;
+ }
+ return 0;
+}
+
static int
doveadm_client_resolve_hostname(struct doveadm_client *conn,
const char **error_r)
unsigned int ips_count;
int ret;
+ if (conn->set.dns_client_socket_path[0] != '\0') {
+ /* If there is an dns_client_socket_path do a dns
+ lookup. */
+ if (doveadm_client_dns_lookup(conn, error_r) < 0)
+ return -1;
+ return 0;
+ }
+
ret = net_gethostbyname(conn->set.hostname, &ips, &ips_count);
if (ret == 0) {
conn->ips = p_new(conn->pool, struct ip_addr, 1);
return -1;
}
- if (doveadm_client_connect(conn, error_r) < 0) {
- connection_deinit(&conn->conn);
- pool_unref(&pool);
- return -1;
+ if (conn->dns_lookup == NULL) {
+ /* Only connect here if this is not using an async dns
+ lookup. */
+ if (doveadm_client_connect(conn, error_r) < 0) {
+ connection_deinit(&conn->conn);
+ pool_unref(&pool);
+ return -1;
+ }
+ conn->state = DOVEADM_CLIENT_REPLY_STATE_DONE;
}
- conn->state = DOVEADM_CLIENT_REPLY_STATE_DONE;
*conn_r = conn;
return 0;
*_conn = NULL;
conn->destroyed = TRUE;
+ timeout_remove(&conn->to_create_failed);
doveadm_client_destroy_int(conn);
doveadm_client_unref(&conn);
}