From: Timo Sirainen Date: Tue, 2 Mar 2010 09:40:52 +0000 (+0200) Subject: lmtp proxy: Added support for DNS lookups. X-Git-Tag: 2.0.beta4~143 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=98720d3b830e8ec762e9bdde94a71c0ef184595d;p=thirdparty%2Fdovecot%2Fcore.git lmtp proxy: Added support for DNS lookups. --HG-- branch : HEAD --- diff --git a/src/lib-lda/Makefile.am b/src/lib-lda/Makefile.am index c9763f9fd4..9100d596bb 100644 --- a/src/lib-lda/Makefile.am +++ b/src/lib-lda/Makefile.am @@ -4,6 +4,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib \ -I$(top_srcdir)/src/lib-settings \ -I$(top_srcdir)/src/lib-master \ + -I$(top_srcdir)/src/lib-dns \ -I$(top_srcdir)/src/lib-imap \ -I$(top_srcdir)/src/lib-mail \ -I$(top_srcdir)/src/lib-storage diff --git a/src/lib-lda/lmtp-client.c b/src/lib-lda/lmtp-client.c index 07eead61b2..671519aedc 100644 --- a/src/lib-lda/lmtp-client.c +++ b/src/lib-lda/lmtp-client.c @@ -6,11 +6,13 @@ #include "network.h" #include "istream.h" #include "ostream.h" +#include "dns-lookup.h" #include "lmtp-client.h" #include #define LMTP_MAX_LINE_LEN 1024 +#define LMTP_CLIENT_DNS_LOOKUP_TIMEOUT_MSECS (60*1000) enum lmtp_input_state { LMTP_INPUT_STATE_GREET, @@ -33,10 +35,9 @@ struct lmtp_rcpt { struct lmtp_client { pool_t pool; - const char *mail_from; int refcount; - const char *my_hostname; + struct lmtp_client_settings set; const char *host; struct ip_addr ip; unsigned int port; @@ -71,21 +72,23 @@ struct lmtp_client { static void lmtp_client_send_rcpts(struct lmtp_client *client); struct lmtp_client * -lmtp_client_init(const char *mail_from, const char *my_hostname, +lmtp_client_init(const struct lmtp_client_settings *set, lmtp_finish_callback_t *finish_callback, void *context) { struct lmtp_client *client; pool_t pool; - i_assert(*mail_from == '<'); - i_assert(*my_hostname != '\0'); + i_assert(*set->mail_from == '<'); + i_assert(*set->my_hostname != '\0'); pool = pool_alloconly_create("lmtp client", 512); client = p_new(pool, struct lmtp_client, 1); client->refcount = 1; client->pool = pool; - client->mail_from = p_strdup(pool, mail_from); - client->my_hostname = p_strdup(pool, my_hostname); + client->set.mail_from = p_strdup(pool, set->mail_from); + client->set.my_hostname = p_strdup(pool, set->my_hostname); + client->set.dns_client_socket_path = + p_strdup(pool, set->dns_client_socket_path); client->finish_callback = finish_callback; client->finish_context = context; client->fd = -1; @@ -319,15 +322,17 @@ static void lmtp_client_send_handshake(struct lmtp_client *client) switch (client->protocol) { case LMTP_CLIENT_PROTOCOL_LMTP: o_stream_send_str(client->output, - t_strdup_printf("LHLO %s\r\n", client->my_hostname)); + t_strdup_printf("LHLO %s\r\n", + client->set.my_hostname)); break; case LMTP_CLIENT_PROTOCOL_SMTP: o_stream_send_str(client->output, - t_strdup_printf("EHLO %s\r\n", client->my_hostname)); + t_strdup_printf("EHLO %s\r\n", + client->set.my_hostname)); break; } o_stream_send_str(client->output, - t_strdup_printf("MAIL FROM:%s\r\n", client->mail_from)); + t_strdup_printf("MAIL FROM:%s\r\n", client->set.mail_from)); o_stream_uncork(client->output); } @@ -466,22 +471,12 @@ static int lmtp_client_output(struct lmtp_client *client) return ret; } -int lmtp_client_connect_tcp(struct lmtp_client *client, - enum lmtp_client_protocol protocol, - const char *host, unsigned int port) +static int lmtp_client_connect(struct lmtp_client *client) { - client->host = p_strdup(client->pool, host); - client->port = port; - client->protocol = protocol; - - if (net_addr2ip(host, &client->ip) < 0) { - i_error("lmtp client: %s is not a valid IP", host); - return -1; - } - - client->fd = net_connect_ip(&client->ip, port, NULL); + client->fd = net_connect_ip(&client->ip, client->port, NULL); if (client->fd == -1) { - i_error("lmtp client: connect(%s, %u) failed: %m", host, port); + i_error("lmtp client: connect(%s, %u) failed: %m", + client->host, client->port); return -1; } client->input = @@ -491,7 +486,55 @@ int lmtp_client_connect_tcp(struct lmtp_client *client, /* we're already sending data in ostream, so can't use IO_WRITE here */ client->io = io_add(client->fd, IO_READ, lmtp_client_wait_connect, client); + return 0; +} + +static void lmtp_client_dns_done(const struct dns_lookup_result *result, + struct lmtp_client *client) +{ + if (result->ret != 0) { + i_error("lmtp client: DNS lookup of %s failed: %s", + client->host, result->error); + lmtp_client_fail(client, ERRSTR_TEMP_REMOTE_FAILURE + " (DNS lookup)"); + } else { + client->ip = result->ips[0]; + if (lmtp_client_connect(client) < 0) { + lmtp_client_fail(client, ERRSTR_TEMP_REMOTE_FAILURE + " (connect)"); + } + } +} + +int lmtp_client_connect_tcp(struct lmtp_client *client, + enum lmtp_client_protocol protocol, + const char *host, unsigned int port) +{ + struct dns_lookup_settings dns_lookup_set; + client->input_state = LMTP_INPUT_STATE_GREET; + client->host = p_strdup(client->pool, host); + client->port = port; + client->protocol = protocol; + + if (*host == '\0') { + i_error("lmtp client: host not given"); + return -1; + } + + memset(&dns_lookup_set, 0, sizeof(dns_lookup_set)); + dns_lookup_set.dns_client_socket_path = + client->set.dns_client_socket_path; + dns_lookup_set.timeout_msecs = LMTP_CLIENT_DNS_LOOKUP_TIMEOUT_MSECS; + + if (net_addr2ip(host, &client->ip) < 0) { + if (dns_lookup(host, &dns_lookup_set, + lmtp_client_dns_done, client) < 0) + return -1; + } else { + if (lmtp_client_connect(client) < 0) + return -1; + } return 0; } diff --git a/src/lib-lda/lmtp-client.h b/src/lib-lda/lmtp-client.h index 77d3e2a5ed..df4b202de3 100644 --- a/src/lib-lda/lmtp-client.h +++ b/src/lib-lda/lmtp-client.h @@ -10,6 +10,12 @@ enum lmtp_client_protocol { LMTP_CLIENT_PROTOCOL_SMTP }; +struct lmtp_client_settings { + const char *my_hostname; + const char *mail_from; + const char *dns_client_socket_path; +}; + /* reply contains the reply coming from remote server, or NULL if it's a connection error. */ typedef void lmtp_callback_t(bool success, const char *reply, void *context); @@ -18,7 +24,7 @@ typedef void lmtp_callback_t(bool success, const char *reply, void *context); typedef void lmtp_finish_callback_t(void *context); struct lmtp_client * -lmtp_client_init(const char *mail_from, const char *my_hostname, +lmtp_client_init(const struct lmtp_client_settings *set, lmtp_finish_callback_t *finish_callback, void *context); void lmtp_client_deinit(struct lmtp_client **client); diff --git a/src/lmtp/commands.c b/src/lmtp/commands.c index bc3c66af72..e775e2466d 100644 --- a/src/lmtp/commands.c +++ b/src/lmtp/commands.c @@ -251,6 +251,7 @@ static bool client_proxy_rcpt(struct client *client, const char *address, if (client->proxy == NULL) { client->proxy = lmtp_proxy_init(client->set->hostname, + dns_client_socket_path, client->output); if (client->mail_body_8bitmime) args = " BODY=8BITMIME"; diff --git a/src/lmtp/lmtp-proxy.c b/src/lmtp/lmtp-proxy.c index 0eefff1df6..9ddab8c081 100644 --- a/src/lmtp/lmtp-proxy.c +++ b/src/lmtp/lmtp-proxy.c @@ -35,6 +35,8 @@ struct lmtp_proxy_connection { struct lmtp_proxy { pool_t pool; const char *mail_from, *my_hostname; + const char *dns_client_socket_path; + ARRAY_DEFINE(connections, struct lmtp_proxy_connection *); ARRAY_DEFINE(rcpt_to, struct lmtp_proxy_recipient *); unsigned int next_data_reply_idx; @@ -59,7 +61,8 @@ static void lmtp_conn_finish(void *context); static void lmtp_proxy_data_input(struct lmtp_proxy *proxy); struct lmtp_proxy * -lmtp_proxy_init(const char *my_hostname, struct ostream *client_output) +lmtp_proxy_init(const char *my_hostname, const char *dns_client_socket_path, + struct ostream *client_output) { struct lmtp_proxy *proxy; pool_t pool; @@ -71,6 +74,7 @@ lmtp_proxy_init(const char *my_hostname, struct ostream *client_output) proxy->pool = pool; proxy->my_hostname = p_strdup(pool, my_hostname); proxy->client_output = client_output; + proxy->dns_client_socket_path = p_strdup(pool, dns_client_socket_path); i_array_init(&proxy->rcpt_to, 32); i_array_init(&proxy->connections, 32); return proxy; @@ -121,6 +125,7 @@ lmtp_proxy_get_connection(struct lmtp_proxy *proxy, const struct lmtp_proxy_settings *set) { struct lmtp_proxy_connection *const *conns, *conn; + struct lmtp_client_settings client_set; i_assert(set->timeout_msecs > 0); @@ -132,14 +137,19 @@ lmtp_proxy_get_connection(struct lmtp_proxy *proxy, return conn; } + memset(&client_set, 0, sizeof(client_set)); + client_set.mail_from = proxy->mail_from; + client_set.my_hostname = proxy->my_hostname; + client_set.dns_client_socket_path = proxy->dns_client_socket_path; + conn = p_new(proxy->pool, struct lmtp_proxy_connection, 1); conn->proxy = proxy; conn->set.host = p_strdup(proxy->pool, set->host); conn->set.port = set->port; conn->set.timeout_msecs = set->timeout_msecs; array_append(&proxy->connections, &conn, 1); - conn->client = lmtp_client_init(proxy->mail_from, proxy->my_hostname, - lmtp_conn_finish, conn); + + conn->client = lmtp_client_init(&client_set, lmtp_conn_finish, conn); if (lmtp_client_connect_tcp(conn->client, set->protocol, conn->set.host, conn->set.port) < 0) conn->failed = TRUE; diff --git a/src/lmtp/lmtp-proxy.h b/src/lmtp/lmtp-proxy.h index fdcbc02131..babc12c990 100644 --- a/src/lmtp/lmtp-proxy.h +++ b/src/lmtp/lmtp-proxy.h @@ -14,7 +14,8 @@ struct lmtp_proxy_settings { typedef void lmtp_proxy_finish_callback_t(bool timeout, void *context); struct lmtp_proxy * -lmtp_proxy_init(const char *my_hostname, struct ostream *client_output); +lmtp_proxy_init(const char *my_hostname, const char *dns_client_socket_path, + struct ostream *client_output); void lmtp_proxy_deinit(struct lmtp_proxy **proxy); /* Set the "MAIL FROM:" line, including <> and options */ diff --git a/src/lmtp/main.c b/src/lmtp/main.c index 3bc4af9df2..3a502b1c9c 100644 --- a/src/lmtp/main.c +++ b/src/lmtp/main.c @@ -4,6 +4,7 @@ #include "array.h" #include "ioloop.h" #include "hostpid.h" +#include "abspath.h" #include "restrict-access.h" #include "fd-close-on-exec.h" #include "master-service.h" @@ -18,11 +19,13 @@ #include #include +#define DNS_CLIENT_SOCKET_PATH "dns-client" #define LMTP_MASTER_FIRST_LISTEN_FD 3 #define IS_STANDALONE() \ (getenv(MASTER_UID_ENV) == NULL) +const char *dns_client_socket_path; struct mail_storage_service_ctx *storage_service; static void client_connected(const struct master_service_connection *conn) @@ -38,6 +41,7 @@ static void main_init(void) memset(&conn, 0, sizeof(conn)); (void)client_create(STDIN_FILENO, STDOUT_FILENO, &conn); } + dns_client_socket_path = t_abspath(DNS_CLIENT_SOCKET_PATH); } static void main_deinit(void) diff --git a/src/lmtp/main.h b/src/lmtp/main.h index 542307ca2c..9aae739ce9 100644 --- a/src/lmtp/main.h +++ b/src/lmtp/main.h @@ -1,6 +1,7 @@ #ifndef MAIN_H #define MAIN_H +extern const char *dns_client_socket_path; extern struct mail_storage_service_ctx *storage_service; void listener_client_destroyed(void);