Gitweb:
http://git.exim.org/exim.git/commitdiff/a3bddaa8058346a11835f0d9947f3f60bb029fef
Commit: a3bddaa8058346a11835f0d9947f3f60bb029fef
Parent: aa26e1378803587c24924ad0055318959d597802
Author: Todd Lyons <tlyons@???>
AuthorDate: Mon Dec 30 15:02:21 2013 -0800
Committer: Todd Lyons <tlyons@???>
CommitDate: Mon Dec 30 15:56:37 2013 -0800
Proxy negotiation saves socket timeout values.
Rename proxy expansions conforming to Exim standards.
Update documentation to reflect rename.
Seperate restore socket function
---
doc/doc-txt/experimental-spec.txt | 16 +++++++-------
src/src/expand.c | 4 +-
src/src/globals.c | 4 +-
src/src/globals.h | 4 +-
src/src/receive.c | 2 +-
src/src/smtp_in.c | 40 +++++++++++++++++++++++++++++++++---
6 files changed, 51 insertions(+), 19 deletions(-)
diff --git a/doc/doc-txt/experimental-spec.txt b/doc/doc-txt/experimental-spec.txt
index 92790ae..b80e02b 100644
--- a/doc/doc-txt/experimental-spec.txt
+++ b/doc/doc-txt/experimental-spec.txt
@@ -1066,28 +1066,28 @@ Proxy Protocol server at 192.168.1.2 will look like this:
3. In the ACL's the following expansion variables are available.
-proxy_host The src IP of the proxy server making the connection
-proxy_port The src port the proxy server is using
-proxy_session Boolean, yes/no, the connected host is required to use
- Proxy Protocol.
+proxy_host_address The src IP of the proxy server making the connection
+proxy_host_port The src port the proxy server is using
+proxy_session Boolean, yes/no, the connected host is required to use
+ Proxy Protocol.
There is no expansion for a failed proxy session, however you can detect
it by checking if $proxy_session is true but $proxy_host is empty. As
an example, in my connect ACL, I have:
warn condition = ${if and{ {bool{$proxy_session}} \
- {eq{$proxy_host}{}} } }
+ {eq{$proxy_host_address}{}} } }
log_message = Failed required proxy protocol negotiation \
from $sender_host_name [$sender_host_address]
warn condition = ${if and{ {bool{$proxy_session}} \
- {!eq{$proxy_host}{}} } }
+ {!eq{$proxy_host_address}{}} } }
# But don't log health probes from the proxy itself
- condition = ${if eq{$proxy_host}{$sender_host_address} \
+ condition = ${if eq{$proxy_host_address}{$sender_host_address} \
{false}{true}}
log_message = Successfully proxied from $sender_host_name \
[$sender_host_address] through proxy protocol \
- host $proxy_host
+ host $proxy_host_address
4. Runtime issues to be aware of:
- Since the real connections are all coming from your proxy, and the
diff --git a/src/src/expand.c b/src/src/expand.c
index 325b051..de52e60 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -559,8 +559,8 @@ static var_entry var_table[] = {
{ "pid", vtype_pid, NULL },
{ "primary_hostname", vtype_stringptr, &primary_hostname },
#ifdef EXPERIMENTAL_PROXY
- { "proxy_host", vtype_stringptr, &proxy_host },
- { "proxy_port", vtype_int, &proxy_port },
+ { "proxy_host_address", vtype_stringptr, &proxy_host_address },
+ { "proxy_host_port", vtype_int, &proxy_host_port },
{ "proxy_session", vtype_bool, &proxy_session },
#endif
{ "prvscheck_address", vtype_stringptr, &prvscheck_address },
diff --git a/src/src/globals.c b/src/src/globals.c
index ec6700d..1572461 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -919,8 +919,8 @@ uschar *process_log_path = NULL;
BOOL prod_requires_admin = TRUE;
#ifdef EXPERIMENTAL_PROXY
-uschar *proxy_host = US"";
-int proxy_port = 0;
+uschar *proxy_host_address = US"";
+int proxy_host_port = 0;
uschar *proxy_required_hosts = US"";
BOOL proxy_session = FALSE;
BOOL proxy_session_failed = FALSE;
diff --git a/src/src/globals.h b/src/src/globals.h
index 5661489..bf54fb4 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -594,8 +594,8 @@ extern uschar *process_log_path; /* Alternate path */
extern BOOL prod_requires_admin; /* TRUE if prodding requires admin */
#ifdef EXPERIMENTAL_PROXY
-extern uschar *proxy_host; /* IP of proxy server */
-extern int proxy_port; /* Port of proxy server */
+extern uschar *proxy_host_address; /* IP of proxy server */
+extern int proxy_host_port; /* Port of proxy server */
extern uschar *proxy_required_hosts; /* Hostlist which (require) use proxy protocol */
extern BOOL proxy_session; /* TRUE if receiving mail from valid proxy */
extern BOOL proxy_session_failed; /* TRUE if required proxy negotiation failed */
diff --git a/src/src/receive.c b/src/src/receive.c
index 02db23f..0295b7e 100644
--- a/src/src/receive.c
+++ b/src/src/receive.c
@@ -3759,7 +3759,7 @@ if (prdr_requested)
if (proxy_session &&
(log_extra_selector & LX_proxy) != 0)
{
- s = string_append(s, &size, &sptr, 2, US" PRX=", proxy_host);
+ s = string_append(s, &size, &sptr, 2, US" PRX=", proxy_host_address);
}
#endif
diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c
index 144ad28..95c615e 100644
--- a/src/src/smtp_in.c
+++ b/src/src/smtp_in.c
@@ -555,6 +555,25 @@ exim_exit(EXIT_FAILURE);
#ifdef EXPERIMENTAL_PROXY
/*************************************************
+* Restore socket timeout to previous value *
+*************************************************/
+/* If the previous value was successfully retrieved, restore
+it before returning control to the non-proxy routines
+
+Arguments: fd - File descriptor for input
+ get_ok - Successfully retrieved previous values
+ tvtmp - Time struct with previous values
+ vslen - Length of time struct
+Returns: none
+*/
+static void
+restore_socket_timeout(int fd, int get_ok, struct timeval tvtmp, socklen_t vslen)
+{
+if (get_ok == 0)
+ setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tvtmp, vslen);
+}
+
+/*************************************************
* Check if host is required proxy host *
*************************************************/
/* The function determines if inbound host will be a regular smtp host
@@ -650,15 +669,25 @@ uschar *tmpip;
const char v2sig[13] = "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x02";
uschar *iptype; /* To display debug info */
struct timeval tv;
+int get_ok = 0;
+socklen_t vslen = 0;
+struct timeval tvtmp;
+
+vslen = sizeof(struct timeval);
fd = fileno(smtp_in);
+/* Save current socket timeout values */
+get_ok = getsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tvtmp,
+ &vslen);
+
/* Proxy Protocol host must send header within a short time
(default 3 seconds) or it's considered invalid */
tv.tv_sec = PROXY_NEGOTIATION_TIMEOUT_SEC;
tv.tv_usec = PROXY_NEGOTIATION_TIMEOUT_USEC;
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,
sizeof(struct timeval));
+
do
{
ret = recv(fd, &hdr, sizeof(hdr), MSG_PEEK);
@@ -666,7 +695,10 @@ do
while (ret == -1 && errno == EINTR);
if (ret == -1)
+ {
+ restore_socket_timeout(fd, get_ok, tvtmp, vslen);
return (errno == EAGAIN) ? 0 : ERRNO_PROXYFAIL;
+ }
if (ret >= 16 &&
memcmp(&hdr.v2, v2sig, 13) == 0)
@@ -768,7 +800,7 @@ else if (ret >= 8 &&
debug_printf("Proxied src arg is not an %s address\n", iptype);
goto proxyfail;
}
- proxy_host = sender_host_address;
+ proxy_host_address = sender_host_address;
sender_host_address = p;
p = sp + 1;
if ((sp = Ustrchr(p, ' ')) == NULL)
@@ -799,7 +831,7 @@ else if (ret >= 8 &&
debug_printf("Proxied src port '%s' not an integer\n", p);
goto proxyfail;
}
- proxy_port = sender_host_port;
+ proxy_host_port = sender_host_port;
sender_host_port = tmp_port;
p = sp + 1;
if ((sp = Ustrchr(p, '\0')) == NULL)
@@ -826,11 +858,13 @@ else
}
proxyfail:
+restore_socket_timeout(fd, get_ok, tvtmp, vslen);
/* Don't flush any potential buffer contents. Any input should cause a
synchronization failure or we just don't want to speak SMTP to them */
return FALSE;
done:
+restore_socket_timeout(fd, get_ok, tvtmp, vslen);
flush_input();
DEBUG(D_receive)
debug_printf("Valid %s sender from Proxy Protocol header\n",
@@ -839,8 +873,6 @@ return proxy_session;
}
#endif
-
-
/*************************************************
* Read one command line *
*************************************************/