dovecot-2.2: smtp/lmtp client: Send XCLIENT ADDR+PORT when possi...
dovecot at dovecot.org
dovecot at dovecot.org
Thu Feb 23 11:59:23 EET 2012
details: http://hg.dovecot.org/dovecot-2.2/rev/3144001fae84
changeset: 14150:3144001fae84
user: Timo Sirainen <tss at iki.fi>
date: Thu Feb 23 11:58:35 2012 +0200
description:
smtp/lmtp client: Send XCLIENT ADDR+PORT when possible.
diffstat:
src/lib-lda/lmtp-client.c | 91 +++++++++++++++++++++++++++++++++++++++++++---
src/lib-lda/lmtp-client.h | 7 +++
2 files changed, 91 insertions(+), 7 deletions(-)
diffs (234 lines):
diff -r 1af2a0497f3f -r 3144001fae84 src/lib-lda/lmtp-client.c
--- a/src/lib-lda/lmtp-client.c Thu Feb 23 11:12:04 2012 +0200
+++ b/src/lib-lda/lmtp-client.c Thu Feb 23 11:58:35 2012 +0200
@@ -6,6 +6,7 @@
#include "network.h"
#include "istream.h"
#include "ostream.h"
+#include "str.h"
#include "dns-lookup.h"
#include "lmtp-client.h"
@@ -20,7 +21,8 @@
LMTP_INPUT_STATE_MAIL_FROM,
LMTP_INPUT_STATE_RCPT_TO,
LMTP_INPUT_STATE_DATA_CONTINUE,
- LMTP_INPUT_STATE_DATA
+ LMTP_INPUT_STATE_DATA,
+ LMTP_INPUT_STATE_XCLIENT
};
struct lmtp_rcpt {
@@ -44,6 +46,8 @@
enum lmtp_client_protocol protocol;
enum lmtp_input_state input_state;
const char *global_fail_string;
+ string_t *input_multiline;
+ const char **xclient_args;
struct istream *input;
struct ostream *output;
@@ -64,6 +68,7 @@
struct istream *data_input;
unsigned char output_last;
+ unsigned int xclient_sent:1;
unsigned int rcpt_to_successes:1;
unsigned int output_finished:1;
unsigned int finish_called:1;
@@ -89,9 +94,12 @@
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->set.source_ip = set->source_ip;
+ client->set.source_port = set->source_port;
client->finish_callback = finish_callback;
client->finish_context = context;
client->fd = -1;
+ client->input_multiline = str_new(default_pool, 128);
p_array_init(&client->recipients, pool, 16);
return client;
}
@@ -138,6 +146,7 @@
i_stream_unref(&client->input);
if (client->output != NULL)
o_stream_unref(&client->output);
+ str_free(&client->input_multiline);
pool_unref(&client->pool);
}
@@ -177,6 +186,8 @@
return t_strdup_printf("DATA (%"PRIuUOFF_T"/?)",
client->data_input->v_offset);
}
+ case LMTP_INPUT_STATE_XCLIENT:
+ return "XCLIENT";
}
return "??";
}
@@ -356,7 +367,8 @@
}
}
-static int lmtp_input_get_reply_code(const char *line, int *reply_code_r)
+static int lmtp_input_get_reply_code(const char *line, int *reply_code_r,
+ string_t *multiline)
{
if (!i_isdigit(line[0]) || !i_isdigit(line[1]) || !i_isdigit(line[2]))
return -1;
@@ -369,7 +381,9 @@
/* final reply */
return 1;
} else if (line[3] == '-') {
- /* multiline reply. just ignore it. */
+ /* multiline reply. */
+ str_append(multiline, line);
+ str_append_c(multiline, '\n');
return 0;
} else {
/* invalid input */
@@ -377,11 +391,58 @@
}
}
+static void
+lmtp_client_parse_capabilities(struct lmtp_client *client, const char *lines)
+{
+ const char *const *linep;
+
+ for (linep = t_strsplit(lines, "\n"); *linep != NULL; linep++) {
+ const char *line = *linep;
+
+ line += 4; /* already checked this is valid */
+ if (strncasecmp(line, "XCLIENT ", 8) == 0) {
+ client->xclient_args =
+ (void *)p_strsplit(client->pool, line + 8, " ");
+ }
+ }
+}
+
+static bool lmtp_client_send_xclient(struct lmtp_client *client)
+{
+ string_t *str;
+ unsigned int empty_len;
+
+ if (client->xclient_args == NULL) {
+ /* not supported */
+ return FALSE;
+ }
+ if (client->xclient_sent)
+ return FALSE;
+
+ str = t_str_new(64);
+ str_append(str, "XCLIENT");
+ empty_len = str_len(str);
+ if (client->set.source_ip.family != 0 &&
+ str_array_icase_find(client->xclient_args, "ADDR"))
+ str_printfa(str, " ADDR=%s", net_ip2addr(&client->set.source_ip));
+ if (client->set.source_port != 0 &&
+ str_array_icase_find(client->xclient_args, "PORT"))
+ str_printfa(str, " PORT=%u", client->set.source_port);
+
+ if (str_len(str) == empty_len)
+ return FALSE;
+
+ str_append(str, "\r\n");
+ o_stream_send(client->output, str_data(str), str_len(str));
+ return TRUE;
+}
+
static int lmtp_client_input_line(struct lmtp_client *client, const char *line)
{
int ret, reply_code = 0;
- if ((ret = lmtp_input_get_reply_code(line, &reply_code)) <= 0) {
+ if ((ret = lmtp_input_get_reply_code(line, &reply_code,
+ client->input_multiline)) <= 0) {
if (ret == 0)
return 0;
lmtp_client_fail(client, line);
@@ -390,12 +451,13 @@
switch (client->input_state) {
case LMTP_INPUT_STATE_GREET:
+ case LMTP_INPUT_STATE_XCLIENT:
if (reply_code != 220) {
lmtp_client_fail(client, line);
return -1;
}
lmtp_client_send_handshake(client);
- client->input_state++;
+ client->input_state = LMTP_INPUT_STATE_LHLO;
break;
case LMTP_INPUT_STATE_LHLO:
case LMTP_INPUT_STATE_MAIL_FROM:
@@ -403,6 +465,15 @@
lmtp_client_fail(client, line);
return -1;
}
+ str_append(client->input_multiline, line);
+ lmtp_client_parse_capabilities(client,
+ str_c(client->input_multiline));
+ if (client->input_state == LMTP_INPUT_STATE_LHLO &&
+ lmtp_client_send_xclient(client)) {
+ client->input_state = LMTP_INPUT_STATE_XCLIENT;
+ client->xclient_sent = TRUE;
+ break;
+ }
if (client->input_state == LMTP_INPUT_STATE_LHLO) {
o_stream_send_str(client->output,
t_strdup_printf("MAIL FROM:%s\r\n",
@@ -435,21 +506,27 @@
return -1;
break;
}
- return 0;
+ return 1;
}
static void lmtp_client_input(struct lmtp_client *client)
{
const char *line;
+ int ret;
lmtp_client_ref(client);
o_stream_cork(client->output);
while ((line = i_stream_read_next_line(client->input)) != NULL) {
- if (lmtp_client_input_line(client, line) < 0) {
+ T_BEGIN {
+ ret = lmtp_client_input_line(client, line);
+ } T_END;
+ if (ret < 0) {
o_stream_uncork(client->output);
lmtp_client_unref(&client);
return;
}
+ if (ret > 0)
+ str_truncate(client->input_multiline, 0);
}
if (client->input->stream_errno != 0) {
diff -r 1af2a0497f3f -r 3144001fae84 src/lib-lda/lmtp-client.h
--- a/src/lib-lda/lmtp-client.h Thu Feb 23 11:12:04 2012 +0200
+++ b/src/lib-lda/lmtp-client.h Thu Feb 23 11:58:35 2012 +0200
@@ -1,6 +1,8 @@
#ifndef LMTP_CLIENT_H
#define LMTP_CLIENT_H
+#include "network.h"
+
#define ERRSTR_TEMP_REMOTE_FAILURE "451 4.4.0 Remote server not answering"
/* LMTP/SMTP client code. */
@@ -14,6 +16,11 @@
const char *my_hostname;
const char *mail_from;
const char *dns_client_socket_path;
+
+ /* if remote server supports XCLIENT capability,
+ send the these as ADDR/PORT */
+ struct ip_addr source_ip;
+ unsigned int source_port;
};
/* reply contains the reply coming from remote server, or NULL
More information about the dovecot-cvs
mailing list