]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lmtp proxy: Added support for DNS lookups.
authorTimo Sirainen <tss@iki.fi>
Tue, 2 Mar 2010 09:40:52 +0000 (11:40 +0200)
committerTimo Sirainen <tss@iki.fi>
Tue, 2 Mar 2010 09:40:52 +0000 (11:40 +0200)
--HG--
branch : HEAD

src/lib-lda/Makefile.am
src/lib-lda/lmtp-client.c
src/lib-lda/lmtp-client.h
src/lmtp/commands.c
src/lmtp/lmtp-proxy.c
src/lmtp/lmtp-proxy.h
src/lmtp/main.c
src/lmtp/main.h

index c9763f9fd4fabee00332a0b5d0604004a22e9867..9100d596bbdc7450e629ad5fb2c9ecd23edaf17d 100644 (file)
@@ -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
index 07eead61b265d17c82cd35fab9a6c2af7c24a67d..671519aedc0274ec19c8b81e8bd8fb3a71537da7 100644 (file)
@@ -6,11 +6,13 @@
 #include "network.h"
 #include "istream.h"
 #include "ostream.h"
+#include "dns-lookup.h"
 #include "lmtp-client.h"
 
 #include <ctype.h>
 
 #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;
 }
 
index 77d3e2a5eddbd14c88bdd10428494e97ea5b0b32..df4b202de31930726c06a1b332e3cd67e9525b1c 100644 (file)
@@ -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);
 
index bc3c66af724364ed0aee743cba44a881fe5c6edc..e775e2466dc63456196e08658f241c4c8bc91984 100644 (file)
@@ -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";
index 0eefff1df6df49706f8e9bc3308c7dd4276b25fa..9ddab8c0818a5233a4ed26d2bc80f9585b7395ea 100644 (file)
@@ -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;
index fdcbc02131181049ad6e50f45fd890845c2211c4..babc12c9908716a592abfecfd6daeb10b2bc7d88 100644 (file)
@@ -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 */
index 3bc4af9df22cbec2ff6d5c085dd07895f725c4a3..3a502b1c9cb1a9c456e5f2ad49d8876ff853ee84 100644 (file)
@@ -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"
 #include <stdlib.h>
 #include <unistd.h>
 
+#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)
index 542307ca2c60d11a9a1222c839e364985cffa3ea..9aae739ce9940f3c0ed4494741436b361d2e0b67 100644 (file)
@@ -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);