From: Markus Valentin Date: Thu, 8 Dec 2022 13:39:06 +0000 (+0100) Subject: lib-doveadm: Use dns_lookup() if dns_client_socket_path is set X-Git-Tag: 2.4.0~3273 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=747ad2fd8881c4538c1036dab01ffdf251f0d58d;p=thirdparty%2Fdovecot%2Fcore.git lib-doveadm: Use dns_lookup() if dns_client_socket_path is set --- diff --git a/src/lib-doveadm/Makefile.am b/src/lib-doveadm/Makefile.am index eb6410b340..b1233ae9e5 100644 --- a/src/lib-doveadm/Makefile.am +++ b/src/lib-doveadm/Makefile.am @@ -3,6 +3,7 @@ noinst_LTLIBRARIES = libdoveadm.la AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib \ -I$(top_srcdir)/src/lib-auth \ + -I$(top_srcdir)/src/lib-dns \ -I$(top_srcdir)/src/lib-mail \ -I$(top_srcdir)/src/lib-master \ -I$(top_srcdir)/src/lib-ssl-iostream diff --git a/src/lib-doveadm/doveadm-client.c b/src/lib-doveadm/doveadm-client.c index 007d4cda8e..9177568f13 100644 --- a/src/lib-doveadm/doveadm-client.c +++ b/src/lib-doveadm/doveadm-client.c @@ -14,11 +14,16 @@ #include "master-service.h" #include "doveadm-protocol.h" #include "doveadm-client.h" +#include "dns-lookup.h" + +#include #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, @@ -33,6 +38,7 @@ struct doveadm_client { 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; @@ -43,6 +49,7 @@ struct doveadm_client { 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; @@ -80,6 +87,9 @@ void doveadm_client_settings_dup(const struct doveadm_client_settings *src, 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); @@ -643,6 +653,11 @@ static struct connection_settings doveadm_client_set = { .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, @@ -661,6 +676,72 @@ static int doveadm_client_connect(struct doveadm_client *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) @@ -669,6 +750,14 @@ doveadm_client_resolve_hostname(struct doveadm_client *conn, 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); @@ -720,12 +809,16 @@ int doveadm_client_create(const struct doveadm_client_settings *set, 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; @@ -782,6 +875,7 @@ static void doveadm_client_destroy(struct doveadm_client **_conn) *_conn = NULL; conn->destroyed = TRUE; + timeout_remove(&conn->to_create_failed); doveadm_client_destroy_int(conn); doveadm_client_unref(&conn); } diff --git a/src/lib-doveadm/doveadm-client.h b/src/lib-doveadm/doveadm-client.h index 19ca5a21b5..23ade6cd84 100644 --- a/src/lib-doveadm/doveadm-client.h +++ b/src/lib-doveadm/doveadm-client.h @@ -38,6 +38,9 @@ struct doveadm_client_settings { /* Port to use for TCP connections. */ in_port_t port; + /* UNIX socket path to connect to for dns lookups. */ + const char *dns_client_socket_path; + /* Username and password for authentication */ const char *username, *password;