mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-22 18:07:41 +00:00
postfix-2.10-20120625
This commit is contained in:
parent
6fe49cc965
commit
6fa85acc3b
3
postfix/.indent.pro
vendored
3
postfix/.indent.pro
vendored
@ -213,6 +213,8 @@
|
|||||||
-TPSC_DNSBL_HEAD
|
-TPSC_DNSBL_HEAD
|
||||||
-TPSC_DNSBL_SCORE
|
-TPSC_DNSBL_SCORE
|
||||||
-TPSC_DNSBL_SITE
|
-TPSC_DNSBL_SITE
|
||||||
|
-TPSC_ENDPT_LOOKUP_INFO
|
||||||
|
-TPSC_HAPROXY_STATE
|
||||||
-TPSC_SMTPD_COMMAND
|
-TPSC_SMTPD_COMMAND
|
||||||
-TPSC_STARTTLS
|
-TPSC_STARTTLS
|
||||||
-TPSC_STATE
|
-TPSC_STATE
|
||||||
@ -258,6 +260,7 @@
|
|||||||
-TSMFICTX
|
-TSMFICTX
|
||||||
-TSMTPD_CMD
|
-TSMTPD_CMD
|
||||||
-TSMTPD_DEFER
|
-TSMTPD_DEFER
|
||||||
|
-TSMTPD_ENDPT_LOOKUP_INFO
|
||||||
-TSMTPD_PROXY
|
-TSMTPD_PROXY
|
||||||
-TSMTPD_RBL_EXPAND_CONTEXT
|
-TSMTPD_RBL_EXPAND_CONTEXT
|
||||||
-TSMTPD_RBL_STATE
|
-TSMTPD_RBL_STATE
|
||||||
|
@ -17811,3 +17811,51 @@ Apologies for any names omitted.
|
|||||||
Bugfix (introduced: 20031216-21): with soft_bounce=yes, the
|
Bugfix (introduced: 20031216-21): with soft_bounce=yes, the
|
||||||
SMTP client did not move on to the next MX host or fallback
|
SMTP client did not move on to the next MX host or fallback
|
||||||
relay after a 5xx reply. File: smtp/smtp_trouble.c.
|
relay after a 5xx reply. File: smtp/smtp_trouble.c.
|
||||||
|
|
||||||
|
20120527-8
|
||||||
|
|
||||||
|
Infrastructure: limited support to shrink VSTREAM buffers.
|
||||||
|
The change takes place when reading from (a stream for the
|
||||||
|
first time | an empty buffer) or when writing to (a stream
|
||||||
|
for the first time | a full buffer). TODO: the change should
|
||||||
|
also happen after purging or flushing a buffer. File:
|
||||||
|
util/vstream.c.
|
||||||
|
|
||||||
|
20120531-617
|
||||||
|
|
||||||
|
Feature: haproxy support in postscreen(8) and smtpd(8). To
|
||||||
|
enable, specify "smtpd_upstream_proxy_protocol = haproxy"
|
||||||
|
or "postscreen_upstream_proxy_protocol = haproxy". Files:
|
||||||
|
mantools/postlink, proto/postconf.proto, global/Makefile.in,
|
||||||
|
global/haproxy_srvr.c, global/haproxy_srvr.h, global/mail_params.h,
|
||||||
|
global/mail_proto.h, master/single_server.c, master/multi_server.c,
|
||||||
|
master/event_server.c, postscreen/Makefile.in,
|
||||||
|
postscreen/postscreen.c, postscreen/postscreen.h,
|
||||||
|
postscreen/postscreen_endpt.c, postscreen/postscreen_haproxy.c,
|
||||||
|
postscreen/postscreen_haproxy.h, postscreen/postscreen_send.c,
|
||||||
|
postscreen/postscreen_state.c, smtpd/Makefile.in, smtpd/smtpd.h,
|
||||||
|
smtpd/smtpd_peer.c, smtpd/smtpd_sasl_glue.c, smtpd/smtpd_haproxy.c,
|
||||||
|
util/Makefile.in, util/listen.h, util/recv_pass_attr.c,
|
||||||
|
util/stream_listen.c, util/sys_defs.h, util/unix_pass_listen.c.
|
||||||
|
|
||||||
|
|
||||||
|
20120618
|
||||||
|
|
||||||
|
Cleanup: made the postscreen-to-smtpd haproxy attribute
|
||||||
|
transmission more robust for Solaris. Files: util/sys_defs.h,
|
||||||
|
util/connect.h, util/steam_listen.c, postscreen/postscreen_send.c.
|
||||||
|
|
||||||
|
Cleanup: simplified the "stream used" workaround. Files:
|
||||||
|
util/vstream.h, master/event_server.c, master/multi_server.c.
|
||||||
|
|
||||||
|
20120621
|
||||||
|
|
||||||
|
Cleanup: simplified workarounds for Solaris streams versus
|
||||||
|
UNIX-domain sockets. Files: util/pass_accept.c (new),
|
||||||
|
util/pass_trigger.c (new), util/stream_pass_connect.c
|
||||||
|
(deleted), util/unix_pass_listen.c (deleted),
|
||||||
|
util/unix_pass_trigger.c (deleted), updated header files,
|
||||||
|
and replaced PASS_XXX macros by pass_xxx function calls.
|
||||||
|
|
||||||
|
Cleanup: don't clobber errno when logging a problem.
|
||||||
|
File util/msg_output.c.
|
||||||
|
@ -14,6 +14,30 @@ specifies the release date of a stable release or snapshot release.
|
|||||||
If you upgrade from Postfix 2.8 or earlier, read RELEASE_NOTES-2.9
|
If you upgrade from Postfix 2.8 or earlier, read RELEASE_NOTES-2.9
|
||||||
before proceeding.
|
before proceeding.
|
||||||
|
|
||||||
|
Incompatible changes with snapshot 20120625
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
The postscreen(8)-to-smtpd(8) protocol has changed. To avoid "cannot
|
||||||
|
receive connection attributes" warnings and dropped connections,
|
||||||
|
execute the command "postfix reload". No mail will be lost as long
|
||||||
|
as the remote SMTP client tries again later.
|
||||||
|
|
||||||
|
Major changes with snapshot 20120625
|
||||||
|
====================================
|
||||||
|
|
||||||
|
Support for upstream proxy agent in the postscreen(8) and smtpd(8)
|
||||||
|
daemons. To enable the haproxy protocol, specify one of the
|
||||||
|
following:
|
||||||
|
|
||||||
|
postscreen_upstream_proxy_protocol = haproxy
|
||||||
|
smtpd_upstream_proxy_protocol = haproxy
|
||||||
|
|
||||||
|
Note 1: smtpd_upstream_proxy_protocol can't be used behind postscreen.
|
||||||
|
|
||||||
|
Note 2: To use the nginx proxy with smtpd(8), enable the XCLIENT
|
||||||
|
protocol with smtpd_authorized_xclient_hosts. This supports SASL
|
||||||
|
authentication in the proxy agent (Postfix 2.9 and later).
|
||||||
|
|
||||||
Major changes with snapshot 20120422
|
Major changes with snapshot 20120422
|
||||||
====================================
|
====================================
|
||||||
|
|
||||||
|
@ -7639,6 +7639,31 @@ for details. </p>
|
|||||||
<p> This feature is available in Postfix 2.8 and later. </p>
|
<p> This feature is available in Postfix 2.8 and later. </p>
|
||||||
|
|
||||||
|
|
||||||
|
</DD>
|
||||||
|
|
||||||
|
<DT><b><a name="postscreen_upstream_proxy_protocol">postscreen_upstream_proxy_protocol</a>
|
||||||
|
(default: empty)</b></DT><DD>
|
||||||
|
|
||||||
|
<p> The name of the proxy protocol used by an optional before-postscreen
|
||||||
|
proxy agent. When a proxy agent is used, this protocol conveys local
|
||||||
|
and remote address and port information. Specify
|
||||||
|
"<a href="postconf.5.html#postscreen_upstream_proxy_protocol">postscreen_upstream_proxy_protocol</a> = haproxy" to enable the haproxy
|
||||||
|
protocol. <p>
|
||||||
|
|
||||||
|
<p> This feature is available in Postfix 2.10 and later. </p>
|
||||||
|
|
||||||
|
|
||||||
|
</DD>
|
||||||
|
|
||||||
|
<DT><b><a name="postscreen_upstream_proxy_timeout">postscreen_upstream_proxy_timeout</a>
|
||||||
|
(default: 5s)</b></DT><DD>
|
||||||
|
|
||||||
|
<p> The time limit for the proxy protocol specified with the
|
||||||
|
<a href="postconf.5.html#postscreen_upstream_proxy_protocol">postscreen_upstream_proxy_protocol</a> parameter. </p>
|
||||||
|
|
||||||
|
<p> This feature is available in Postfix 2.10 and later. </p>
|
||||||
|
|
||||||
|
|
||||||
</DD>
|
</DD>
|
||||||
|
|
||||||
<DT><b><a name="postscreen_use_tls">postscreen_use_tls</a>
|
<DT><b><a name="postscreen_use_tls">postscreen_use_tls</a>
|
||||||
@ -15142,6 +15167,35 @@ purpose. </p>
|
|||||||
<p> This feature is available in Postfix 2.2 and later. </p>
|
<p> This feature is available in Postfix 2.2 and later. </p>
|
||||||
|
|
||||||
|
|
||||||
|
</DD>
|
||||||
|
|
||||||
|
<DT><b><a name="smtpd_upstream_proxy_protocol">smtpd_upstream_proxy_protocol</a>
|
||||||
|
(default: empty)</b></DT><DD>
|
||||||
|
|
||||||
|
<p> The name of the proxy protocol used by an optional before-smtpd
|
||||||
|
proxy agent. When a proxy agent is used, this protocol conveys local
|
||||||
|
and remote address and port information. Specify
|
||||||
|
"<a href="postconf.5.html#smtpd_upstream_proxy_protocol">smtpd_upstream_proxy_protocol</a> = haproxy" to enable the haproxy
|
||||||
|
protocol. </p>
|
||||||
|
|
||||||
|
<p> NOTE: To use the nginx proxy with <a href="smtpd.8.html">smtpd(8)</a>, enable the XCLIENT
|
||||||
|
protocol with <a href="postconf.5.html#smtpd_authorized_xclient_hosts">smtpd_authorized_xclient_hosts</a>. This supports SASL
|
||||||
|
authentication in the proxy agent (Postfix 2.9 and later). <p>
|
||||||
|
|
||||||
|
<p> This feature is available in Postfix 2.10 and later. </p>
|
||||||
|
|
||||||
|
|
||||||
|
</DD>
|
||||||
|
|
||||||
|
<DT><b><a name="smtpd_upstream_proxy_timeout">smtpd_upstream_proxy_timeout</a>
|
||||||
|
(default: 5s)</b></DT><DD>
|
||||||
|
|
||||||
|
<p> The time limit for the proxy protocol specified with the
|
||||||
|
<a href="postconf.5.html#smtpd_upstream_proxy_protocol">smtpd_upstream_proxy_protocol</a> parameter. </p>
|
||||||
|
|
||||||
|
<p> This feature is available in Postfix 2.10 and later. </p>
|
||||||
|
|
||||||
|
|
||||||
</DD>
|
</DD>
|
||||||
|
|
||||||
<DT><b><a name="smtpd_use_tls">smtpd_use_tls</a>
|
<DT><b><a name="smtpd_use_tls">smtpd_use_tls</a>
|
||||||
|
@ -146,6 +146,18 @@ POSTSCREEN(8) POSTSCREEN(8)
|
|||||||
Safety net to keep mail queued that would otherwise
|
Safety net to keep mail queued that would otherwise
|
||||||
be returned to the sender.
|
be returned to the sender.
|
||||||
|
|
||||||
|
<b>BEFORE-POSTSCREEN PROXY AGENT</b>
|
||||||
|
Available in Postfix version 2.10 and later:
|
||||||
|
|
||||||
|
<b><a href="postconf.5.html#postscreen_upstream_proxy_protocol">postscreen_upstream_proxy_protocol</a> (empty)</b>
|
||||||
|
The name of the proxy protocol used by an optional
|
||||||
|
before-postscreen proxy agent.
|
||||||
|
|
||||||
|
<b><a href="postconf.5.html#postscreen_upstream_proxy_timeout">postscreen_upstream_proxy_timeout</a> (5s)</b>
|
||||||
|
The time limit for the proxy protocol specified
|
||||||
|
with the <a href="postconf.5.html#postscreen_upstream_proxy_protocol">postscreen_upstream_proxy_protocol</a> parame-
|
||||||
|
ter.
|
||||||
|
|
||||||
<b>PERMANENT WHITE/BLACKLIST TEST</b>
|
<b>PERMANENT WHITE/BLACKLIST TEST</b>
|
||||||
This test is executed immediately after a remote SMTP
|
This test is executed immediately after a remote SMTP
|
||||||
client connects. If a client is permanently whitelisted,
|
client connects. If a client is permanently whitelisted,
|
||||||
|
@ -183,6 +183,17 @@ SMTPD(8) SMTPD(8)
|
|||||||
addresses with the domain specified in the
|
addresses with the domain specified in the
|
||||||
<a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> parameter.
|
<a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> parameter.
|
||||||
|
|
||||||
|
<b>BEFORE-SMTPD PROXY AGENT</b>
|
||||||
|
Available in Postfix version 2.10 and later:
|
||||||
|
|
||||||
|
<b><a href="postconf.5.html#smtpd_upstream_proxy_protocol">smtpd_upstream_proxy_protocol</a> (empty)</b>
|
||||||
|
The name of the proxy protocol used by an optional
|
||||||
|
before-smtpd proxy agent.
|
||||||
|
|
||||||
|
<b><a href="postconf.5.html#smtpd_upstream_proxy_timeout">smtpd_upstream_proxy_timeout</a> (5s)</b>
|
||||||
|
The time limit for the proxy protocol specified
|
||||||
|
with the <a href="postconf.5.html#smtpd_upstream_proxy_protocol">smtpd_upstream_proxy_protocol</a> parameter.
|
||||||
|
|
||||||
<b>AFTER QUEUE EXTERNAL CONTENT INSPECTION CONTROLS</b>
|
<b>AFTER QUEUE EXTERNAL CONTENT INSPECTION CONTROLS</b>
|
||||||
As of version 1.0, Postfix can be configured to send new
|
As of version 1.0, Postfix can be configured to send new
|
||||||
mail to an external content filter AFTER the mail is
|
mail to an external content filter AFTER the mail is
|
||||||
|
@ -666,7 +666,7 @@ CCARGS="$CCARGS -DSNAPSHOT"
|
|||||||
|
|
||||||
# Non-production: needs thorough testing, or major changes are still
|
# Non-production: needs thorough testing, or major changes are still
|
||||||
# needed before the code stabilizes.
|
# needed before the code stabilizes.
|
||||||
#CCARGS="$CCARGS -DNONPROD"
|
CCARGS="$CCARGS -DNONPROD"
|
||||||
|
|
||||||
sed 's/ / /g' <<EOF
|
sed 's/ / /g' <<EOF
|
||||||
SYSTYPE = $SYSTYPE
|
SYSTYPE = $SYSTYPE
|
||||||
|
@ -4426,6 +4426,19 @@ postscreen_use_tls and postscreen_enforce_tls. See smtpd_tls_security_level
|
|||||||
for details.
|
for details.
|
||||||
.PP
|
.PP
|
||||||
This feature is available in Postfix 2.8 and later.
|
This feature is available in Postfix 2.8 and later.
|
||||||
|
.SH postscreen_upstream_proxy_protocol (default: empty)
|
||||||
|
The name of the proxy protocol used by an optional before-postscreen
|
||||||
|
proxy agent. When a proxy agent is used, this protocol conveys local
|
||||||
|
and remote address and port information. Specify
|
||||||
|
"postscreen_upstream_proxy_protocol = haproxy" to enable the haproxy
|
||||||
|
protocol.
|
||||||
|
.PP
|
||||||
|
This feature is available in Postfix 2.10 and later.
|
||||||
|
.SH postscreen_upstream_proxy_timeout (default: 5s)
|
||||||
|
The time limit for the proxy protocol specified with the
|
||||||
|
postscreen_upstream_proxy_protocol parameter.
|
||||||
|
.PP
|
||||||
|
This feature is available in Postfix 2.10 and later.
|
||||||
.SH postscreen_use_tls (default: $smtpd_use_tls)
|
.SH postscreen_use_tls (default: $smtpd_use_tls)
|
||||||
Opportunistic TLS: announce STARTTLS support to remote SMTP clients,
|
Opportunistic TLS: announce STARTTLS support to remote SMTP clients,
|
||||||
but do not require that clients use TLS encryption.
|
but do not require that clients use TLS encryption.
|
||||||
@ -9806,6 +9819,23 @@ server's command line. Port 465 (smtps) was once chosen for this
|
|||||||
purpose.
|
purpose.
|
||||||
.PP
|
.PP
|
||||||
This feature is available in Postfix 2.2 and later.
|
This feature is available in Postfix 2.2 and later.
|
||||||
|
.SH smtpd_upstream_proxy_protocol (default: empty)
|
||||||
|
The name of the proxy protocol used by an optional before-smtpd
|
||||||
|
proxy agent. When a proxy agent is used, this protocol conveys local
|
||||||
|
and remote address and port information. Specify
|
||||||
|
"smtpd_upstream_proxy_protocol = haproxy" to enable the haproxy
|
||||||
|
protocol.
|
||||||
|
.PP
|
||||||
|
NOTE: To use the nginx proxy with \fBsmtpd\fR(8), enable the XCLIENT
|
||||||
|
protocol with smtpd_authorized_xclient_hosts. This supports SASL
|
||||||
|
authentication in the proxy agent (Postfix 2.9 and later).
|
||||||
|
.PP
|
||||||
|
This feature is available in Postfix 2.10 and later.
|
||||||
|
.SH smtpd_upstream_proxy_timeout (default: 5s)
|
||||||
|
The time limit for the proxy protocol specified with the
|
||||||
|
smtpd_upstream_proxy_protocol parameter.
|
||||||
|
.PP
|
||||||
|
This feature is available in Postfix 2.10 and later.
|
||||||
.SH smtpd_use_tls (default: no)
|
.SH smtpd_use_tls (default: no)
|
||||||
Opportunistic TLS: announce STARTTLS support to remote SMTP clients,
|
Opportunistic TLS: announce STARTTLS support to remote SMTP clients,
|
||||||
but do not require that clients use TLS encryption.
|
but do not require that clients use TLS encryption.
|
||||||
|
@ -152,6 +152,18 @@ response.
|
|||||||
.IP "\fBsoft_bounce (no)\fR"
|
.IP "\fBsoft_bounce (no)\fR"
|
||||||
Safety net to keep mail queued that would otherwise be returned to
|
Safety net to keep mail queued that would otherwise be returned to
|
||||||
the sender.
|
the sender.
|
||||||
|
.SH "BEFORE-POSTSCREEN PROXY AGENT"
|
||||||
|
.na
|
||||||
|
.nf
|
||||||
|
.ad
|
||||||
|
.fi
|
||||||
|
Available in Postfix version 2.10 and later:
|
||||||
|
.IP "\fBpostscreen_upstream_proxy_protocol (empty)\fR"
|
||||||
|
The name of the proxy protocol used by an optional before-postscreen
|
||||||
|
proxy agent.
|
||||||
|
.IP "\fBpostscreen_upstream_proxy_timeout (5s)\fR"
|
||||||
|
The time limit for the proxy protocol specified with the
|
||||||
|
postscreen_upstream_proxy_protocol parameter.
|
||||||
.SH "PERMANENT WHITE/BLACKLIST TEST"
|
.SH "PERMANENT WHITE/BLACKLIST TEST"
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
|
@ -172,6 +172,18 @@ $mydomain; either don't rewrite message headers from other clients
|
|||||||
at all, or rewrite message headers and update incomplete addresses
|
at all, or rewrite message headers and update incomplete addresses
|
||||||
with the domain specified in the remote_header_rewrite_domain
|
with the domain specified in the remote_header_rewrite_domain
|
||||||
parameter.
|
parameter.
|
||||||
|
.SH "BEFORE-SMTPD PROXY AGENT"
|
||||||
|
.na
|
||||||
|
.nf
|
||||||
|
.ad
|
||||||
|
.fi
|
||||||
|
Available in Postfix version 2.10 and later:
|
||||||
|
.IP "\fBsmtpd_upstream_proxy_protocol (empty)\fR"
|
||||||
|
The name of the proxy protocol used by an optional before-smtpd
|
||||||
|
proxy agent.
|
||||||
|
.IP "\fBsmtpd_upstream_proxy_timeout (5s)\fR"
|
||||||
|
The time limit for the proxy protocol specified with the
|
||||||
|
smtpd_upstream_proxy_protocol parameter.
|
||||||
.SH "AFTER QUEUE EXTERNAL CONTENT INSPECTION CONTROLS"
|
.SH "AFTER QUEUE EXTERNAL CONTENT INSPECTION CONTROLS"
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
|
@ -673,6 +673,8 @@ while (<>) {
|
|||||||
s;\bsmtpd_use_tls\b;<a href="postconf.5.html#smtpd_use_tls">$&</a>;g;
|
s;\bsmtpd_use_tls\b;<a href="postconf.5.html#smtpd_use_tls">$&</a>;g;
|
||||||
s;\bsmtpd_reject_footer\b;<a href="postconf.5.html#smtpd_reject_footer">$&</a>;g;
|
s;\bsmtpd_reject_footer\b;<a href="postconf.5.html#smtpd_reject_footer">$&</a>;g;
|
||||||
s;\bsmtpd_per_record_deadline\b;<a href="postconf.5.html#smtpd_per_record_deadline">$&</a>;g;
|
s;\bsmtpd_per_record_deadline\b;<a href="postconf.5.html#smtpd_per_record_deadline">$&</a>;g;
|
||||||
|
s;\bsmtpd_upstream_proxy_protocol\b;<a href="postconf.5.html#smtpd_upstream_proxy_protocol">$&</a>;g;
|
||||||
|
s;\bsmtpd_upstream_proxy_timeout\b;<a href="postconf.5.html#smtpd_upstream_proxy_timeout">$&</a>;g;
|
||||||
s;\btls_daemon_random_bytes\b;<a href="postconf.5.html#tls_daemon_random_bytes">$&</a>;g;
|
s;\btls_daemon_random_bytes\b;<a href="postconf.5.html#tls_daemon_random_bytes">$&</a>;g;
|
||||||
s;\btls_daemon_random_source\b;<a href="postconf.5.html#tls_daemon_random_source">$&</a>;g;
|
s;\btls_daemon_random_source\b;<a href="postconf.5.html#tls_daemon_random_source">$&</a>;g;
|
||||||
s;\btls_ran[-</Bb>]*\n* *[<Bb>]*dom_bytes\b;<a href="postconf.5.html#tls_random_bytes">$&</a>;g;
|
s;\btls_ran[-</Bb>]*\n* *[<Bb>]*dom_bytes\b;<a href="postconf.5.html#tls_random_bytes">$&</a>;g;
|
||||||
@ -969,6 +971,8 @@ while (<>) {
|
|||||||
s;\bpostscreen_reject_footer\b;<a href="postconf.5.html#postscreen_reject_footer">$&</a>;g;
|
s;\bpostscreen_reject_footer\b;<a href="postconf.5.html#postscreen_reject_footer">$&</a>;g;
|
||||||
s;\bpostscreen_command_filter\b;<a href="postconf.5.html#postscreen_command_filter">$&</a>;g;
|
s;\bpostscreen_command_filter\b;<a href="postconf.5.html#postscreen_command_filter">$&</a>;g;
|
||||||
s;\bpostscreen_whitelist_interfaces\b;<a href="postconf.5.html#postscreen_whitelist_interfaces">$&</a>;g;
|
s;\bpostscreen_whitelist_interfaces\b;<a href="postconf.5.html#postscreen_whitelist_interfaces">$&</a>;g;
|
||||||
|
s;\bpostscreen_upstream_proxy_protocol\b;<a href="postconf.5.html#postscreen_upstream_proxy_protocol">$&</a>;g;
|
||||||
|
s;\bpostscreen_upstream_proxy_timeout\b;<a href="postconf.5.html#postscreen_upstream_proxy_timeout">$&</a>;g;
|
||||||
|
|
||||||
s;\btlsproxy_watchdog_timeout\b;<a href="postconf.5.html#tlsproxy_watchdog_timeout">$&</a>;g;
|
s;\btlsproxy_watchdog_timeout\b;<a href="postconf.5.html#tlsproxy_watchdog_timeout">$&</a>;g;
|
||||||
s;\btlsproxy_enforce_tls\b;<a href="postconf.5.html#tlsproxy_enforce_tls">$&</a>;g;
|
s;\btlsproxy_enforce_tls\b;<a href="postconf.5.html#tlsproxy_enforce_tls">$&</a>;g;
|
||||||
|
@ -14369,6 +14369,44 @@ and will never be allowed to talk to a Postfix SMTP server process.
|
|||||||
|
|
||||||
<p> This feature is available in Postfix 2.9 and later. </p>
|
<p> This feature is available in Postfix 2.9 and later. </p>
|
||||||
|
|
||||||
|
%PARAM postscreen_upstream_proxy_protocol
|
||||||
|
|
||||||
|
<p> The name of the proxy protocol used by an optional before-postscreen
|
||||||
|
proxy agent. When a proxy agent is used, this protocol conveys local
|
||||||
|
and remote address and port information. Specify
|
||||||
|
"postscreen_upstream_proxy_protocol = haproxy" to enable the haproxy
|
||||||
|
protocol. <p>
|
||||||
|
|
||||||
|
<p> This feature is available in Postfix 2.10 and later. </p>
|
||||||
|
|
||||||
|
%PARAM postscreen_upstream_proxy_timeout 5s
|
||||||
|
|
||||||
|
<p> The time limit for the proxy protocol specified with the
|
||||||
|
postscreen_upstream_proxy_protocol parameter. </p>
|
||||||
|
|
||||||
|
<p> This feature is available in Postfix 2.10 and later. </p>
|
||||||
|
|
||||||
|
%PARAM smtpd_upstream_proxy_protocol
|
||||||
|
|
||||||
|
<p> The name of the proxy protocol used by an optional before-smtpd
|
||||||
|
proxy agent. When a proxy agent is used, this protocol conveys local
|
||||||
|
and remote address and port information. Specify
|
||||||
|
"smtpd_upstream_proxy_protocol = haproxy" to enable the haproxy
|
||||||
|
protocol. </p>
|
||||||
|
|
||||||
|
<p> NOTE: To use the nginx proxy with smtpd(8), enable the XCLIENT
|
||||||
|
protocol with smtpd_authorized_xclient_hosts. This supports SASL
|
||||||
|
authentication in the proxy agent (Postfix 2.9 and later). <p>
|
||||||
|
|
||||||
|
<p> This feature is available in Postfix 2.10 and later. </p>
|
||||||
|
|
||||||
|
%PARAM smtpd_upstream_proxy_timeout 5s
|
||||||
|
|
||||||
|
<p> The time limit for the proxy protocol specified with the
|
||||||
|
smtpd_upstream_proxy_protocol parameter. </p>
|
||||||
|
|
||||||
|
<p> This feature is available in Postfix 2.10 and later. </p>
|
||||||
|
|
||||||
%PARAM enable_long_queue_ids no
|
%PARAM enable_long_queue_ids no
|
||||||
|
|
||||||
<p> Enable long, non-repeating, queue IDs (queue file names). The
|
<p> Enable long, non-repeating, queue IDs (queue file names). The
|
||||||
|
@ -32,7 +32,7 @@ SRCS = abounce.c anvil_clnt.c been_here.c bounce.c bounce_log.c \
|
|||||||
match_service.c mail_conf_nint.c addr_match_list.c mail_conf_nbool.c \
|
match_service.c mail_conf_nint.c addr_match_list.c mail_conf_nbool.c \
|
||||||
smtp_reply_footer.c safe_ultostr.c verify_sender_addr.c \
|
smtp_reply_footer.c safe_ultostr.c verify_sender_addr.c \
|
||||||
dict_memcache.c mail_version.c memcache_proto.c server_acl.c \
|
dict_memcache.c mail_version.c memcache_proto.c server_acl.c \
|
||||||
mkmap_fail.c
|
mkmap_fail.c haproxy_srvr.c
|
||||||
OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
|
OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
|
||||||
canon_addr.o cfg_parser.o cleanup_strerror.o cleanup_strflags.o \
|
canon_addr.o cfg_parser.o cleanup_strerror.o cleanup_strflags.o \
|
||||||
clnt_stream.o conv_time.o db_common.o debug_peer.o debug_process.o \
|
clnt_stream.o conv_time.o db_common.o debug_peer.o debug_process.o \
|
||||||
@ -66,7 +66,7 @@ OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
|
|||||||
match_service.o mail_conf_nint.o addr_match_list.o mail_conf_nbool.o \
|
match_service.o mail_conf_nint.o addr_match_list.o mail_conf_nbool.o \
|
||||||
smtp_reply_footer.o safe_ultostr.o verify_sender_addr.o \
|
smtp_reply_footer.o safe_ultostr.o verify_sender_addr.o \
|
||||||
dict_memcache.o mail_version.o memcache_proto.o server_acl.o \
|
dict_memcache.o mail_version.o memcache_proto.o server_acl.o \
|
||||||
mkmap_fail.o
|
mkmap_fail.o haproxy_srvr.o
|
||||||
HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \
|
HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \
|
||||||
canon_addr.h cfg_parser.h cleanup_user.h clnt_stream.h config.h \
|
canon_addr.h cfg_parser.h cleanup_user.h clnt_stream.h config.h \
|
||||||
conv_time.h db_common.h debug_peer.h debug_process.h defer.h \
|
conv_time.h db_common.h debug_peer.h debug_process.h defer.h \
|
||||||
@ -92,7 +92,8 @@ HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \
|
|||||||
verp_sender.h wildcard_inet_addr.h xtext.h delivered_hdr.h \
|
verp_sender.h wildcard_inet_addr.h xtext.h delivered_hdr.h \
|
||||||
fold_addr.h header_body_checks.h data_redirect.h match_service.h \
|
fold_addr.h header_body_checks.h data_redirect.h match_service.h \
|
||||||
addr_match_list.h smtp_reply_footer.h safe_ultostr.h \
|
addr_match_list.h smtp_reply_footer.h safe_ultostr.h \
|
||||||
verify_sender_addr.h dict_memcache.h memcache_proto.h server_acl.h
|
verify_sender_addr.h dict_memcache.h memcache_proto.h server_acl.h \
|
||||||
|
haproxy_srvr.h
|
||||||
TESTSRC = rec2stream.c stream2rec.c recdump.c
|
TESTSRC = rec2stream.c stream2rec.c recdump.c
|
||||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||||
@ -1100,6 +1101,15 @@ fold_addr.o: ../../include/vbuf.h
|
|||||||
fold_addr.o: ../../include/vstring.h
|
fold_addr.o: ../../include/vstring.h
|
||||||
fold_addr.o: fold_addr.c
|
fold_addr.o: fold_addr.c
|
||||||
fold_addr.o: fold_addr.h
|
fold_addr.o: fold_addr.h
|
||||||
|
haproxy_srvr.o: ../../include/msg.h
|
||||||
|
haproxy_srvr.o: ../../include/myaddrinfo.h
|
||||||
|
haproxy_srvr.o: ../../include/stringops.h
|
||||||
|
haproxy_srvr.o: ../../include/sys_defs.h
|
||||||
|
haproxy_srvr.o: ../../include/valid_hostname.h
|
||||||
|
haproxy_srvr.o: ../../include/vbuf.h
|
||||||
|
haproxy_srvr.o: ../../include/vstring.h
|
||||||
|
haproxy_srvr.o: haproxy_srvr.c
|
||||||
|
haproxy_srvr.o: haproxy_srvr.h
|
||||||
header_body_checks.o: ../../include/argv.h
|
header_body_checks.o: ../../include/argv.h
|
||||||
header_body_checks.o: ../../include/dict.h
|
header_body_checks.o: ../../include/dict.h
|
||||||
header_body_checks.o: ../../include/msg.h
|
header_body_checks.o: ../../include/msg.h
|
||||||
|
197
postfix/src/global/haproxy_srvr.c
Normal file
197
postfix/src/global/haproxy_srvr.c
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
/*++
|
||||||
|
/* NAME
|
||||||
|
/* haproxy_srvr 3
|
||||||
|
/* SUMMARY
|
||||||
|
/* server-side haproxy protocol support
|
||||||
|
/* SYNOPSIS
|
||||||
|
/* #include <haproxy_srvr.h>
|
||||||
|
/*
|
||||||
|
/* const char *haproxy_srvr_parse(str,
|
||||||
|
/* smtp_client_addr, smtp_client_port,
|
||||||
|
/* smtp_server_addr, smtp_server_port)
|
||||||
|
/* const char *str;
|
||||||
|
/* MAI_HOSTADDR_STR *smtp_client_addr,
|
||||||
|
/* MAI_SERVPORT_STR *smtp_client_port,
|
||||||
|
/* MAI_HOSTADDR_STR *smtp_server_addr,
|
||||||
|
/* MAI_SERVPORT_STR *smtp_server_port;
|
||||||
|
/* DESCRIPTION
|
||||||
|
/* haproxy_srvr_parse() parses a haproxy line. The result is
|
||||||
|
/* null in case of success, a pointer to text (with the error
|
||||||
|
/* type) in case of error. If both IPv6 and IPv4 support are
|
||||||
|
/* enabled, IPV4_IN_IPV6 address syntax (::ffff:1.2.3.4) is
|
||||||
|
/* converted to IPV4 syntax.
|
||||||
|
/* LICENSE
|
||||||
|
/* .ad
|
||||||
|
/* .fi
|
||||||
|
/* The Secure Mailer license must be distributed with this software.
|
||||||
|
/* AUTHOR(S)
|
||||||
|
/* Wietse Venema
|
||||||
|
/* IBM T.J. Watson Research
|
||||||
|
/* P.O. Box 704
|
||||||
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*--*/
|
||||||
|
|
||||||
|
/* System library. */
|
||||||
|
|
||||||
|
#include <sys_defs.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef STRCASECMP_IN_STRINGS_H
|
||||||
|
#include <strings.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Utility library. */
|
||||||
|
|
||||||
|
#include <msg.h>
|
||||||
|
#include <myaddrinfo.h>
|
||||||
|
#include <valid_hostname.h>
|
||||||
|
#include <stringops.h>
|
||||||
|
#include <mymalloc.h>
|
||||||
|
#include <inet_proto.h>
|
||||||
|
|
||||||
|
/* Global library. */
|
||||||
|
|
||||||
|
#include <haproxy_srvr.h>
|
||||||
|
|
||||||
|
/* Application-specific. */
|
||||||
|
|
||||||
|
static INET_PROTO_INFO *proto_info;
|
||||||
|
|
||||||
|
/* haproxy_srvr_parse_lit - extract and validate string literal */
|
||||||
|
|
||||||
|
static int haproxy_srvr_parse_lit(const char *str,...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
const char *cp;
|
||||||
|
int result = -1;
|
||||||
|
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("haproxy_srvr_parse: %s", str);
|
||||||
|
|
||||||
|
if (str != 0) {
|
||||||
|
va_start(ap, str);
|
||||||
|
while (result < 0 && (cp = va_arg(ap, const char *)) != 0)
|
||||||
|
if (strcmp(str, cp) == 0)
|
||||||
|
result = 0;
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* haproxy_srvr_parse_proto - parse and validate the protocol type */
|
||||||
|
|
||||||
|
static int haproxy_srvr_parse_proto(const char *str, int *addr_family)
|
||||||
|
{
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("haproxy_srvr_parse: proto=%s", str);
|
||||||
|
|
||||||
|
#ifdef AF_INET6
|
||||||
|
if (strcasecmp(str, "TCP6") == 0) {
|
||||||
|
if (strchr((char *) proto_info->sa_family_list, AF_INET6) != 0) {
|
||||||
|
*addr_family = AF_INET6;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
if (strcasecmp(str, "TCP4") == 0) {
|
||||||
|
if (strchr((char *) proto_info->sa_family_list, AF_INET) != 0) {
|
||||||
|
*addr_family = AF_INET;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* haproxy_srvr_parse_addr - extract and validate IP address */
|
||||||
|
|
||||||
|
static int haproxy_srvr_parse_addr(const char *str, MAI_HOSTADDR_STR *addr,
|
||||||
|
int addr_family)
|
||||||
|
{
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("haproxy_srvr_parse: addr=%s proto=%d", str, addr_family);
|
||||||
|
|
||||||
|
if (str == 0 || strlen(str) >= sizeof(MAI_HOSTADDR_STR))
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
switch (addr_family) {
|
||||||
|
#ifdef AF_INET6
|
||||||
|
case AF_INET6:
|
||||||
|
if (!valid_ipv6_hostaddr(str, DONT_GRIPE))
|
||||||
|
return (-1);
|
||||||
|
if (strncasecmp("::ffff:", str, 7) == 0
|
||||||
|
&& strchr((char *) proto_info->sa_family_list, AF_INET) != 0) {
|
||||||
|
memcpy(addr->buf, str + 7, strlen(str) + 1 - 7);
|
||||||
|
return (0);
|
||||||
|
} else {
|
||||||
|
memcpy(addr->buf, str, strlen(str) + 1);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
case AF_INET:
|
||||||
|
if (!valid_ipv4_hostaddr(str, DONT_GRIPE))
|
||||||
|
return (-1);
|
||||||
|
memcpy(addr->buf, str, strlen(str) + 1);
|
||||||
|
return (0);
|
||||||
|
default:
|
||||||
|
msg_panic("haproxy_srvr_parse: unexpected address family: %d",
|
||||||
|
addr_family);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* haproxy_srvr_parse_port - extract and validate TCP port */
|
||||||
|
|
||||||
|
static int haproxy_srvr_parse_port(const char *str, MAI_SERVPORT_STR *port)
|
||||||
|
{
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("haproxy_srvr_parse: port=%s", str);
|
||||||
|
if (str == 0 || strlen(str) >= sizeof(MAI_SERVPORT_STR)
|
||||||
|
|| !valid_hostport(str, DONT_GRIPE)) {
|
||||||
|
return (-1);
|
||||||
|
} else {
|
||||||
|
memcpy(port->buf, str, strlen(str) + 1);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* haproxy_srvr_parse - parse haproxy line */
|
||||||
|
|
||||||
|
const char *haproxy_srvr_parse(const char *str,
|
||||||
|
MAI_HOSTADDR_STR *smtp_client_addr,
|
||||||
|
MAI_SERVPORT_STR *smtp_client_port,
|
||||||
|
MAI_HOSTADDR_STR *smtp_server_addr,
|
||||||
|
MAI_SERVPORT_STR *smtp_server_port)
|
||||||
|
{
|
||||||
|
char *saved_str = mystrdup(str);
|
||||||
|
char *cp = saved_str;
|
||||||
|
const char *err;
|
||||||
|
int addr_family;
|
||||||
|
|
||||||
|
if (proto_info == 0)
|
||||||
|
proto_info = inet_proto_info();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX We don't accept connections with the "UNKNOWN" protocol type,
|
||||||
|
* because those would sidestep address-based access control mechanisms.
|
||||||
|
*/
|
||||||
|
#define NEXT_TOKEN mystrtok(&cp, " \r\n")
|
||||||
|
if (haproxy_srvr_parse_lit(NEXT_TOKEN, "PROXY", (char *) 0) < 0)
|
||||||
|
err = "unexpected protocol header";
|
||||||
|
else if (haproxy_srvr_parse_proto(NEXT_TOKEN, &addr_family) < 0)
|
||||||
|
err = "unsupported protocol type";
|
||||||
|
else if (haproxy_srvr_parse_addr(NEXT_TOKEN, smtp_client_addr,
|
||||||
|
addr_family) < 0)
|
||||||
|
err = "unexpected client address syntax";
|
||||||
|
else if (haproxy_srvr_parse_addr(NEXT_TOKEN, smtp_server_addr,
|
||||||
|
addr_family) < 0)
|
||||||
|
err = "unexpected server address syntax";
|
||||||
|
else if (haproxy_srvr_parse_port(NEXT_TOKEN, smtp_client_port) < 0)
|
||||||
|
err = "unexpected client port syntax";
|
||||||
|
else if (haproxy_srvr_parse_port(NEXT_TOKEN, smtp_server_port) < 0)
|
||||||
|
err = "unexpected server port syntax";
|
||||||
|
else
|
||||||
|
err = 0;
|
||||||
|
myfree(saved_str);
|
||||||
|
return (err);
|
||||||
|
}
|
45
postfix/src/global/haproxy_srvr.h
Normal file
45
postfix/src/global/haproxy_srvr.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#ifndef _HAPROXY_SRVR_H_INCLUDED_
|
||||||
|
#define _HAPROXY_SRVR_H_INCLUDED_
|
||||||
|
|
||||||
|
/*++
|
||||||
|
/* NAME
|
||||||
|
/* haproxy_srvr 3h
|
||||||
|
/* SUMMARY
|
||||||
|
/* server-side haproxy protocol support
|
||||||
|
/* SYNOPSIS
|
||||||
|
/* #include <haproxy_srvr.h>
|
||||||
|
/* DESCRIPTION
|
||||||
|
/* .nf
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility library.
|
||||||
|
*/
|
||||||
|
#include <myaddrinfo.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* External interface.
|
||||||
|
*/
|
||||||
|
extern const char *haproxy_srvr_parse(const char *,
|
||||||
|
MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *,
|
||||||
|
MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *);
|
||||||
|
|
||||||
|
#define HAPROXY_PROTO_NAME "haproxy"
|
||||||
|
#define HAPROXY_MAX_LEN (256 + 2)
|
||||||
|
|
||||||
|
#ifndef DO_GRIPE
|
||||||
|
#define DO_GRIPE 1
|
||||||
|
#define DONT_GRIPE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* LICENSE
|
||||||
|
/* .ad
|
||||||
|
/* .fi
|
||||||
|
/* The Secure Mailer license must be distributed with this software.
|
||||||
|
/* AUTHOR(S)
|
||||||
|
/* Wietse Venema
|
||||||
|
/* IBM T.J. Watson Research
|
||||||
|
/* P.O. Box 704
|
||||||
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*--*/
|
||||||
|
|
||||||
|
#endif
|
@ -3458,6 +3458,14 @@ extern char *var_psc_acl;
|
|||||||
#define DEF_PSC_WLIST_IF "static:all"
|
#define DEF_PSC_WLIST_IF "static:all"
|
||||||
extern char *var_psc_wlist_if;
|
extern char *var_psc_wlist_if;
|
||||||
|
|
||||||
|
#define VAR_PSC_UPROXY_PROTO "postscreen_upstream_proxy_protocol"
|
||||||
|
#define DEF_PSC_UPROXY_PROTO ""
|
||||||
|
extern char *var_psc_uproxy_proto;
|
||||||
|
|
||||||
|
#define VAR_PSC_UPROXY_TMOUT "postscreen_upstream_proxy_timeout"
|
||||||
|
#define DEF_PSC_UPROXY_TMOUT "5s"
|
||||||
|
extern int var_psc_uproxy_tmout;
|
||||||
|
|
||||||
#define VAR_DNSBLOG_SERVICE "dnsblog_service_name"
|
#define VAR_DNSBLOG_SERVICE "dnsblog_service_name"
|
||||||
#define DEF_DNSBLOG_SERVICE MAIL_SERVICE_DNSBLOG
|
#define DEF_DNSBLOG_SERVICE MAIL_SERVICE_DNSBLOG
|
||||||
extern char *var_dnsblog_service;
|
extern char *var_dnsblog_service;
|
||||||
@ -3620,6 +3628,17 @@ extern bool var_smtp_rec_deadline;
|
|||||||
#define DEF_SMTPD_ACL_PERM_LOG ""
|
#define DEF_SMTPD_ACL_PERM_LOG ""
|
||||||
extern char *var_smtpd_acl_perm_log;
|
extern char *var_smtpd_acl_perm_log;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Before-smtpd proxy support.
|
||||||
|
*/
|
||||||
|
#define VAR_SMTPD_UPROXY_PROTO "smtpd_upstream_proxy_protocol"
|
||||||
|
#define DEF_SMTPD_UPROXY_PROTO ""
|
||||||
|
extern char *var_smtpd_uproxy_proto;
|
||||||
|
|
||||||
|
#define VAR_SMTPD_UPROXY_TMOUT "smtpd_upstream_proxy_timeout"
|
||||||
|
#define DEF_SMTPD_UPROXY_TMOUT "5s"
|
||||||
|
extern int var_smtpd_uproxy_tmout;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Postfix sendmail command compatibility features.
|
* Postfix sendmail command compatibility features.
|
||||||
*/
|
*/
|
||||||
|
@ -193,6 +193,9 @@ extern char *mail_pathname(const char *, const char *);
|
|||||||
#define MAIL_ATTR_ACT_REVERSE_CLIENT_NAME "reverse_client_name"
|
#define MAIL_ATTR_ACT_REVERSE_CLIENT_NAME "reverse_client_name"
|
||||||
#define MAIL_ATTR_ACT_FORWARD_CLIENT_NAME "forward_client_name"
|
#define MAIL_ATTR_ACT_FORWARD_CLIENT_NAME "forward_client_name"
|
||||||
|
|
||||||
|
#define MAIL_ATTR_ACT_SERVER_ADDR "server_address" /* server address */
|
||||||
|
#define MAIL_ATTR_ACT_SERVER_PORT "server_port" /* server TCP port */
|
||||||
|
|
||||||
#define MAIL_ATTR_PROTO_STATE "protocol_state" /* MAIL/RCPT/... */
|
#define MAIL_ATTR_PROTO_STATE "protocol_state" /* MAIL/RCPT/... */
|
||||||
#define MAIL_ATTR_ORG_NONE "unknown" /* origin unknown */
|
#define MAIL_ATTR_ORG_NONE "unknown" /* origin unknown */
|
||||||
#define MAIL_ATTR_ORG_LOCAL "local" /* local submission */
|
#define MAIL_ATTR_ORG_LOCAL "local" /* local submission */
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
* Patches change both the patchlevel and the release date. Snapshots have no
|
* Patches change both the patchlevel and the release date. Snapshots have no
|
||||||
* patchlevel; they change the release date only.
|
* patchlevel; they change the release date only.
|
||||||
*/
|
*/
|
||||||
#define MAIL_RELEASE_DATE "20120617"
|
#define MAIL_RELEASE_DATE "20120621"
|
||||||
#define MAIL_VERSION_NUMBER "2.10"
|
#define MAIL_VERSION_NUMBER "2.10"
|
||||||
|
|
||||||
#ifdef SNAPSHOT
|
#ifdef SNAPSHOT
|
||||||
|
@ -90,6 +90,7 @@ event_server.o: ../../include/chroot_uid.h
|
|||||||
event_server.o: ../../include/debug_process.h
|
event_server.o: ../../include/debug_process.h
|
||||||
event_server.o: ../../include/dict.h
|
event_server.o: ../../include/dict.h
|
||||||
event_server.o: ../../include/events.h
|
event_server.o: ../../include/events.h
|
||||||
|
event_server.o: ../../include/htable.h
|
||||||
event_server.o: ../../include/iostuff.h
|
event_server.o: ../../include/iostuff.h
|
||||||
event_server.o: ../../include/listen.h
|
event_server.o: ../../include/listen.h
|
||||||
event_server.o: ../../include/mail_conf.h
|
event_server.o: ../../include/mail_conf.h
|
||||||
@ -193,6 +194,7 @@ master_flow.o: ../../include/sys_defs.h
|
|||||||
master_flow.o: master.h
|
master_flow.o: master.h
|
||||||
master_flow.o: master_flow.c
|
master_flow.o: master_flow.c
|
||||||
master_flow.o: master_proto.h
|
master_flow.o: master_proto.h
|
||||||
|
master_listen.o: ../../include/htable.h
|
||||||
master_listen.o: ../../include/inet_addr_list.h
|
master_listen.o: ../../include/inet_addr_list.h
|
||||||
master_listen.o: ../../include/iostuff.h
|
master_listen.o: ../../include/iostuff.h
|
||||||
master_listen.o: ../../include/listen.h
|
master_listen.o: ../../include/listen.h
|
||||||
@ -286,6 +288,7 @@ multi_server.o: ../../include/chroot_uid.h
|
|||||||
multi_server.o: ../../include/debug_process.h
|
multi_server.o: ../../include/debug_process.h
|
||||||
multi_server.o: ../../include/dict.h
|
multi_server.o: ../../include/dict.h
|
||||||
multi_server.o: ../../include/events.h
|
multi_server.o: ../../include/events.h
|
||||||
|
multi_server.o: ../../include/htable.h
|
||||||
multi_server.o: ../../include/iostuff.h
|
multi_server.o: ../../include/iostuff.h
|
||||||
multi_server.o: ../../include/listen.h
|
multi_server.o: ../../include/listen.h
|
||||||
multi_server.o: ../../include/mail_conf.h
|
multi_server.o: ../../include/mail_conf.h
|
||||||
@ -318,6 +321,7 @@ single_server.o: ../../include/chroot_uid.h
|
|||||||
single_server.o: ../../include/debug_process.h
|
single_server.o: ../../include/debug_process.h
|
||||||
single_server.o: ../../include/dict.h
|
single_server.o: ../../include/dict.h
|
||||||
single_server.o: ../../include/events.h
|
single_server.o: ../../include/events.h
|
||||||
|
single_server.o: ../../include/htable.h
|
||||||
single_server.o: ../../include/iostuff.h
|
single_server.o: ../../include/iostuff.h
|
||||||
single_server.o: ../../include/listen.h
|
single_server.o: ../../include/listen.h
|
||||||
single_server.o: ../../include/mail_conf.h
|
single_server.o: ../../include/mail_conf.h
|
||||||
@ -350,6 +354,7 @@ trigger_server.o: ../../include/chroot_uid.h
|
|||||||
trigger_server.o: ../../include/debug_process.h
|
trigger_server.o: ../../include/debug_process.h
|
||||||
trigger_server.o: ../../include/dict.h
|
trigger_server.o: ../../include/dict.h
|
||||||
trigger_server.o: ../../include/events.h
|
trigger_server.o: ../../include/events.h
|
||||||
|
trigger_server.o: ../../include/htable.h
|
||||||
trigger_server.o: ../../include/iostuff.h
|
trigger_server.o: ../../include/iostuff.h
|
||||||
trigger_server.o: ../../include/listen.h
|
trigger_server.o: ../../include/listen.h
|
||||||
trigger_server.o: ../../include/mail_conf.h
|
trigger_server.o: ../../include/mail_conf.h
|
||||||
|
@ -38,7 +38,10 @@
|
|||||||
/* its privileges. The application is responsible for managing
|
/* its privileges. The application is responsible for managing
|
||||||
/* subsequent I/O events on the stream, and is responsible for
|
/* subsequent I/O events on the stream, and is responsible for
|
||||||
/* calling event_server_disconnect() when the stream is closed.
|
/* calling event_server_disconnect() when the stream is closed.
|
||||||
/* The stream initial state is non-blocking mode. The service
|
/* The stream initial state is non-blocking mode.
|
||||||
|
/* Optional connection attributes are provided as a hash that
|
||||||
|
/* is attached as stream context. NOTE: the attributes are
|
||||||
|
/* destroyed after this function is called. The service
|
||||||
/* name argument corresponds to the service name in the master.cf
|
/* name argument corresponds to the service name in the master.cf
|
||||||
/* file. The argv argument specifies command-line arguments
|
/* file. The argv argument specifies command-line arguments
|
||||||
/* left over after options processing.
|
/* left over after options processing.
|
||||||
@ -255,6 +258,7 @@ static unsigned event_server_generation;
|
|||||||
static void (*event_server_pre_disconn) (VSTREAM *, char *, char **);
|
static void (*event_server_pre_disconn) (VSTREAM *, char *, char **);
|
||||||
static void (*event_server_slow_exit) (char *, char **);
|
static void (*event_server_slow_exit) (char *, char **);
|
||||||
static int event_server_watchdog = 1000;
|
static int event_server_watchdog = 1000;
|
||||||
|
static int event_server_saved_flags;
|
||||||
|
|
||||||
/* event_server_exit - normal termination */
|
/* event_server_exit - normal termination */
|
||||||
|
|
||||||
@ -339,6 +343,8 @@ void event_server_disconnect(VSTREAM *stream)
|
|||||||
static void event_server_execute(int unused_event, char *context)
|
static void event_server_execute(int unused_event, char *context)
|
||||||
{
|
{
|
||||||
VSTREAM *stream = (VSTREAM *) context;
|
VSTREAM *stream = (VSTREAM *) context;
|
||||||
|
HTABLE *attr = (vstream_flags(stream) == event_server_saved_flags ?
|
||||||
|
(HTABLE *) vstream_context(stream) : 0);
|
||||||
|
|
||||||
if (event_server_lock != 0
|
if (event_server_lock != 0
|
||||||
&& myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK,
|
&& myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK,
|
||||||
@ -355,11 +361,13 @@ static void event_server_execute(int unused_event, char *context)
|
|||||||
event_server_service(stream, event_server_name, event_server_argv);
|
event_server_service(stream, event_server_name, event_server_argv);
|
||||||
if (master_notify(var_pid, event_server_generation, MASTER_STAT_AVAIL) < 0)
|
if (master_notify(var_pid, event_server_generation, MASTER_STAT_AVAIL) < 0)
|
||||||
event_server_abort(EVENT_NULL_TYPE, EVENT_NULL_CONTEXT);
|
event_server_abort(EVENT_NULL_TYPE, EVENT_NULL_CONTEXT);
|
||||||
|
if (attr)
|
||||||
|
htable_free(attr, myfree);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* event_server_wakeup - wake up application */
|
/* event_server_wakeup - wake up application */
|
||||||
|
|
||||||
static void event_server_wakeup(int fd)
|
static void event_server_wakeup(int fd, HTABLE *attr)
|
||||||
{
|
{
|
||||||
VSTREAM *stream;
|
VSTREAM *stream;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
@ -388,9 +396,13 @@ static void event_server_wakeup(int fd)
|
|||||||
client_count++;
|
client_count++;
|
||||||
stream = vstream_fdopen(fd, O_RDWR);
|
stream = vstream_fdopen(fd, O_RDWR);
|
||||||
tmp = concatenate(event_server_name, " socket", (char *) 0);
|
tmp = concatenate(event_server_name, " socket", (char *) 0);
|
||||||
vstream_control(stream, VSTREAM_CTL_PATH, tmp, VSTREAM_CTL_END);
|
vstream_control(stream,
|
||||||
|
VSTREAM_CTL_PATH, tmp,
|
||||||
|
VSTREAM_CTL_CONTEXT, (char *) attr,
|
||||||
|
VSTREAM_CTL_END);
|
||||||
myfree(tmp);
|
myfree(tmp);
|
||||||
timed_ipc_setup(stream);
|
timed_ipc_setup(stream);
|
||||||
|
event_server_saved_flags = vstream_flags(stream);
|
||||||
if (event_server_in_flow_delay && mail_flow_get(1) < 0)
|
if (event_server_in_flow_delay && mail_flow_get(1) < 0)
|
||||||
event_request_timer(event_server_execute, (char *) stream,
|
event_request_timer(event_server_execute, (char *) stream,
|
||||||
var_in_flow_delay);
|
var_in_flow_delay);
|
||||||
@ -430,7 +442,7 @@ static void event_server_accept_local(int unused_event, char *context)
|
|||||||
event_request_timer(event_server_timeout, (char *) 0, time_left);
|
event_request_timer(event_server_timeout, (char *) 0, time_left);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
event_server_wakeup(fd);
|
event_server_wakeup(fd, (HTABLE *) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MASTER_XPORT_NAME_PASS
|
#ifdef MASTER_XPORT_NAME_PASS
|
||||||
@ -442,6 +454,7 @@ static void event_server_accept_pass(int unused_event, char *context)
|
|||||||
int listen_fd = CAST_CHAR_PTR_TO_INT(context);
|
int listen_fd = CAST_CHAR_PTR_TO_INT(context);
|
||||||
int time_left = -1;
|
int time_left = -1;
|
||||||
int fd;
|
int fd;
|
||||||
|
HTABLE *attr = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Be prepared for accept() to fail because some other process already
|
* Be prepared for accept() to fail because some other process already
|
||||||
@ -455,7 +468,7 @@ static void event_server_accept_pass(int unused_event, char *context)
|
|||||||
|
|
||||||
if (event_server_pre_accept)
|
if (event_server_pre_accept)
|
||||||
event_server_pre_accept(event_server_name, event_server_argv);
|
event_server_pre_accept(event_server_name, event_server_argv);
|
||||||
fd = PASS_ACCEPT(listen_fd);
|
fd = pass_accept_attr(listen_fd, &attr);
|
||||||
if (event_server_lock != 0
|
if (event_server_lock != 0
|
||||||
&& myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK,
|
&& myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK,
|
||||||
MYFLOCK_OP_NONE) < 0)
|
MYFLOCK_OP_NONE) < 0)
|
||||||
@ -467,7 +480,7 @@ static void event_server_accept_pass(int unused_event, char *context)
|
|||||||
event_request_timer(event_server_timeout, (char *) 0, time_left);
|
event_request_timer(event_server_timeout, (char *) 0, time_left);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
event_server_wakeup(fd);
|
event_server_wakeup(fd, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -504,7 +517,7 @@ static void event_server_accept_inet(int unused_event, char *context)
|
|||||||
event_request_timer(event_server_timeout, (char *) 0, time_left);
|
event_request_timer(event_server_timeout, (char *) 0, time_left);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
event_server_wakeup(fd);
|
event_server_wakeup(fd, (HTABLE *) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* event_server_main - the real main program */
|
/* event_server_main - the real main program */
|
||||||
|
@ -136,7 +136,7 @@ void master_listen_init(MASTER_SERV *serv)
|
|||||||
case MASTER_SERV_TYPE_PASS:
|
case MASTER_SERV_TYPE_PASS:
|
||||||
set_eugid(var_owner_uid, var_owner_gid);
|
set_eugid(var_owner_uid, var_owner_gid);
|
||||||
serv->listen_fd[0] =
|
serv->listen_fd[0] =
|
||||||
PASS_LISTEN(serv->name, serv->max_proc > var_proc_limit ?
|
LOCAL_LISTEN(serv->name, serv->max_proc > var_proc_limit ?
|
||||||
serv->max_proc : var_proc_limit, NON_BLOCKING);
|
serv->max_proc : var_proc_limit, NON_BLOCKING);
|
||||||
close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC);
|
close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC);
|
||||||
set_ugid(getuid(), getgid());
|
set_ugid(getuid(), getgid());
|
||||||
|
@ -107,7 +107,7 @@ static void master_wakeup_timer_event(int unused_event, char *context)
|
|||||||
break;
|
break;
|
||||||
#ifdef MASTER_SERV_TYPE_PASS
|
#ifdef MASTER_SERV_TYPE_PASS
|
||||||
case MASTER_SERV_TYPE_PASS:
|
case MASTER_SERV_TYPE_PASS:
|
||||||
status = PASS_TRIGGER(serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
|
status = pass_trigger(serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -35,6 +35,9 @@
|
|||||||
/* function is run after the program has optionally dropped its
|
/* function is run after the program has optionally dropped its
|
||||||
/* privileges. This function should not attempt to preserve state
|
/* privileges. This function should not attempt to preserve state
|
||||||
/* across calls. The stream initial state is non-blocking mode.
|
/* across calls. The stream initial state is non-blocking mode.
|
||||||
|
/* Optional connection attributes are provided as a hash that
|
||||||
|
/* is attached as stream context. NOTE: the attributes are
|
||||||
|
/* destroyed after this function is called.
|
||||||
/* The service name argument corresponds to the service name in the
|
/* The service name argument corresponds to the service name in the
|
||||||
/* master.cf file.
|
/* master.cf file.
|
||||||
/* The argv argument specifies command-line arguments left over
|
/* The argv argument specifies command-line arguments left over
|
||||||
@ -241,6 +244,7 @@ static VSTREAM *multi_server_lock;
|
|||||||
static int multi_server_in_flow_delay;
|
static int multi_server_in_flow_delay;
|
||||||
static unsigned multi_server_generation;
|
static unsigned multi_server_generation;
|
||||||
static void (*multi_server_pre_disconn) (VSTREAM *, char *, char **);
|
static void (*multi_server_pre_disconn) (VSTREAM *, char *, char **);
|
||||||
|
static int multi_server_saved_flags;
|
||||||
|
|
||||||
/* multi_server_exit - normal termination */
|
/* multi_server_exit - normal termination */
|
||||||
|
|
||||||
@ -322,6 +326,8 @@ void multi_server_disconnect(VSTREAM *stream)
|
|||||||
static void multi_server_execute(int unused_event, char *context)
|
static void multi_server_execute(int unused_event, char *context)
|
||||||
{
|
{
|
||||||
VSTREAM *stream = (VSTREAM *) context;
|
VSTREAM *stream = (VSTREAM *) context;
|
||||||
|
HTABLE *attr = (vstream_flags(stream) == multi_server_saved_flags ?
|
||||||
|
(HTABLE *) vstream_context(stream) : 0);
|
||||||
|
|
||||||
if (multi_server_lock != 0
|
if (multi_server_lock != 0
|
||||||
&& myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
|
&& myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
|
||||||
@ -342,6 +348,8 @@ static void multi_server_execute(int unused_event, char *context)
|
|||||||
} else {
|
} else {
|
||||||
multi_server_disconnect(stream);
|
multi_server_disconnect(stream);
|
||||||
}
|
}
|
||||||
|
if (attr)
|
||||||
|
htable_free(attr, myfree);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* multi_server_enable_read - enable read events */
|
/* multi_server_enable_read - enable read events */
|
||||||
@ -355,7 +363,7 @@ static void multi_server_enable_read(int unused_event, char *context)
|
|||||||
|
|
||||||
/* multi_server_wakeup - wake up application */
|
/* multi_server_wakeup - wake up application */
|
||||||
|
|
||||||
static void multi_server_wakeup(int fd)
|
static void multi_server_wakeup(int fd, HTABLE *attr)
|
||||||
{
|
{
|
||||||
VSTREAM *stream;
|
VSTREAM *stream;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
@ -384,9 +392,13 @@ static void multi_server_wakeup(int fd)
|
|||||||
client_count++;
|
client_count++;
|
||||||
stream = vstream_fdopen(fd, O_RDWR);
|
stream = vstream_fdopen(fd, O_RDWR);
|
||||||
tmp = concatenate(multi_server_name, " socket", (char *) 0);
|
tmp = concatenate(multi_server_name, " socket", (char *) 0);
|
||||||
vstream_control(stream, VSTREAM_CTL_PATH, tmp, VSTREAM_CTL_END);
|
vstream_control(stream,
|
||||||
|
VSTREAM_CTL_PATH, tmp,
|
||||||
|
VSTREAM_CTL_CONTEXT, (char *) attr,
|
||||||
|
VSTREAM_CTL_END);
|
||||||
myfree(tmp);
|
myfree(tmp);
|
||||||
timed_ipc_setup(stream);
|
timed_ipc_setup(stream);
|
||||||
|
multi_server_saved_flags = vstream_flags(stream);
|
||||||
if (multi_server_in_flow_delay && mail_flow_get(1) < 0)
|
if (multi_server_in_flow_delay && mail_flow_get(1) < 0)
|
||||||
event_request_timer(multi_server_enable_read, (char *) stream,
|
event_request_timer(multi_server_enable_read, (char *) stream,
|
||||||
var_in_flow_delay);
|
var_in_flow_delay);
|
||||||
@ -426,7 +438,7 @@ static void multi_server_accept_local(int unused_event, char *context)
|
|||||||
event_request_timer(multi_server_timeout, (char *) 0, time_left);
|
event_request_timer(multi_server_timeout, (char *) 0, time_left);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
multi_server_wakeup(fd);
|
multi_server_wakeup(fd, (HTABLE *) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MASTER_XPORT_NAME_PASS
|
#ifdef MASTER_XPORT_NAME_PASS
|
||||||
@ -438,6 +450,7 @@ static void multi_server_accept_pass(int unused_event, char *context)
|
|||||||
int listen_fd = CAST_CHAR_PTR_TO_INT(context);
|
int listen_fd = CAST_CHAR_PTR_TO_INT(context);
|
||||||
int time_left = -1;
|
int time_left = -1;
|
||||||
int fd;
|
int fd;
|
||||||
|
HTABLE *attr = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Be prepared for accept() to fail because some other process already
|
* Be prepared for accept() to fail because some other process already
|
||||||
@ -451,7 +464,7 @@ static void multi_server_accept_pass(int unused_event, char *context)
|
|||||||
|
|
||||||
if (multi_server_pre_accept)
|
if (multi_server_pre_accept)
|
||||||
multi_server_pre_accept(multi_server_name, multi_server_argv);
|
multi_server_pre_accept(multi_server_name, multi_server_argv);
|
||||||
fd = PASS_ACCEPT(listen_fd);
|
fd = pass_accept_attr(listen_fd, &attr);
|
||||||
if (multi_server_lock != 0
|
if (multi_server_lock != 0
|
||||||
&& myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
|
&& myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
|
||||||
MYFLOCK_OP_NONE) < 0)
|
MYFLOCK_OP_NONE) < 0)
|
||||||
@ -463,7 +476,7 @@ static void multi_server_accept_pass(int unused_event, char *context)
|
|||||||
event_request_timer(multi_server_timeout, (char *) 0, time_left);
|
event_request_timer(multi_server_timeout, (char *) 0, time_left);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
multi_server_wakeup(fd);
|
multi_server_wakeup(fd, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -500,7 +513,7 @@ static void multi_server_accept_inet(int unused_event, char *context)
|
|||||||
event_request_timer(multi_server_timeout, (char *) 0, time_left);
|
event_request_timer(multi_server_timeout, (char *) 0, time_left);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
multi_server_wakeup(fd);
|
multi_server_wakeup(fd, (HTABLE *) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* multi_server_main - the real main program */
|
/* multi_server_main - the real main program */
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
/* a client connects to the program's service port. The function is
|
/* a client connects to the program's service port. The function is
|
||||||
/* run after the program has irrevocably dropped its privileges.
|
/* run after the program has irrevocably dropped its privileges.
|
||||||
/* The stream initial state is non-blocking mode.
|
/* The stream initial state is non-blocking mode.
|
||||||
|
/* Optional connection attributes are provided as a hash that
|
||||||
|
/* is attached as stream context.
|
||||||
/* The service name argument corresponds to the service name in the
|
/* The service name argument corresponds to the service name in the
|
||||||
/* master.cf file.
|
/* master.cf file.
|
||||||
/* The argv argument specifies command-line arguments left over
|
/* The argv argument specifies command-line arguments left over
|
||||||
@ -245,7 +247,7 @@ static void single_server_timeout(int unused_event, char *unused_context)
|
|||||||
|
|
||||||
/* single_server_wakeup - wake up application */
|
/* single_server_wakeup - wake up application */
|
||||||
|
|
||||||
static void single_server_wakeup(int fd)
|
static void single_server_wakeup(int fd, HTABLE *attr)
|
||||||
{
|
{
|
||||||
VSTREAM *stream;
|
VSTREAM *stream;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
@ -263,7 +265,10 @@ static void single_server_wakeup(int fd)
|
|||||||
close_on_exec(fd, CLOSE_ON_EXEC);
|
close_on_exec(fd, CLOSE_ON_EXEC);
|
||||||
stream = vstream_fdopen(fd, O_RDWR);
|
stream = vstream_fdopen(fd, O_RDWR);
|
||||||
tmp = concatenate(single_server_name, " socket", (char *) 0);
|
tmp = concatenate(single_server_name, " socket", (char *) 0);
|
||||||
vstream_control(stream, VSTREAM_CTL_PATH, tmp, VSTREAM_CTL_END);
|
vstream_control(stream,
|
||||||
|
VSTREAM_CTL_PATH, tmp,
|
||||||
|
VSTREAM_CTL_CONTEXT, (char *) attr,
|
||||||
|
VSTREAM_CTL_END);
|
||||||
myfree(tmp);
|
myfree(tmp);
|
||||||
timed_ipc_setup(stream);
|
timed_ipc_setup(stream);
|
||||||
if (master_notify(var_pid, single_server_generation, MASTER_STAT_TAKEN) < 0)
|
if (master_notify(var_pid, single_server_generation, MASTER_STAT_TAKEN) < 0)
|
||||||
@ -281,6 +286,8 @@ static void single_server_wakeup(int fd)
|
|||||||
use_count++;
|
use_count++;
|
||||||
if (var_idle_limit > 0)
|
if (var_idle_limit > 0)
|
||||||
event_request_timer(single_server_timeout, (char *) 0, var_idle_limit);
|
event_request_timer(single_server_timeout, (char *) 0, var_idle_limit);
|
||||||
|
if (attr)
|
||||||
|
htable_free(attr, myfree);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* single_server_accept_local - accept client connection request */
|
/* single_server_accept_local - accept client connection request */
|
||||||
@ -314,7 +321,7 @@ static void single_server_accept_local(int unused_event, char *context)
|
|||||||
event_request_timer(single_server_timeout, (char *) 0, time_left);
|
event_request_timer(single_server_timeout, (char *) 0, time_left);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
single_server_wakeup(fd);
|
single_server_wakeup(fd, (HTABLE *) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MASTER_XPORT_NAME_PASS
|
#ifdef MASTER_XPORT_NAME_PASS
|
||||||
@ -326,6 +333,7 @@ static void single_server_accept_pass(int unused_event, char *context)
|
|||||||
int listen_fd = CAST_CHAR_PTR_TO_INT(context);
|
int listen_fd = CAST_CHAR_PTR_TO_INT(context);
|
||||||
int time_left = -1;
|
int time_left = -1;
|
||||||
int fd;
|
int fd;
|
||||||
|
HTABLE *attr = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Be prepared for accept() to fail because some other process already
|
* Be prepared for accept() to fail because some other process already
|
||||||
@ -338,7 +346,7 @@ static void single_server_accept_pass(int unused_event, char *context)
|
|||||||
|
|
||||||
if (single_server_pre_accept)
|
if (single_server_pre_accept)
|
||||||
single_server_pre_accept(single_server_name, single_server_argv);
|
single_server_pre_accept(single_server_name, single_server_argv);
|
||||||
fd = PASS_ACCEPT(listen_fd);
|
fd = pass_accept_attr(listen_fd, &attr);
|
||||||
if (single_server_lock != 0
|
if (single_server_lock != 0
|
||||||
&& myflock(vstream_fileno(single_server_lock), INTERNAL_LOCK,
|
&& myflock(vstream_fileno(single_server_lock), INTERNAL_LOCK,
|
||||||
MYFLOCK_OP_NONE) < 0)
|
MYFLOCK_OP_NONE) < 0)
|
||||||
@ -350,7 +358,7 @@ static void single_server_accept_pass(int unused_event, char *context)
|
|||||||
event_request_timer(single_server_timeout, (char *) 0, time_left);
|
event_request_timer(single_server_timeout, (char *) 0, time_left);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
single_server_wakeup(fd);
|
single_server_wakeup(fd, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -386,7 +394,7 @@ static void single_server_accept_inet(int unused_event, char *context)
|
|||||||
event_request_timer(single_server_timeout, (char *) 0, time_left);
|
event_request_timer(single_server_timeout, (char *) 0, time_left);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
single_server_wakeup(fd);
|
single_server_wakeup(fd, (HTABLE *) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* single_server_main - the real main program */
|
/* single_server_main - the real main program */
|
||||||
|
@ -376,7 +376,7 @@ static void trigger_server_accept_pass(int unused_event, char *context)
|
|||||||
|
|
||||||
if (trigger_server_pre_accept)
|
if (trigger_server_pre_accept)
|
||||||
trigger_server_pre_accept(trigger_server_name, trigger_server_argv);
|
trigger_server_pre_accept(trigger_server_name, trigger_server_argv);
|
||||||
fd = PASS_ACCEPT(listen_fd);
|
fd = pass_accept(listen_fd);
|
||||||
if (trigger_server_lock != 0
|
if (trigger_server_lock != 0
|
||||||
&& myflock(vstream_fileno(trigger_server_lock), INTERNAL_LOCK,
|
&& myflock(vstream_fileno(trigger_server_lock), INTERNAL_LOCK,
|
||||||
MYFLOCK_OP_NONE) < 0)
|
MYFLOCK_OP_NONE) < 0)
|
||||||
|
@ -2,11 +2,13 @@ SHELL = /bin/sh
|
|||||||
SRCS = postscreen.c postscreen_dict.c postscreen_dnsbl.c \
|
SRCS = postscreen.c postscreen_dict.c postscreen_dnsbl.c \
|
||||||
postscreen_early.c postscreen_smtpd.c postscreen_misc.c \
|
postscreen_early.c postscreen_smtpd.c postscreen_misc.c \
|
||||||
postscreen_state.c postscreen_tests.c postscreen_send.c \
|
postscreen_state.c postscreen_tests.c postscreen_send.c \
|
||||||
postscreen_starttls.c postscreen_expand.c
|
postscreen_starttls.c postscreen_expand.c postscreen_endpt.c \
|
||||||
|
postscreen_haproxy.c
|
||||||
OBJS = postscreen.o postscreen_dict.o postscreen_dnsbl.o \
|
OBJS = postscreen.o postscreen_dict.o postscreen_dnsbl.o \
|
||||||
postscreen_early.o postscreen_smtpd.o postscreen_misc.o \
|
postscreen_early.o postscreen_smtpd.o postscreen_misc.o \
|
||||||
postscreen_state.o postscreen_tests.o postscreen_send.o \
|
postscreen_state.o postscreen_tests.o postscreen_send.o \
|
||||||
postscreen_starttls.o postscreen_expand.o
|
postscreen_starttls.o postscreen_expand.o postscreen_endpt.o \
|
||||||
|
postscreen_haproxy.o
|
||||||
HDRS =
|
HDRS =
|
||||||
TESTSRC =
|
TESTSRC =
|
||||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||||
@ -103,6 +105,7 @@ postscreen_dict.o: ../../include/htable.h
|
|||||||
postscreen_dict.o: ../../include/maps.h
|
postscreen_dict.o: ../../include/maps.h
|
||||||
postscreen_dict.o: ../../include/match_list.h
|
postscreen_dict.o: ../../include/match_list.h
|
||||||
postscreen_dict.o: ../../include/msg.h
|
postscreen_dict.o: ../../include/msg.h
|
||||||
|
postscreen_dict.o: ../../include/myaddrinfo.h
|
||||||
postscreen_dict.o: ../../include/server_acl.h
|
postscreen_dict.o: ../../include/server_acl.h
|
||||||
postscreen_dict.o: ../../include/string_list.h
|
postscreen_dict.o: ../../include/string_list.h
|
||||||
postscreen_dict.o: ../../include/sys_defs.h
|
postscreen_dict.o: ../../include/sys_defs.h
|
||||||
@ -149,6 +152,7 @@ postscreen_early.o: ../../include/mail_params.h
|
|||||||
postscreen_early.o: ../../include/maps.h
|
postscreen_early.o: ../../include/maps.h
|
||||||
postscreen_early.o: ../../include/match_list.h
|
postscreen_early.o: ../../include/match_list.h
|
||||||
postscreen_early.o: ../../include/msg.h
|
postscreen_early.o: ../../include/msg.h
|
||||||
|
postscreen_early.o: ../../include/myaddrinfo.h
|
||||||
postscreen_early.o: ../../include/mymalloc.h
|
postscreen_early.o: ../../include/mymalloc.h
|
||||||
postscreen_early.o: ../../include/server_acl.h
|
postscreen_early.o: ../../include/server_acl.h
|
||||||
postscreen_early.o: ../../include/string_list.h
|
postscreen_early.o: ../../include/string_list.h
|
||||||
@ -159,6 +163,27 @@ postscreen_early.o: ../../include/vstream.h
|
|||||||
postscreen_early.o: ../../include/vstring.h
|
postscreen_early.o: ../../include/vstring.h
|
||||||
postscreen_early.o: postscreen.h
|
postscreen_early.o: postscreen.h
|
||||||
postscreen_early.o: postscreen_early.c
|
postscreen_early.o: postscreen_early.c
|
||||||
|
postscreen_endpt.o: ../../include/addr_match_list.h
|
||||||
|
postscreen_endpt.o: ../../include/argv.h
|
||||||
|
postscreen_endpt.o: ../../include/dict.h
|
||||||
|
postscreen_endpt.o: ../../include/dict_cache.h
|
||||||
|
postscreen_endpt.o: ../../include/events.h
|
||||||
|
postscreen_endpt.o: ../../include/haproxy_srvr.h
|
||||||
|
postscreen_endpt.o: ../../include/htable.h
|
||||||
|
postscreen_endpt.o: ../../include/mail_params.h
|
||||||
|
postscreen_endpt.o: ../../include/maps.h
|
||||||
|
postscreen_endpt.o: ../../include/match_list.h
|
||||||
|
postscreen_endpt.o: ../../include/msg.h
|
||||||
|
postscreen_endpt.o: ../../include/myaddrinfo.h
|
||||||
|
postscreen_endpt.o: ../../include/server_acl.h
|
||||||
|
postscreen_endpt.o: ../../include/string_list.h
|
||||||
|
postscreen_endpt.o: ../../include/sys_defs.h
|
||||||
|
postscreen_endpt.o: ../../include/vbuf.h
|
||||||
|
postscreen_endpt.o: ../../include/vstream.h
|
||||||
|
postscreen_endpt.o: ../../include/vstring.h
|
||||||
|
postscreen_endpt.o: postscreen.h
|
||||||
|
postscreen_endpt.o: postscreen_endpt.c
|
||||||
|
postscreen_endpt.o: postscreen_haproxy.h
|
||||||
postscreen_expand.o: ../../include/addr_match_list.h
|
postscreen_expand.o: ../../include/addr_match_list.h
|
||||||
postscreen_expand.o: ../../include/argv.h
|
postscreen_expand.o: ../../include/argv.h
|
||||||
postscreen_expand.o: ../../include/attr.h
|
postscreen_expand.o: ../../include/attr.h
|
||||||
@ -172,6 +197,7 @@ postscreen_expand.o: ../../include/mail_proto.h
|
|||||||
postscreen_expand.o: ../../include/maps.h
|
postscreen_expand.o: ../../include/maps.h
|
||||||
postscreen_expand.o: ../../include/match_list.h
|
postscreen_expand.o: ../../include/match_list.h
|
||||||
postscreen_expand.o: ../../include/msg.h
|
postscreen_expand.o: ../../include/msg.h
|
||||||
|
postscreen_expand.o: ../../include/myaddrinfo.h
|
||||||
postscreen_expand.o: ../../include/server_acl.h
|
postscreen_expand.o: ../../include/server_acl.h
|
||||||
postscreen_expand.o: ../../include/string_list.h
|
postscreen_expand.o: ../../include/string_list.h
|
||||||
postscreen_expand.o: ../../include/stringops.h
|
postscreen_expand.o: ../../include/stringops.h
|
||||||
@ -181,6 +207,28 @@ postscreen_expand.o: ../../include/vstream.h
|
|||||||
postscreen_expand.o: ../../include/vstring.h
|
postscreen_expand.o: ../../include/vstring.h
|
||||||
postscreen_expand.o: postscreen.h
|
postscreen_expand.o: postscreen.h
|
||||||
postscreen_expand.o: postscreen_expand.c
|
postscreen_expand.o: postscreen_expand.c
|
||||||
|
postscreen_haproxy.o: ../../include/addr_match_list.h
|
||||||
|
postscreen_haproxy.o: ../../include/argv.h
|
||||||
|
postscreen_haproxy.o: ../../include/dict.h
|
||||||
|
postscreen_haproxy.o: ../../include/dict_cache.h
|
||||||
|
postscreen_haproxy.o: ../../include/events.h
|
||||||
|
postscreen_haproxy.o: ../../include/haproxy_srvr.h
|
||||||
|
postscreen_haproxy.o: ../../include/htable.h
|
||||||
|
postscreen_haproxy.o: ../../include/maps.h
|
||||||
|
postscreen_haproxy.o: ../../include/match_list.h
|
||||||
|
postscreen_haproxy.o: ../../include/msg.h
|
||||||
|
postscreen_haproxy.o: ../../include/myaddrinfo.h
|
||||||
|
postscreen_haproxy.o: ../../include/mymalloc.h
|
||||||
|
postscreen_haproxy.o: ../../include/server_acl.h
|
||||||
|
postscreen_haproxy.o: ../../include/string_list.h
|
||||||
|
postscreen_haproxy.o: ../../include/stringops.h
|
||||||
|
postscreen_haproxy.o: ../../include/sys_defs.h
|
||||||
|
postscreen_haproxy.o: ../../include/vbuf.h
|
||||||
|
postscreen_haproxy.o: ../../include/vstream.h
|
||||||
|
postscreen_haproxy.o: ../../include/vstring.h
|
||||||
|
postscreen_haproxy.o: postscreen.h
|
||||||
|
postscreen_haproxy.o: postscreen_haproxy.c
|
||||||
|
postscreen_haproxy.o: postscreen_haproxy.h
|
||||||
postscreen_misc.o: ../../include/addr_match_list.h
|
postscreen_misc.o: ../../include/addr_match_list.h
|
||||||
postscreen_misc.o: ../../include/argv.h
|
postscreen_misc.o: ../../include/argv.h
|
||||||
postscreen_misc.o: ../../include/dict.h
|
postscreen_misc.o: ../../include/dict.h
|
||||||
@ -193,6 +241,7 @@ postscreen_misc.o: ../../include/mail_params.h
|
|||||||
postscreen_misc.o: ../../include/maps.h
|
postscreen_misc.o: ../../include/maps.h
|
||||||
postscreen_misc.o: ../../include/match_list.h
|
postscreen_misc.o: ../../include/match_list.h
|
||||||
postscreen_misc.o: ../../include/msg.h
|
postscreen_misc.o: ../../include/msg.h
|
||||||
|
postscreen_misc.o: ../../include/myaddrinfo.h
|
||||||
postscreen_misc.o: ../../include/server_acl.h
|
postscreen_misc.o: ../../include/server_acl.h
|
||||||
postscreen_misc.o: ../../include/string_list.h
|
postscreen_misc.o: ../../include/string_list.h
|
||||||
postscreen_misc.o: ../../include/sys_defs.h
|
postscreen_misc.o: ../../include/sys_defs.h
|
||||||
@ -203,6 +252,7 @@ postscreen_misc.o: postscreen.h
|
|||||||
postscreen_misc.o: postscreen_misc.c
|
postscreen_misc.o: postscreen_misc.c
|
||||||
postscreen_send.o: ../../include/addr_match_list.h
|
postscreen_send.o: ../../include/addr_match_list.h
|
||||||
postscreen_send.o: ../../include/argv.h
|
postscreen_send.o: ../../include/argv.h
|
||||||
|
postscreen_send.o: ../../include/attr.h
|
||||||
postscreen_send.o: ../../include/connect.h
|
postscreen_send.o: ../../include/connect.h
|
||||||
postscreen_send.o: ../../include/dict.h
|
postscreen_send.o: ../../include/dict.h
|
||||||
postscreen_send.o: ../../include/dict_cache.h
|
postscreen_send.o: ../../include/dict_cache.h
|
||||||
@ -212,9 +262,11 @@ postscreen_send.o: ../../include/iostuff.h
|
|||||||
postscreen_send.o: ../../include/mac_expand.h
|
postscreen_send.o: ../../include/mac_expand.h
|
||||||
postscreen_send.o: ../../include/mac_parse.h
|
postscreen_send.o: ../../include/mac_parse.h
|
||||||
postscreen_send.o: ../../include/mail_params.h
|
postscreen_send.o: ../../include/mail_params.h
|
||||||
|
postscreen_send.o: ../../include/mail_proto.h
|
||||||
postscreen_send.o: ../../include/maps.h
|
postscreen_send.o: ../../include/maps.h
|
||||||
postscreen_send.o: ../../include/match_list.h
|
postscreen_send.o: ../../include/match_list.h
|
||||||
postscreen_send.o: ../../include/msg.h
|
postscreen_send.o: ../../include/msg.h
|
||||||
|
postscreen_send.o: ../../include/myaddrinfo.h
|
||||||
postscreen_send.o: ../../include/server_acl.h
|
postscreen_send.o: ../../include/server_acl.h
|
||||||
postscreen_send.o: ../../include/smtp_reply_footer.h
|
postscreen_send.o: ../../include/smtp_reply_footer.h
|
||||||
postscreen_send.o: ../../include/string_list.h
|
postscreen_send.o: ../../include/string_list.h
|
||||||
@ -240,6 +292,7 @@ postscreen_smtpd.o: ../../include/mail_proto.h
|
|||||||
postscreen_smtpd.o: ../../include/maps.h
|
postscreen_smtpd.o: ../../include/maps.h
|
||||||
postscreen_smtpd.o: ../../include/match_list.h
|
postscreen_smtpd.o: ../../include/match_list.h
|
||||||
postscreen_smtpd.o: ../../include/msg.h
|
postscreen_smtpd.o: ../../include/msg.h
|
||||||
|
postscreen_smtpd.o: ../../include/myaddrinfo.h
|
||||||
postscreen_smtpd.o: ../../include/mymalloc.h
|
postscreen_smtpd.o: ../../include/mymalloc.h
|
||||||
postscreen_smtpd.o: ../../include/name_code.h
|
postscreen_smtpd.o: ../../include/name_code.h
|
||||||
postscreen_smtpd.o: ../../include/name_mask.h
|
postscreen_smtpd.o: ../../include/name_mask.h
|
||||||
@ -267,6 +320,7 @@ postscreen_starttls.o: ../../include/mail_proto.h
|
|||||||
postscreen_starttls.o: ../../include/maps.h
|
postscreen_starttls.o: ../../include/maps.h
|
||||||
postscreen_starttls.o: ../../include/match_list.h
|
postscreen_starttls.o: ../../include/match_list.h
|
||||||
postscreen_starttls.o: ../../include/msg.h
|
postscreen_starttls.o: ../../include/msg.h
|
||||||
|
postscreen_starttls.o: ../../include/myaddrinfo.h
|
||||||
postscreen_starttls.o: ../../include/mymalloc.h
|
postscreen_starttls.o: ../../include/mymalloc.h
|
||||||
postscreen_starttls.o: ../../include/name_code.h
|
postscreen_starttls.o: ../../include/name_code.h
|
||||||
postscreen_starttls.o: ../../include/name_mask.h
|
postscreen_starttls.o: ../../include/name_mask.h
|
||||||
@ -294,6 +348,7 @@ postscreen_state.o: ../../include/mail_server.h
|
|||||||
postscreen_state.o: ../../include/maps.h
|
postscreen_state.o: ../../include/maps.h
|
||||||
postscreen_state.o: ../../include/match_list.h
|
postscreen_state.o: ../../include/match_list.h
|
||||||
postscreen_state.o: ../../include/msg.h
|
postscreen_state.o: ../../include/msg.h
|
||||||
|
postscreen_state.o: ../../include/myaddrinfo.h
|
||||||
postscreen_state.o: ../../include/mymalloc.h
|
postscreen_state.o: ../../include/mymalloc.h
|
||||||
postscreen_state.o: ../../include/name_mask.h
|
postscreen_state.o: ../../include/name_mask.h
|
||||||
postscreen_state.o: ../../include/server_acl.h
|
postscreen_state.o: ../../include/server_acl.h
|
||||||
@ -314,6 +369,7 @@ postscreen_tests.o: ../../include/mail_params.h
|
|||||||
postscreen_tests.o: ../../include/maps.h
|
postscreen_tests.o: ../../include/maps.h
|
||||||
postscreen_tests.o: ../../include/match_list.h
|
postscreen_tests.o: ../../include/match_list.h
|
||||||
postscreen_tests.o: ../../include/msg.h
|
postscreen_tests.o: ../../include/msg.h
|
||||||
|
postscreen_tests.o: ../../include/myaddrinfo.h
|
||||||
postscreen_tests.o: ../../include/server_acl.h
|
postscreen_tests.o: ../../include/server_acl.h
|
||||||
postscreen_tests.o: ../../include/string_list.h
|
postscreen_tests.o: ../../include/string_list.h
|
||||||
postscreen_tests.o: ../../include/sys_defs.h
|
postscreen_tests.o: ../../include/sys_defs.h
|
||||||
|
@ -132,6 +132,16 @@
|
|||||||
/* .IP "\fBsoft_bounce (no)\fR"
|
/* .IP "\fBsoft_bounce (no)\fR"
|
||||||
/* Safety net to keep mail queued that would otherwise be returned to
|
/* Safety net to keep mail queued that would otherwise be returned to
|
||||||
/* the sender.
|
/* the sender.
|
||||||
|
/* BEFORE-POSTSCREEN PROXY AGENT
|
||||||
|
/* .ad
|
||||||
|
/* .fi
|
||||||
|
/* Available in Postfix version 2.10 and later:
|
||||||
|
/* .IP "\fBpostscreen_upstream_proxy_protocol (empty)\fR"
|
||||||
|
/* The name of the proxy protocol used by an optional before-postscreen
|
||||||
|
/* proxy agent.
|
||||||
|
/* .IP "\fBpostscreen_upstream_proxy_timeout (5s)\fR"
|
||||||
|
/* The time limit for the proxy protocol specified with the
|
||||||
|
/* postscreen_upstream_proxy_protocol parameter.
|
||||||
/* PERMANENT WHITE/BLACKLIST TEST
|
/* PERMANENT WHITE/BLACKLIST TEST
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
@ -484,6 +494,8 @@ char *var_smtpd_exp_filter;
|
|||||||
char *var_psc_exp_filter;
|
char *var_psc_exp_filter;
|
||||||
|
|
||||||
char *var_psc_wlist_if;
|
char *var_psc_wlist_if;
|
||||||
|
char *var_psc_uproxy_proto;
|
||||||
|
int var_psc_uproxy_tmout;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global variables.
|
* Global variables.
|
||||||
@ -512,12 +524,16 @@ DICT *psc_dnsbl_reply; /* DNSBL name mapper */
|
|||||||
HTABLE *psc_client_concurrency; /* per-client concurrency */
|
HTABLE *psc_client_concurrency; /* per-client concurrency */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local variables.
|
* Local variables and functions.
|
||||||
*/
|
*/
|
||||||
static ARGV *psc_acl; /* permanent white/backlist */
|
static ARGV *psc_acl; /* permanent white/backlist */
|
||||||
static int psc_blist_action; /* PSC_ACT_DROP/ENFORCE/etc */
|
static int psc_blist_action; /* PSC_ACT_DROP/ENFORCE/etc */
|
||||||
static ADDR_MATCH_LIST *psc_wlist_if; /* whitelist interfaces */
|
static ADDR_MATCH_LIST *psc_wlist_if; /* whitelist interfaces */
|
||||||
|
|
||||||
|
static void psc_endpt_lookup_done(int, VSTREAM *,
|
||||||
|
MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *,
|
||||||
|
MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *);
|
||||||
|
|
||||||
/* psc_dump - dump some statistics before exit */
|
/* psc_dump - dump some statistics before exit */
|
||||||
|
|
||||||
static void psc_dump(void)
|
static void psc_dump(void)
|
||||||
@ -581,17 +597,6 @@ static void psc_service(VSTREAM *smtp_client_stream,
|
|||||||
char *unused_service,
|
char *unused_service,
|
||||||
char **unused_argv)
|
char **unused_argv)
|
||||||
{
|
{
|
||||||
const char *myname = "psc_service";
|
|
||||||
PSC_STATE *state;
|
|
||||||
struct sockaddr_storage addr_storage;
|
|
||||||
SOCKADDR_SIZE addr_storage_len = sizeof(addr_storage);
|
|
||||||
MAI_HOSTADDR_STR smtp_client_addr;
|
|
||||||
MAI_SERVPORT_STR smtp_client_port;
|
|
||||||
MAI_HOSTADDR_STR smtp_server_addr;
|
|
||||||
MAI_SERVPORT_STR smtp_server_port;
|
|
||||||
int aierr;
|
|
||||||
const char *stamp_str;
|
|
||||||
int saved_flags;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For sanity, require that at least one of INET or INET6 is enabled.
|
* For sanity, require that at least one of INET or INET6 is enabled.
|
||||||
@ -611,85 +616,53 @@ static void psc_service(VSTREAM *smtp_client_stream,
|
|||||||
*/
|
*/
|
||||||
non_blocking(vstream_fileno(smtp_client_stream), NON_BLOCKING);
|
non_blocking(vstream_fileno(smtp_client_stream), NON_BLOCKING);
|
||||||
|
|
||||||
/*
|
|
||||||
* We use the event_server framework. This means we get already-accepted
|
|
||||||
* connections so we have to invoke getpeername() to find out the remote
|
|
||||||
* address and port.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Best effort - if this non-blocking write(2) fails, so be it. */
|
|
||||||
#define PSC_SERVICE_DISCONNECT_AND_RETURN(stream) do { \
|
|
||||||
(void) write(vstream_fileno(stream), \
|
|
||||||
"421 4.3.2 No system resources\r\n", \
|
|
||||||
sizeof("421 4.3.2 No system resources\r\n") - 1); \
|
|
||||||
event_server_disconnect(stream); \
|
|
||||||
return; \
|
|
||||||
} while (0);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Look up the remote SMTP client address and port.
|
* Look up the remote SMTP client address and port.
|
||||||
*/
|
*/
|
||||||
if (getpeername(vstream_fileno(smtp_client_stream), (struct sockaddr *)
|
psc_endpt_lookup(smtp_client_stream, psc_endpt_lookup_done);
|
||||||
& addr_storage, &addr_storage_len) < 0) {
|
}
|
||||||
msg_warn("getpeername: %m -- dropping this connection");
|
|
||||||
PSC_SERVICE_DISCONNECT_AND_RETURN(smtp_client_stream);
|
/* psc_endpt_lookup_done - endpoint lookup completed */
|
||||||
}
|
|
||||||
|
static void psc_endpt_lookup_done(int endpt_status,
|
||||||
|
VSTREAM *smtp_client_stream,
|
||||||
|
MAI_HOSTADDR_STR *smtp_client_addr,
|
||||||
|
MAI_SERVPORT_STR *smtp_client_port,
|
||||||
|
MAI_HOSTADDR_STR *smtp_server_addr,
|
||||||
|
MAI_SERVPORT_STR *smtp_server_port)
|
||||||
|
{
|
||||||
|
const char *myname = "psc_endpt_lookup_done";
|
||||||
|
PSC_STATE *state;
|
||||||
|
const char *stamp_str;
|
||||||
|
int saved_flags;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert the remote SMTP client address and port to printable form for
|
* Best effort - if this non-blocking write(2) fails, so be it.
|
||||||
* logging and access control.
|
|
||||||
*/
|
*/
|
||||||
if ((aierr = sockaddr_to_hostaddr((struct sockaddr *) & addr_storage,
|
if (endpt_status < 0) {
|
||||||
addr_storage_len, &smtp_client_addr,
|
(void) write(vstream_fileno(smtp_client_stream),
|
||||||
&smtp_client_port, 0)) != 0) {
|
"421 4.3.2 No system resources\r\n",
|
||||||
msg_warn("cannot convert client address/port to string: %s"
|
sizeof("421 4.3.2 No system resources\r\n") - 1);
|
||||||
" -- dropping this connection",
|
event_server_disconnect(smtp_client_stream);
|
||||||
MAI_STRERROR(aierr));
|
return;
|
||||||
PSC_SERVICE_DISCONNECT_AND_RETURN(smtp_client_stream);
|
|
||||||
}
|
}
|
||||||
if (strncasecmp("::ffff:", smtp_client_addr.buf, 7) == 0)
|
|
||||||
memmove(smtp_client_addr.buf, smtp_client_addr.buf + 7,
|
|
||||||
sizeof(smtp_client_addr.buf) - 7);
|
|
||||||
if (msg_verbose > 1)
|
if (msg_verbose > 1)
|
||||||
msg_info("%s: sq=%d cq=%d connect from [%s]:%s",
|
msg_info("%s: sq=%d cq=%d connect from [%s]:%s",
|
||||||
myname, psc_post_queue_length, psc_check_queue_length,
|
myname, psc_post_queue_length, psc_check_queue_length,
|
||||||
smtp_client_addr.buf, smtp_client_port.buf);
|
smtp_client_addr->buf, smtp_client_port->buf);
|
||||||
|
|
||||||
/*
|
|
||||||
* Look up the local SMTP server address and port.
|
|
||||||
*/
|
|
||||||
if (getsockname(vstream_fileno(smtp_client_stream), (struct sockaddr *)
|
|
||||||
& addr_storage, &addr_storage_len) < 0) {
|
|
||||||
msg_warn("getsockname: %m -- dropping this connection");
|
|
||||||
PSC_SERVICE_DISCONNECT_AND_RETURN(smtp_client_stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert the local SMTP server address and port to printable form for
|
|
||||||
* logging and access control.
|
|
||||||
*/
|
|
||||||
if ((aierr = sockaddr_to_hostaddr((struct sockaddr *) & addr_storage,
|
|
||||||
addr_storage_len, &smtp_server_addr,
|
|
||||||
&smtp_server_port, 0)) != 0) {
|
|
||||||
msg_warn("cannot convert server address/port to string: %s"
|
|
||||||
" -- dropping this connection",
|
|
||||||
MAI_STRERROR(aierr));
|
|
||||||
PSC_SERVICE_DISCONNECT_AND_RETURN(smtp_client_stream);
|
|
||||||
}
|
|
||||||
if (strncasecmp("::ffff:", smtp_server_addr.buf, 7) == 0)
|
|
||||||
memmove(smtp_server_addr.buf, smtp_server_addr.buf + 7,
|
|
||||||
sizeof(smtp_server_addr.buf) - 7);
|
|
||||||
|
|
||||||
msg_info("CONNECT from [%s]:%s to [%s]:%s",
|
msg_info("CONNECT from [%s]:%s to [%s]:%s",
|
||||||
smtp_client_addr.buf, smtp_client_port.buf,
|
smtp_client_addr->buf, smtp_client_port->buf,
|
||||||
smtp_server_addr.buf, smtp_server_port.buf);
|
smtp_server_addr->buf, smtp_server_port->buf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bundle up all the loose session pieces. This zeroes all flags and time
|
* Bundle up all the loose session pieces. This zeroes all flags and time
|
||||||
* stamps.
|
* stamps.
|
||||||
*/
|
*/
|
||||||
state = psc_new_session_state(smtp_client_stream, smtp_client_addr.buf,
|
state = psc_new_session_state(smtp_client_stream, smtp_client_addr->buf,
|
||||||
smtp_client_port.buf);
|
smtp_client_port->buf,
|
||||||
|
smtp_server_addr->buf,
|
||||||
|
smtp_server_port->buf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reply with 421 when the client has too many open connections.
|
* Reply with 421 when the client has too many open connections.
|
||||||
@ -799,7 +772,7 @@ static void psc_service(VSTREAM *smtp_client_stream,
|
|||||||
* Don't whitelist clients that connect to backup MX addresses. Fail
|
* Don't whitelist clients that connect to backup MX addresses. Fail
|
||||||
* "closed" on error.
|
* "closed" on error.
|
||||||
*/
|
*/
|
||||||
if (addr_match_list_match(psc_wlist_if, smtp_server_addr.buf) == 0) {
|
if (addr_match_list_match(psc_wlist_if, smtp_server_addr->buf) == 0) {
|
||||||
state->flags |= (PSC_STATE_FLAG_WLIST_FAIL | PSC_STATE_FLAG_NOFORWARD);
|
state->flags |= (PSC_STATE_FLAG_WLIST_FAIL | PSC_STATE_FLAG_NOFORWARD);
|
||||||
msg_info("WHITELIST VETO [%s]:%s", PSC_CLIENT_ADDR_PORT(state));
|
msg_info("WHITELIST VETO [%s]:%s", PSC_CLIENT_ADDR_PORT(state));
|
||||||
}
|
}
|
||||||
@ -1114,6 +1087,7 @@ int main(int argc, char **argv)
|
|||||||
VAR_DNSBLOG_SERVICE, DEF_DNSBLOG_SERVICE, &var_dnsblog_service, 1, 0,
|
VAR_DNSBLOG_SERVICE, DEF_DNSBLOG_SERVICE, &var_dnsblog_service, 1, 0,
|
||||||
VAR_TLSPROXY_SERVICE, DEF_TLSPROXY_SERVICE, &var_tlsproxy_service, 1, 0,
|
VAR_TLSPROXY_SERVICE, DEF_TLSPROXY_SERVICE, &var_tlsproxy_service, 1, 0,
|
||||||
VAR_PSC_WLIST_IF, DEF_PSC_WLIST_IF, &var_psc_wlist_if, 0, 0,
|
VAR_PSC_WLIST_IF, DEF_PSC_WLIST_IF, &var_psc_wlist_if, 0, 0,
|
||||||
|
VAR_PSC_UPROXY_PROTO, DEF_PSC_UPROXY_PROTO, &var_psc_uproxy_proto, 0, 0,
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
static const CONFIG_INT_TABLE int_table[] = {
|
static const CONFIG_INT_TABLE int_table[] = {
|
||||||
@ -1139,6 +1113,7 @@ int main(int argc, char **argv)
|
|||||||
VAR_PSC_CACHE_RET, DEF_PSC_CACHE_RET, &var_psc_cache_ret, 1, 0,
|
VAR_PSC_CACHE_RET, DEF_PSC_CACHE_RET, &var_psc_cache_ret, 1, 0,
|
||||||
VAR_PSC_CACHE_SCAN, DEF_PSC_CACHE_SCAN, &var_psc_cache_scan, 0, 0,
|
VAR_PSC_CACHE_SCAN, DEF_PSC_CACHE_SCAN, &var_psc_cache_scan, 0, 0,
|
||||||
VAR_PSC_WATCHDOG, DEF_PSC_WATCHDOG, &var_psc_watchdog, 10, 0,
|
VAR_PSC_WATCHDOG, DEF_PSC_WATCHDOG, &var_psc_watchdog, 10, 0,
|
||||||
|
VAR_PSC_UPROXY_TMOUT, DEF_PSC_UPROXY_TMOUT, &var_psc_uproxy_tmout, 1, 0,
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
static const CONFIG_BOOL_TABLE bool_table[] = {
|
static const CONFIG_BOOL_TABLE bool_table[] = {
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <vstring.h>
|
#include <vstring.h>
|
||||||
#include <events.h>
|
#include <events.h>
|
||||||
#include <htable.h>
|
#include <htable.h>
|
||||||
|
#include <myaddrinfo.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global library.
|
* Global library.
|
||||||
@ -44,6 +45,8 @@ typedef struct {
|
|||||||
int smtp_server_fd; /* real SMTP server */
|
int smtp_server_fd; /* real SMTP server */
|
||||||
char *smtp_client_addr; /* client address */
|
char *smtp_client_addr; /* client address */
|
||||||
char *smtp_client_port; /* client port */
|
char *smtp_client_port; /* client port */
|
||||||
|
char *smtp_server_addr; /* server address */
|
||||||
|
char *smtp_server_port; /* server port */
|
||||||
int client_concurrency; /* per-client */
|
int client_concurrency; /* per-client */
|
||||||
const char *final_reply; /* cause for hanging up */
|
const char *final_reply; /* cause for hanging up */
|
||||||
VSTRING *send_buf; /* pending output */
|
VSTRING *send_buf; /* pending output */
|
||||||
@ -379,7 +382,7 @@ extern HTABLE *psc_client_concurrency; /* per-client concurrency */
|
|||||||
(state)->smtp_client_stream = 0; \
|
(state)->smtp_client_stream = 0; \
|
||||||
psc_check_queue_length--; \
|
psc_check_queue_length--; \
|
||||||
} while (0)
|
} while (0)
|
||||||
extern PSC_STATE *psc_new_session_state(VSTREAM *, const char *, const char *);
|
extern PSC_STATE *psc_new_session_state(VSTREAM *, const char *, const char *, const char *, const char *);
|
||||||
extern void psc_free_session_state(PSC_STATE *);
|
extern void psc_free_session_state(PSC_STATE *);
|
||||||
extern const char *psc_print_state_flags(int, const char *);
|
extern const char *psc_print_state_flags(int, const char *);
|
||||||
|
|
||||||
@ -468,6 +471,14 @@ extern VSTRING *psc_expand_filter;
|
|||||||
extern void psc_expand_init(void);
|
extern void psc_expand_init(void);
|
||||||
extern const char *psc_expand_lookup(const char *, int, char *);
|
extern const char *psc_expand_lookup(const char *, int, char *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* postscreen_endpt.c
|
||||||
|
*/
|
||||||
|
typedef void (*PSC_ENDPT_LOOKUP_FN) (int, VSTREAM *,
|
||||||
|
MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *,
|
||||||
|
MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *);
|
||||||
|
extern void psc_endpt_lookup(VSTREAM *, PSC_ENDPT_LOOKUP_FN);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* postscreen_access emulation.
|
* postscreen_access emulation.
|
||||||
*/
|
*/
|
||||||
|
186
postfix/src/postscreen/postscreen_endpt.c
Normal file
186
postfix/src/postscreen/postscreen_endpt.c
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
/*++
|
||||||
|
/* NAME
|
||||||
|
/* postscreen_endpt 3
|
||||||
|
/* SUMMARY
|
||||||
|
/* look up connection endpoint information
|
||||||
|
/* SYNOPSIS
|
||||||
|
/* #include <postscreen.h>
|
||||||
|
/*
|
||||||
|
/* void psc_endpt_lookup(smtp_client_stream,
|
||||||
|
/* void *lookup_done(status, smtp_client_stream,
|
||||||
|
/* smtp_client_addr, smtp_client_port,
|
||||||
|
/* smtp_server_addr, smtp_server_port))
|
||||||
|
/* VSTRING *smtp_client_stream;
|
||||||
|
/* int status;
|
||||||
|
/* MAI_HOSTADDR_STR *smtp_client_addr;
|
||||||
|
/* MAI_SERVPORT_STR *smtp_client_port;
|
||||||
|
/* MAI_HOSTADDR_STR *smtp_server_addr;
|
||||||
|
/* MAI_SERVPORT_STR *smtp_server_port;
|
||||||
|
/* DESCRIPTION
|
||||||
|
/* psc_endpt_lookup() looks up remote and local connection
|
||||||
|
/* endpoint information through local system calls or through
|
||||||
|
/* a remote proxy protocol. The lookup_done() call-back routine
|
||||||
|
/* passes the result status, address and port information. The
|
||||||
|
/* result status is -1 in case of error, 0 in case of success.
|
||||||
|
/* This function (and its supporting routines) logs a warning
|
||||||
|
/* in case of error, and never communicates with a remote SMTP
|
||||||
|
/* client.
|
||||||
|
/* LICENSE
|
||||||
|
/* .ad
|
||||||
|
/* .fi
|
||||||
|
/* The Secure Mailer license must be distributed with this software.
|
||||||
|
/* AUTHOR(S)
|
||||||
|
/* Wietse Venema
|
||||||
|
/* IBM T.J. Watson Research
|
||||||
|
/* P.O. Box 704
|
||||||
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*--*/
|
||||||
|
|
||||||
|
/* System library. */
|
||||||
|
|
||||||
|
#include <sys_defs.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef STRCASECMP_IN_STRINGS_H
|
||||||
|
#include <strings.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Utility library. */
|
||||||
|
|
||||||
|
#include <msg.h>
|
||||||
|
#include <myaddrinfo.h>
|
||||||
|
#include <vstream.h>
|
||||||
|
#include <inet_proto.h>
|
||||||
|
|
||||||
|
/* Global library. */
|
||||||
|
|
||||||
|
#include <mail_params.h>
|
||||||
|
#include <haproxy_srvr.h>
|
||||||
|
|
||||||
|
/* Application-specific. */
|
||||||
|
|
||||||
|
#include <postscreen.h>
|
||||||
|
#include <postscreen_haproxy.h>
|
||||||
|
|
||||||
|
static INET_PROTO_INFO *proto_info;
|
||||||
|
|
||||||
|
/* psc_sockaddr_to_hostaddr - transform endpoint address and port to string */
|
||||||
|
|
||||||
|
static int psc_sockaddr_to_hostaddr(struct sockaddr * addr_storage,
|
||||||
|
SOCKADDR_SIZE addr_storage_len,
|
||||||
|
MAI_HOSTADDR_STR *addr_buf,
|
||||||
|
MAI_SERVPORT_STR *port_buf,
|
||||||
|
int socktype)
|
||||||
|
{
|
||||||
|
int aierr;
|
||||||
|
|
||||||
|
if ((aierr = sockaddr_to_hostaddr(addr_storage, addr_storage_len,
|
||||||
|
addr_buf, port_buf, socktype)) == 0
|
||||||
|
&& strncasecmp("::ffff:", addr_buf->buf, 7) == 0
|
||||||
|
&& strchr((char *) proto_info->sa_family_list, AF_INET) != 0)
|
||||||
|
memmove(addr_buf->buf, addr_buf->buf + 7,
|
||||||
|
sizeof(addr_buf->buf) - 7);
|
||||||
|
return (aierr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* psc_endpt_local_lookup - look up local system connection information */
|
||||||
|
|
||||||
|
static void psc_endpt_local_lookup(VSTREAM *smtp_client_stream,
|
||||||
|
PSC_ENDPT_LOOKUP_FN lookup_done)
|
||||||
|
{
|
||||||
|
struct sockaddr_storage addr_storage;
|
||||||
|
SOCKADDR_SIZE addr_storage_len = sizeof(addr_storage);
|
||||||
|
int status;
|
||||||
|
MAI_HOSTADDR_STR smtp_client_addr;
|
||||||
|
MAI_SERVPORT_STR smtp_client_port;
|
||||||
|
MAI_HOSTADDR_STR smtp_server_addr;
|
||||||
|
MAI_SERVPORT_STR smtp_server_port;
|
||||||
|
int aierr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look up the remote SMTP client address and port.
|
||||||
|
*/
|
||||||
|
if (getpeername(vstream_fileno(smtp_client_stream), (struct sockaddr *)
|
||||||
|
& addr_storage, &addr_storage_len) < 0) {
|
||||||
|
msg_warn("getpeername: %m -- dropping this connection");
|
||||||
|
status = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert the remote SMTP client address and port to printable form for
|
||||||
|
* logging and access control.
|
||||||
|
*/
|
||||||
|
else if ((aierr = psc_sockaddr_to_hostaddr(
|
||||||
|
(struct sockaddr *) & addr_storage,
|
||||||
|
addr_storage_len, &smtp_client_addr,
|
||||||
|
&smtp_client_port, SOCK_STREAM)) != 0) {
|
||||||
|
msg_warn("cannot convert client address/port to string: %s"
|
||||||
|
" -- dropping this connection",
|
||||||
|
MAI_STRERROR(aierr));
|
||||||
|
status = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look up the local SMTP server address and port.
|
||||||
|
*/
|
||||||
|
else if (getsockname(vstream_fileno(smtp_client_stream),
|
||||||
|
(struct sockaddr *) & addr_storage,
|
||||||
|
&addr_storage_len) < 0) {
|
||||||
|
msg_warn("getsockname: %m -- dropping this connection");
|
||||||
|
status = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert the local SMTP server address and port to printable form for
|
||||||
|
* logging.
|
||||||
|
*/
|
||||||
|
else if ((aierr = psc_sockaddr_to_hostaddr(
|
||||||
|
(struct sockaddr *) & addr_storage,
|
||||||
|
addr_storage_len, &smtp_server_addr,
|
||||||
|
&smtp_server_port, SOCK_STREAM)) != 0) {
|
||||||
|
msg_warn("cannot convert server address/port to string: %s"
|
||||||
|
" -- dropping this connection",
|
||||||
|
MAI_STRERROR(aierr));
|
||||||
|
status = -1;
|
||||||
|
} else {
|
||||||
|
status = 0;
|
||||||
|
}
|
||||||
|
lookup_done(status, smtp_client_stream,
|
||||||
|
&smtp_client_addr, &smtp_client_port,
|
||||||
|
&smtp_server_addr, &smtp_server_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lookup table for available proxy protocols.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
const char *name;
|
||||||
|
void (*endpt_lookup) (VSTREAM *, PSC_ENDPT_LOOKUP_FN);
|
||||||
|
} PSC_ENDPT_LOOKUP_INFO;
|
||||||
|
|
||||||
|
static const PSC_ENDPT_LOOKUP_INFO psc_endpt_lookup_info[] = {
|
||||||
|
DEF_PSC_UPROXY_PROTO, psc_endpt_local_lookup,
|
||||||
|
HAPROXY_PROTO_NAME, psc_endpt_haproxy_lookup,
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* psc_endpt_lookup - look up connection endpoint information */
|
||||||
|
|
||||||
|
void psc_endpt_lookup(VSTREAM *smtp_client_stream,
|
||||||
|
PSC_ENDPT_LOOKUP_FN notify)
|
||||||
|
{
|
||||||
|
const PSC_ENDPT_LOOKUP_INFO *pp;
|
||||||
|
|
||||||
|
if (proto_info == 0)
|
||||||
|
proto_info = inet_proto_info();
|
||||||
|
|
||||||
|
for (pp = psc_endpt_lookup_info; /* see below */ ; pp++) {
|
||||||
|
if (pp->name == 0)
|
||||||
|
msg_fatal("unsupported %s value: %s",
|
||||||
|
VAR_PSC_UPROXY_PROTO, var_psc_uproxy_proto);
|
||||||
|
if (strcmp(var_psc_uproxy_proto, pp->name) == 0) {
|
||||||
|
pp->endpt_lookup(smtp_client_stream, notify);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
194
postfix/src/postscreen/postscreen_haproxy.c
Normal file
194
postfix/src/postscreen/postscreen_haproxy.c
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
/*++
|
||||||
|
/* NAME
|
||||||
|
/* postscreen_haproxy 3
|
||||||
|
/* SUMMARY
|
||||||
|
/* haproxy protocol adapter
|
||||||
|
/* SYNOPSIS
|
||||||
|
/* #include <postscreen_haproxy.h>
|
||||||
|
/*
|
||||||
|
/* void psc_endpt_haproxy_lookup(smtp_client_stream,
|
||||||
|
/* void *lookup_done(status, smtp_client_stream,
|
||||||
|
/* smtp_client_addr, smtp_client_port,
|
||||||
|
/* smtp_server_addr, smtp_server_port))
|
||||||
|
/* VSTRING *smtp_client_stream;
|
||||||
|
/* int status;
|
||||||
|
/* MAI_HOSTADDR_STR *smtp_client_addr;
|
||||||
|
/* MAI_SERVPORT_STR *smtp_client_port;
|
||||||
|
/* MAI_HOSTADDR_STR *smtp_server_addr;
|
||||||
|
/* MAI_SERVPORT_STR *smtp_server_port;
|
||||||
|
/* DESCRIPTION
|
||||||
|
/* psc_endpt_haproxy_lookup() looks up connection endpoint
|
||||||
|
/* information via the haproxy protocol. Arguments and results
|
||||||
|
/* conform to the postscreen_endpt(3) API.
|
||||||
|
/*
|
||||||
|
/* The following summarizes what the Postfix SMTP server expects
|
||||||
|
/* from an up-stream proxy adapter.
|
||||||
|
/* .IP \(bu
|
||||||
|
/* Validate address and port syntax. Permit only protocols
|
||||||
|
/* that are configured with the main.cf:inet_protocols
|
||||||
|
/* setting.
|
||||||
|
/* .IP \(bu
|
||||||
|
/* Convert IPv4-in-IPv6 address syntax to IPv4 form, when both
|
||||||
|
/* IPv4 and IPv6 support are enabled with main.cf:inet_protocols.
|
||||||
|
/* LICENSE
|
||||||
|
/* .ad
|
||||||
|
/* .fi
|
||||||
|
/* The Secure Mailer license must be distributed with this software.
|
||||||
|
/* AUTHOR(S)
|
||||||
|
/* Wietse Venema
|
||||||
|
/* IBM T.J. Watson Research
|
||||||
|
/* P.O. Box 704
|
||||||
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*--*/
|
||||||
|
|
||||||
|
/* System library. */
|
||||||
|
|
||||||
|
#include <sys_defs.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Utility library. */
|
||||||
|
|
||||||
|
#include <msg.h>
|
||||||
|
#include <mymalloc.h>
|
||||||
|
#include <events.h>
|
||||||
|
#include <myaddrinfo.h>
|
||||||
|
#include <vstream.h>
|
||||||
|
#include <vstring.h>
|
||||||
|
#include <stringops.h>
|
||||||
|
|
||||||
|
/* Global library. */
|
||||||
|
|
||||||
|
#include <haproxy_srvr.h>
|
||||||
|
#include <mail_params.h>
|
||||||
|
|
||||||
|
/* Application-specific. */
|
||||||
|
|
||||||
|
#include <postscreen.h>
|
||||||
|
#include <postscreen_haproxy.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Per-session state.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
VSTREAM *stream;
|
||||||
|
PSC_ENDPT_LOOKUP_FN notify;
|
||||||
|
VSTRING *buffer;
|
||||||
|
} PSC_HAPROXY_STATE;
|
||||||
|
|
||||||
|
/* psc_endpt_haproxy_event - read or time event */
|
||||||
|
|
||||||
|
static void psc_endpt_haproxy_event(int event, char *context)
|
||||||
|
{
|
||||||
|
const char *myname = "psc_endpt_haproxy_event";
|
||||||
|
PSC_HAPROXY_STATE *state = (PSC_HAPROXY_STATE *) context;
|
||||||
|
int status = 0;
|
||||||
|
MAI_HOSTADDR_STR smtp_client_addr;
|
||||||
|
MAI_SERVPORT_STR smtp_client_port;
|
||||||
|
MAI_HOSTADDR_STR smtp_server_addr;
|
||||||
|
MAI_SERVPORT_STR smtp_server_port;
|
||||||
|
int last_char = 0;
|
||||||
|
const char *err;
|
||||||
|
VSTRING *escape_buf;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Basic event processing.
|
||||||
|
*/
|
||||||
|
switch (event) {
|
||||||
|
case EVENT_TIME:
|
||||||
|
msg_warn("haproxy read: time limit exceeded");
|
||||||
|
status = -1;
|
||||||
|
break;
|
||||||
|
case EVENT_READ:
|
||||||
|
if ((last_char = VSTREAM_GETC(state->stream)) == VSTREAM_EOF) {
|
||||||
|
if (vstream_ferror(state->stream))
|
||||||
|
msg_warn("haproxy read: %m");
|
||||||
|
else
|
||||||
|
msg_warn("haproxy read: lost connection");
|
||||||
|
status = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (VSTRING_LEN(state->buffer) >= HAPROXY_MAX_LEN) {
|
||||||
|
msg_warn("haproxy read: line too long");
|
||||||
|
status = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
VSTRING_ADDCH(state->buffer, last_char);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse the haproxy line. Note: the haproxy_srvr_parse() routine
|
||||||
|
* performs address protocol checks, address and port syntax checks, and
|
||||||
|
* converts IPv4-in-IPv6 address string syntax (:ffff::1.2.3.4) to IPv4
|
||||||
|
* syntax where permitted by the main.cf:inet_protocols setting.
|
||||||
|
*/
|
||||||
|
if (status == 0 && last_char == '\n') {
|
||||||
|
VSTRING_TERMINATE(state->buffer);
|
||||||
|
if ((err = haproxy_srvr_parse(vstring_str(state->buffer),
|
||||||
|
&smtp_client_addr, &smtp_client_port,
|
||||||
|
&smtp_server_addr, &smtp_server_port)) != 0) {
|
||||||
|
escape_buf = vstring_alloc(HAPROXY_MAX_LEN + 2);
|
||||||
|
escape(escape_buf, vstring_str(state->buffer),
|
||||||
|
VSTRING_LEN(state->buffer));
|
||||||
|
msg_warn("haproxy read: %s: %s", err, vstring_str(escape_buf));
|
||||||
|
status = -1;
|
||||||
|
vstring_free(escape_buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Are we done yet?
|
||||||
|
*/
|
||||||
|
if (status < 0 || last_char == '\n') {
|
||||||
|
PSC_CLEAR_EVENT_REQUEST(vstream_fileno(state->stream),
|
||||||
|
psc_endpt_haproxy_event, context);
|
||||||
|
vstream_control(state->stream,
|
||||||
|
VSTREAM_CTL_BUFSIZE, VSTREAM_BUFSIZE,
|
||||||
|
VSTREAM_CTL_END);
|
||||||
|
state->notify(status, state->stream,
|
||||||
|
&smtp_client_addr, &smtp_client_port,
|
||||||
|
&smtp_server_addr, &smtp_server_port);
|
||||||
|
/* Note: the stream may be closed at this point. */
|
||||||
|
vstring_free(state->buffer);
|
||||||
|
myfree((char *) state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* psc_endpt_haproxy_lookup - event-driven haproxy client */
|
||||||
|
|
||||||
|
void psc_endpt_haproxy_lookup(VSTREAM *stream,
|
||||||
|
PSC_ENDPT_LOOKUP_FN notify)
|
||||||
|
{
|
||||||
|
const char *myname = "psc_endpt_haproxy_lookup";
|
||||||
|
PSC_HAPROXY_STATE *state;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare the per-session state. XXX To improve overload behavior,
|
||||||
|
* maintain a pool of these so that we can reduce memory allocator
|
||||||
|
* activity.
|
||||||
|
*/
|
||||||
|
state = (PSC_HAPROXY_STATE *) mymalloc(sizeof(*state));
|
||||||
|
state->stream = stream;
|
||||||
|
state->notify = notify;
|
||||||
|
state->buffer = vstring_alloc(100);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We don't assume that the haproxy line will be unfragmented. Therefore,
|
||||||
|
* we use read(2) instead of recv(..., MSG_PEEK).
|
||||||
|
*
|
||||||
|
* We must not read(2) past the <CR><LF> that terminates the haproxy line.
|
||||||
|
* Therefore we force one-character read(2) calls.
|
||||||
|
*
|
||||||
|
* We want to (eventually) build this on top of a reusable line read
|
||||||
|
* routine, once we have figured out an easy-to-use and efficient API.
|
||||||
|
*/
|
||||||
|
vstream_control(stream, VSTREAM_CTL_BUFSIZE, 1, VSTREAM_CTL_END);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read the haproxy line.
|
||||||
|
*/
|
||||||
|
PSC_READ_EVENT_REQUEST(vstream_fileno(stream), psc_endpt_haproxy_event,
|
||||||
|
(char *) state, var_psc_uproxy_tmout);
|
||||||
|
}
|
25
postfix/src/postscreen/postscreen_haproxy.h
Normal file
25
postfix/src/postscreen/postscreen_haproxy.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*++
|
||||||
|
/* NAME
|
||||||
|
/* postscreen_haproxy 3h
|
||||||
|
/* SUMMARY
|
||||||
|
/* postscreen haproxy protocol support
|
||||||
|
/* SYNOPSIS
|
||||||
|
/* #include <postscreen_haproxy.h>
|
||||||
|
/* DESCRIPTION
|
||||||
|
/* .nf
|
||||||
|
|
||||||
|
/*
|
||||||
|
* haproxy protocol interface.
|
||||||
|
*/
|
||||||
|
extern void psc_endpt_haproxy_lookup(VSTREAM *, PSC_ENDPT_LOOKUP_FN);
|
||||||
|
|
||||||
|
/* LICENSE
|
||||||
|
/* .ad
|
||||||
|
/* .fi
|
||||||
|
/* The Secure Mailer license must be distributed with this software.
|
||||||
|
/* AUTHOR(S)
|
||||||
|
/* Wietse Venema
|
||||||
|
/* IBM T.J. Watson Research
|
||||||
|
/* P.O. Box 704
|
||||||
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*--*/
|
@ -61,11 +61,14 @@
|
|||||||
#include <msg.h>
|
#include <msg.h>
|
||||||
#include <iostuff.h>
|
#include <iostuff.h>
|
||||||
#include <connect.h>
|
#include <connect.h>
|
||||||
|
#include <attr.h>
|
||||||
|
#include <vstream.h>
|
||||||
|
|
||||||
/* Global library. */
|
/* Global library. */
|
||||||
|
|
||||||
#include <mail_params.h>
|
#include <mail_params.h>
|
||||||
#include <smtp_reply_footer.h>
|
#include <smtp_reply_footer.h>
|
||||||
|
#include <mail_proto.h>
|
||||||
|
|
||||||
/* Application-specific. */
|
/* Application-specific. */
|
||||||
|
|
||||||
@ -163,6 +166,8 @@ void psc_send_socket(PSC_STATE *state)
|
|||||||
{
|
{
|
||||||
const char *myname = "psc_send_socket";
|
const char *myname = "psc_send_socket";
|
||||||
int server_fd;
|
int server_fd;
|
||||||
|
int pass_err;
|
||||||
|
VSTREAM *fp;
|
||||||
|
|
||||||
if (msg_verbose > 1)
|
if (msg_verbose > 1)
|
||||||
msg_info("%s: sq=%d cq=%d send socket %d from [%s]:%s",
|
msg_info("%s: sq=%d cq=%d send socket %d from [%s]:%s",
|
||||||
@ -187,7 +192,7 @@ void psc_send_socket(PSC_STATE *state)
|
|||||||
* Postfix-specific.
|
* Postfix-specific.
|
||||||
*/
|
*/
|
||||||
if ((server_fd =
|
if ((server_fd =
|
||||||
PASS_CONNECT(psc_smtpd_service_name, NON_BLOCKING,
|
LOCAL_CONNECT(psc_smtpd_service_name, NON_BLOCKING,
|
||||||
PSC_SEND_SOCK_CONNECT_TIMEOUT)) < 0) {
|
PSC_SEND_SOCK_CONNECT_TIMEOUT)) < 0) {
|
||||||
msg_warn("cannot connect to service %s: %m", psc_smtpd_service_name);
|
msg_warn("cannot connect to service %s: %m", psc_smtpd_service_name);
|
||||||
if (state->flags & PSC_STATE_FLAG_PREGR_TODO) {
|
if (state->flags & PSC_STATE_FLAG_PREGR_TODO) {
|
||||||
@ -198,8 +203,19 @@ void psc_send_socket(PSC_STATE *state)
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (LOCAL_SEND_FD(server_fd,
|
/* XXX Note: no dummy read between LOCAL_SEND_FD() and attr_print(). */
|
||||||
vstream_fileno(state->smtp_client_stream)) < 0) {
|
fp = vstream_fdopen(server_fd, O_RDWR);
|
||||||
|
pass_err =
|
||||||
|
(LOCAL_SEND_FD(server_fd,
|
||||||
|
vstream_fileno(state->smtp_client_stream)) < 0
|
||||||
|
|| (attr_print(fp, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_ACT_CLIENT_ADDR, state->smtp_client_addr,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_ACT_CLIENT_PORT, state->smtp_client_port,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_ACT_SERVER_ADDR, state->smtp_server_addr,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_ACT_SERVER_PORT, state->smtp_server_port,
|
||||||
|
ATTR_TYPE_END) || vstream_fflush(fp)));
|
||||||
|
(void) vstream_fdclose(fp);
|
||||||
|
if (pass_err != 0) {
|
||||||
msg_warn("cannot pass connection to service %s: %m",
|
msg_warn("cannot pass connection to service %s: %m",
|
||||||
psc_smtpd_service_name);
|
psc_smtpd_service_name);
|
||||||
(void) close(server_fd);
|
(void) close(server_fd);
|
||||||
|
@ -6,10 +6,13 @@
|
|||||||
/* SYNOPSIS
|
/* SYNOPSIS
|
||||||
/* #include <postscreen.h>
|
/* #include <postscreen.h>
|
||||||
/*
|
/*
|
||||||
/* PSC_STATE *psc_new_session_state(stream, addr, port)
|
/* PSC_STATE *psc_new_session_state(stream, client_addr, client_port,
|
||||||
|
/* server_addr, server_port)
|
||||||
/* VSTREAM *stream;
|
/* VSTREAM *stream;
|
||||||
/* const char *addr;
|
/* const char *client_addr;
|
||||||
/* const char *port;
|
/* const char *client_port;
|
||||||
|
/* const char *server_addr;
|
||||||
|
/* const char *server_port;
|
||||||
/*
|
/*
|
||||||
/* void psc_free_session_state(state)
|
/* void psc_free_session_state(state)
|
||||||
/* PSC_STATE *state;
|
/* PSC_STATE *state;
|
||||||
@ -140,8 +143,10 @@
|
|||||||
/* psc_new_session_state - fill in connection state for event processing */
|
/* psc_new_session_state - fill in connection state for event processing */
|
||||||
|
|
||||||
PSC_STATE *psc_new_session_state(VSTREAM *stream,
|
PSC_STATE *psc_new_session_state(VSTREAM *stream,
|
||||||
const char *addr,
|
const char *client_addr,
|
||||||
const char *port)
|
const char *client_port,
|
||||||
|
const char *server_addr,
|
||||||
|
const char *server_port)
|
||||||
{
|
{
|
||||||
PSC_STATE *state;
|
PSC_STATE *state;
|
||||||
HTABLE_INFO *ht;
|
HTABLE_INFO *ht;
|
||||||
@ -151,8 +156,10 @@ PSC_STATE *psc_new_session_state(VSTREAM *stream,
|
|||||||
if ((state->smtp_client_stream = stream) != 0)
|
if ((state->smtp_client_stream = stream) != 0)
|
||||||
psc_check_queue_length++;
|
psc_check_queue_length++;
|
||||||
state->smtp_server_fd = (-1);
|
state->smtp_server_fd = (-1);
|
||||||
state->smtp_client_addr = mystrdup(addr);
|
state->smtp_client_addr = mystrdup(client_addr);
|
||||||
state->smtp_client_port = mystrdup(port);
|
state->smtp_client_port = mystrdup(client_port);
|
||||||
|
state->smtp_server_addr = mystrdup(server_addr);
|
||||||
|
state->smtp_server_port = mystrdup(server_port);
|
||||||
state->send_buf = vstring_alloc(100);
|
state->send_buf = vstring_alloc(100);
|
||||||
state->test_name = "TEST NAME HERE";
|
state->test_name = "TEST NAME HERE";
|
||||||
state->dnsbl_reply = 0;
|
state->dnsbl_reply = 0;
|
||||||
@ -180,8 +187,8 @@ PSC_STATE *psc_new_session_state(VSTREAM *stream,
|
|||||||
/*
|
/*
|
||||||
* Update the per-client session count.
|
* Update the per-client session count.
|
||||||
*/
|
*/
|
||||||
if ((ht = htable_locate(psc_client_concurrency, addr)) == 0)
|
if ((ht = htable_locate(psc_client_concurrency, client_addr)) == 0)
|
||||||
ht = htable_enter(psc_client_concurrency, addr, (char *) 0);
|
ht = htable_enter(psc_client_concurrency, client_addr, (char *) 0);
|
||||||
ht->value += 1;
|
ht->value += 1;
|
||||||
state->client_concurrency = CAST_CHAR_PTR_TO_INT(ht->value);
|
state->client_concurrency = CAST_CHAR_PTR_TO_INT(ht->value);
|
||||||
|
|
||||||
@ -218,6 +225,8 @@ void psc_free_session_state(PSC_STATE *state)
|
|||||||
state->send_buf = vstring_free(state->send_buf);
|
state->send_buf = vstring_free(state->send_buf);
|
||||||
myfree(state->smtp_client_addr);
|
myfree(state->smtp_client_addr);
|
||||||
myfree(state->smtp_client_port);
|
myfree(state->smtp_client_port);
|
||||||
|
myfree(state->smtp_server_addr);
|
||||||
|
myfree(state->smtp_server_port);
|
||||||
if (state->dnsbl_reply)
|
if (state->dnsbl_reply)
|
||||||
vstring_free(state->dnsbl_reply);
|
vstring_free(state->dnsbl_reply);
|
||||||
if (state->helo_name)
|
if (state->helo_name)
|
||||||
|
@ -2,11 +2,11 @@ SHELL = /bin/sh
|
|||||||
SRCS = smtpd.c smtpd_token.c smtpd_check.c smtpd_chat.c smtpd_state.c \
|
SRCS = smtpd.c smtpd_token.c smtpd_check.c smtpd_chat.c smtpd_state.c \
|
||||||
smtpd_peer.c smtpd_sasl_proto.c smtpd_sasl_glue.c smtpd_proxy.c \
|
smtpd_peer.c smtpd_sasl_proto.c smtpd_sasl_glue.c smtpd_proxy.c \
|
||||||
smtpd_xforward.c smtpd_dsn_fix.c smtpd_milter.c smtpd_resolve.c \
|
smtpd_xforward.c smtpd_dsn_fix.c smtpd_milter.c smtpd_resolve.c \
|
||||||
smtpd_expand.c
|
smtpd_expand.c smtpd_haproxy.c
|
||||||
OBJS = smtpd.o smtpd_token.o smtpd_check.o smtpd_chat.o smtpd_state.o \
|
OBJS = smtpd.o smtpd_token.o smtpd_check.o smtpd_chat.o smtpd_state.o \
|
||||||
smtpd_peer.o smtpd_sasl_proto.o smtpd_sasl_glue.o smtpd_proxy.o \
|
smtpd_peer.o smtpd_sasl_proto.o smtpd_sasl_glue.o smtpd_proxy.o \
|
||||||
smtpd_xforward.o smtpd_dsn_fix.o smtpd_milter.o smtpd_resolve.o \
|
smtpd_xforward.o smtpd_dsn_fix.o smtpd_milter.o smtpd_resolve.o \
|
||||||
smtpd_expand.o
|
smtpd_expand.o smtpd_haproxy.o
|
||||||
HDRS = smtpd_token.h smtpd_check.h smtpd_chat.h smtpd_sasl_proto.h \
|
HDRS = smtpd_token.h smtpd_check.h smtpd_chat.h smtpd_sasl_proto.h \
|
||||||
smtpd_sasl_glue.h smtpd_proxy.h smtpd_dsn_fix.h smtpd_milter.h \
|
smtpd_sasl_glue.h smtpd_proxy.h smtpd_dsn_fix.h smtpd_milter.h \
|
||||||
smtpd_resolve.h smtpd_expand.h
|
smtpd_resolve.h smtpd_expand.h
|
||||||
@ -346,6 +346,28 @@ smtpd_expand.o: ../../include/vstring.h
|
|||||||
smtpd_expand.o: smtpd.h
|
smtpd_expand.o: smtpd.h
|
||||||
smtpd_expand.o: smtpd_expand.c
|
smtpd_expand.o: smtpd_expand.c
|
||||||
smtpd_expand.o: smtpd_expand.h
|
smtpd_expand.o: smtpd_expand.h
|
||||||
|
smtpd_haproxy.o: ../../include/argv.h
|
||||||
|
smtpd_haproxy.o: ../../include/attr.h
|
||||||
|
smtpd_haproxy.o: ../../include/haproxy_srvr.h
|
||||||
|
smtpd_haproxy.o: ../../include/mail_params.h
|
||||||
|
smtpd_haproxy.o: ../../include/mail_stream.h
|
||||||
|
smtpd_haproxy.o: ../../include/milter.h
|
||||||
|
smtpd_haproxy.o: ../../include/msg.h
|
||||||
|
smtpd_haproxy.o: ../../include/myaddrinfo.h
|
||||||
|
smtpd_haproxy.o: ../../include/mymalloc.h
|
||||||
|
smtpd_haproxy.o: ../../include/name_code.h
|
||||||
|
smtpd_haproxy.o: ../../include/name_mask.h
|
||||||
|
smtpd_haproxy.o: ../../include/smtp_stream.h
|
||||||
|
smtpd_haproxy.o: ../../include/stringops.h
|
||||||
|
smtpd_haproxy.o: ../../include/sys_defs.h
|
||||||
|
smtpd_haproxy.o: ../../include/tls.h
|
||||||
|
smtpd_haproxy.o: ../../include/valid_hostname.h
|
||||||
|
smtpd_haproxy.o: ../../include/valid_mailhost_addr.h
|
||||||
|
smtpd_haproxy.o: ../../include/vbuf.h
|
||||||
|
smtpd_haproxy.o: ../../include/vstream.h
|
||||||
|
smtpd_haproxy.o: ../../include/vstring.h
|
||||||
|
smtpd_haproxy.o: smtpd.h
|
||||||
|
smtpd_haproxy.o: smtpd_haproxy.c
|
||||||
smtpd_milter.o: ../../include/argv.h
|
smtpd_milter.o: ../../include/argv.h
|
||||||
smtpd_milter.o: ../../include/attr.h
|
smtpd_milter.o: ../../include/attr.h
|
||||||
smtpd_milter.o: ../../include/mail_params.h
|
smtpd_milter.o: ../../include/mail_params.h
|
||||||
@ -370,6 +392,8 @@ smtpd_milter.o: smtpd_resolve.h
|
|||||||
smtpd_milter.o: smtpd_sasl_glue.h
|
smtpd_milter.o: smtpd_sasl_glue.h
|
||||||
smtpd_peer.o: ../../include/argv.h
|
smtpd_peer.o: ../../include/argv.h
|
||||||
smtpd_peer.o: ../../include/attr.h
|
smtpd_peer.o: ../../include/attr.h
|
||||||
|
smtpd_peer.o: ../../include/haproxy_srvr.h
|
||||||
|
smtpd_peer.o: ../../include/htable.h
|
||||||
smtpd_peer.o: ../../include/inet_proto.h
|
smtpd_peer.o: ../../include/inet_proto.h
|
||||||
smtpd_peer.o: ../../include/iostuff.h
|
smtpd_peer.o: ../../include/iostuff.h
|
||||||
smtpd_peer.o: ../../include/mail_params.h
|
smtpd_peer.o: ../../include/mail_params.h
|
||||||
|
@ -154,6 +154,16 @@
|
|||||||
/* at all, or rewrite message headers and update incomplete addresses
|
/* at all, or rewrite message headers and update incomplete addresses
|
||||||
/* with the domain specified in the remote_header_rewrite_domain
|
/* with the domain specified in the remote_header_rewrite_domain
|
||||||
/* parameter.
|
/* parameter.
|
||||||
|
/* BEFORE-SMTPD PROXY AGENT
|
||||||
|
/* .ad
|
||||||
|
/* .fi
|
||||||
|
/* Available in Postfix version 2.10 and later:
|
||||||
|
/* .IP "\fBsmtpd_upstream_proxy_protocol (empty)\fR"
|
||||||
|
/* The name of the proxy protocol used by an optional before-smtpd
|
||||||
|
/* proxy agent.
|
||||||
|
/* .IP "\fBsmtpd_upstream_proxy_timeout (5s)\fR"
|
||||||
|
/* The time limit for the proxy protocol specified with the
|
||||||
|
/* smtpd_upstream_proxy_protocol parameter.
|
||||||
/* AFTER QUEUE EXTERNAL CONTENT INSPECTION CONTROLS
|
/* AFTER QUEUE EXTERNAL CONTENT INSPECTION CONTROLS
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
@ -1291,6 +1301,9 @@ char *var_tlsproxy_service;
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
char *var_smtpd_uproxy_proto;
|
||||||
|
int var_smtpd_uproxy_tmout;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Silly little macros.
|
* Silly little macros.
|
||||||
*/
|
*/
|
||||||
@ -4924,6 +4937,7 @@ static void smtpd_service(VSTREAM *stream, char *service, char **argv)
|
|||||||
/*
|
/*
|
||||||
* Provide the SMTP service.
|
* Provide the SMTP service.
|
||||||
*/
|
*/
|
||||||
|
if ((state.flags & SMTPD_FLAG_HANGUP) == 0)
|
||||||
smtpd_proto(&state);
|
smtpd_proto(&state);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -5273,6 +5287,7 @@ int main(int argc, char **argv)
|
|||||||
VAR_MILT_CMD_TIME, DEF_MILT_CMD_TIME, &var_milt_cmd_time, 1, 0,
|
VAR_MILT_CMD_TIME, DEF_MILT_CMD_TIME, &var_milt_cmd_time, 1, 0,
|
||||||
VAR_MILT_MSG_TIME, DEF_MILT_MSG_TIME, &var_milt_msg_time, 1, 0,
|
VAR_MILT_MSG_TIME, DEF_MILT_MSG_TIME, &var_milt_msg_time, 1, 0,
|
||||||
VAR_VERIFY_SENDER_TTL, DEF_VERIFY_SENDER_TTL, &var_verify_sender_ttl, 0, 0,
|
VAR_VERIFY_SENDER_TTL, DEF_VERIFY_SENDER_TTL, &var_verify_sender_ttl, 0, 0,
|
||||||
|
VAR_SMTPD_UPROXY_TMOUT, DEF_SMTPD_UPROXY_TMOUT, &var_smtpd_uproxy_tmout, 1, 0,
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
static const CONFIG_BOOL_TABLE bool_table[] = {
|
static const CONFIG_BOOL_TABLE bool_table[] = {
|
||||||
@ -5401,6 +5416,7 @@ int main(int argc, char **argv)
|
|||||||
VAR_TLSPROXY_SERVICE, DEF_TLSPROXY_SERVICE, &var_tlsproxy_service, 1, 0,
|
VAR_TLSPROXY_SERVICE, DEF_TLSPROXY_SERVICE, &var_tlsproxy_service, 1, 0,
|
||||||
#endif
|
#endif
|
||||||
VAR_SMTPD_ACL_PERM_LOG, DEF_SMTPD_ACL_PERM_LOG, &var_smtpd_acl_perm_log, 0, 0,
|
VAR_SMTPD_ACL_PERM_LOG, DEF_SMTPD_ACL_PERM_LOG, &var_smtpd_acl_perm_log, 0, 0,
|
||||||
|
VAR_SMTPD_UPROXY_PROTO, DEF_SMTPD_UPROXY_PROTO, &var_smtpd_uproxy_proto, 0, 0,
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
static const CONFIG_RAW_TABLE raw_table[] = {
|
static const CONFIG_RAW_TABLE raw_table[] = {
|
||||||
|
@ -79,7 +79,9 @@ typedef struct {
|
|||||||
char *namaddr; /* name[address]:port */
|
char *namaddr; /* name[address]:port */
|
||||||
char *rfc_addr; /* address for RFC 2821 */
|
char *rfc_addr; /* address for RFC 2821 */
|
||||||
int addr_family; /* address family */
|
int addr_family; /* address family */
|
||||||
|
char *dest_addr; /* for Dovecot AUTH */
|
||||||
struct sockaddr_storage sockaddr; /* binary client endpoint */
|
struct sockaddr_storage sockaddr; /* binary client endpoint */
|
||||||
|
SOCKADDR_SIZE sockaddr_len; /* binary client endpoint */
|
||||||
int name_status; /* 2=ok 4=soft 5=hard 6=forged */
|
int name_status; /* 2=ok 4=soft 5=hard 6=forged */
|
||||||
int reverse_name_status; /* 2=ok 4=soft 5=hard */
|
int reverse_name_status; /* 2=ok 4=soft 5=hard */
|
||||||
int conn_count; /* connections from this client */
|
int conn_count; /* connections from this client */
|
||||||
@ -308,6 +310,7 @@ extern void smtpd_state_reset(SMTPD_STATE *);
|
|||||||
*/
|
*/
|
||||||
extern void smtpd_peer_init(SMTPD_STATE *state);
|
extern void smtpd_peer_init(SMTPD_STATE *state);
|
||||||
extern void smtpd_peer_reset(SMTPD_STATE *state);
|
extern void smtpd_peer_reset(SMTPD_STATE *state);
|
||||||
|
extern int smtpd_peer_from_haproxy(SMTPD_STATE *state);
|
||||||
|
|
||||||
#define SMTPD_PEER_CODE_OK 2
|
#define SMTPD_PEER_CODE_OK 2
|
||||||
#define SMTPD_PEER_CODE_TEMP 4
|
#define SMTPD_PEER_CODE_TEMP 4
|
||||||
|
144
postfix/src/smtpd/smtpd_haproxy.c
Normal file
144
postfix/src/smtpd/smtpd_haproxy.c
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
/*++
|
||||||
|
/* NAME
|
||||||
|
/* smtpd_haproxy 3
|
||||||
|
/* SUMMARY
|
||||||
|
/* Postfix SMTP server haproxy adapter
|
||||||
|
/* SYNOPSIS
|
||||||
|
/* #include "smtpd.h"
|
||||||
|
/*
|
||||||
|
/* int smtpd_peer_from_haproxy(state)
|
||||||
|
/* SMTPD_STATE *state;
|
||||||
|
/* DESCRIPTION
|
||||||
|
/* smtpd_peer_from_haproxy() receives endpoint address and
|
||||||
|
/* port information via the haproxy protocol.
|
||||||
|
/*
|
||||||
|
/* The following summarizes what the Postfix SMTP server expects
|
||||||
|
/* from an up-stream proxy adapter.
|
||||||
|
/* .IP \(bu
|
||||||
|
/* Validate address and port syntax. Permit only protocols
|
||||||
|
/* that are configured with the main.cf:inet_protocols
|
||||||
|
/* setting.
|
||||||
|
/* .IP \(bu
|
||||||
|
/* Convert IPv4-in-IPv6 address syntax to IPv4 syntax, when
|
||||||
|
/* both IPv4 and IPv6 support are enabled with main.cf:inet_protocols.
|
||||||
|
/* .IP \(bu
|
||||||
|
/* Update the following session context fields: addr, port,
|
||||||
|
/* rfc_addr, addr_family, dest_addr. The addr_family field
|
||||||
|
/* applies to the client address.
|
||||||
|
/* .IP \(bu
|
||||||
|
/* Dynamically allocate storage for string information with
|
||||||
|
/* mystrdup(). In case of error, leave unassigned string fields
|
||||||
|
/* at their initial zero value.
|
||||||
|
/* .IP \(bu
|
||||||
|
/* Log warnings in case of data format error.
|
||||||
|
/* .PP
|
||||||
|
/* Arguments:
|
||||||
|
/* .IP state
|
||||||
|
/* Session context.
|
||||||
|
/* DIAGNOSTICS
|
||||||
|
/* Warnings: I/O errors, malformed haproxy line.
|
||||||
|
/*
|
||||||
|
/* The result value is 0 in case of success, -1 in case of
|
||||||
|
/* error.
|
||||||
|
/* LICENSE
|
||||||
|
/* .ad
|
||||||
|
/* .fi
|
||||||
|
/* The Secure Mailer license must be distributed with this software.
|
||||||
|
/* AUTHOR(S)
|
||||||
|
/* Wietse Venema
|
||||||
|
/* IBM T.J. Watson Research
|
||||||
|
/* P.O. Box 704
|
||||||
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*--*/
|
||||||
|
|
||||||
|
/* System library. */
|
||||||
|
|
||||||
|
#include <sys_defs.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
/* Utility library. */
|
||||||
|
|
||||||
|
#include <msg.h>
|
||||||
|
#include <myaddrinfo.h>
|
||||||
|
#include <mymalloc.h>
|
||||||
|
#include <stringops.h>
|
||||||
|
|
||||||
|
/* Global library. */
|
||||||
|
|
||||||
|
#include <smtp_stream.h>
|
||||||
|
#include <mail_params.h>
|
||||||
|
#include <valid_mailhost_addr.h>
|
||||||
|
#include <haproxy_srvr.h>
|
||||||
|
|
||||||
|
/* Application-specific. */
|
||||||
|
|
||||||
|
#include <smtpd.h>
|
||||||
|
|
||||||
|
/* SLMs. */
|
||||||
|
|
||||||
|
#define STR(x) vstring_str(x)
|
||||||
|
#define LEN(x) VSTRING_LEN(x)
|
||||||
|
|
||||||
|
/* smtpd_peer_from_haproxy - initialize peer information from haproxy */
|
||||||
|
|
||||||
|
int smtpd_peer_from_haproxy(SMTPD_STATE *state)
|
||||||
|
{
|
||||||
|
const char *myname = "smtpd_peer_from_haproxy";
|
||||||
|
MAI_HOSTADDR_STR smtp_client_addr;
|
||||||
|
MAI_SERVPORT_STR smtp_client_port;
|
||||||
|
MAI_HOSTADDR_STR smtp_server_addr;
|
||||||
|
MAI_SERVPORT_STR smtp_server_port;
|
||||||
|
const char *proxy_err;
|
||||||
|
int io_err;
|
||||||
|
VSTRING *escape_buf;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: the haproxy_srvr_parse() routine performs address protocol
|
||||||
|
* checks, address and port syntax checks, and converts IPv4-in-IPv6
|
||||||
|
* address string syntax (:ffff::1.2.3.4) to IPv4 syntax where permitted
|
||||||
|
* by the main.cf:inet_protocols setting, but logs no warnings.
|
||||||
|
*/
|
||||||
|
#define ENABLE_DEADLINE 1
|
||||||
|
|
||||||
|
smtp_stream_setup(state->client, var_smtpd_uproxy_tmout, ENABLE_DEADLINE);
|
||||||
|
switch (io_err = vstream_setjmp(state->client)) {
|
||||||
|
default:
|
||||||
|
msg_panic("%s: unhandled I/O error %d", myname, io_err);
|
||||||
|
case SMTP_ERR_EOF:
|
||||||
|
msg_warn("haproxy read: unexpected EOF");
|
||||||
|
return (-1);
|
||||||
|
case SMTP_ERR_TIME:
|
||||||
|
msg_warn("haproxy read: timeout error");
|
||||||
|
return (-1);
|
||||||
|
case 0:
|
||||||
|
if (smtp_get(state->buffer, state->client, HAPROXY_MAX_LEN,
|
||||||
|
SMTP_GET_FLAG_NONE) != '\n') {
|
||||||
|
msg_warn("haproxy line > %d characters", HAPROXY_MAX_LEN);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if ((proxy_err = haproxy_srvr_parse(STR(state->buffer),
|
||||||
|
&smtp_client_addr, &smtp_client_port,
|
||||||
|
&smtp_server_addr, &smtp_server_port)) != 0) {
|
||||||
|
escape_buf = vstring_alloc(HAPROXY_MAX_LEN + 2);
|
||||||
|
escape(escape_buf, STR(state->buffer), LEN(state->buffer));
|
||||||
|
msg_warn("haproxy read: %s: %s", proxy_err, STR(escape_buf));
|
||||||
|
vstring_free(escape_buf);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
state->addr = mystrdup(smtp_client_addr.buf);
|
||||||
|
if (strrchr(state->addr, ':') != 0) {
|
||||||
|
state->rfc_addr = concatenate(IPV6_COL, state->addr, (char *) 0);
|
||||||
|
state->addr_family = AF_INET6;
|
||||||
|
} else {
|
||||||
|
state->rfc_addr = mystrdup(state->addr);
|
||||||
|
state->addr_family = AF_INET;
|
||||||
|
}
|
||||||
|
state->port = mystrdup(smtp_client_port.buf);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Avoid surprises in the Dovecot authentication server.
|
||||||
|
*/
|
||||||
|
state->dest_addr = mystrdup(smtp_server_addr.buf);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,9 @@
|
|||||||
/* Where information is unavailable, the name and/or address
|
/* Where information is unavailable, the name and/or address
|
||||||
/* are set to "unknown".
|
/* are set to "unknown".
|
||||||
/*
|
/*
|
||||||
|
/* Alternatively, the peer address and port may be obtained
|
||||||
|
/* from a proxy server.
|
||||||
|
/*
|
||||||
/* This module uses the local name service via getaddrinfo()
|
/* This module uses the local name service via getaddrinfo()
|
||||||
/* and getnameinfo(). It does not query the DNS directly.
|
/* and getnameinfo(). It does not query the DNS directly.
|
||||||
/*
|
/*
|
||||||
@ -45,6 +48,8 @@
|
|||||||
/* .IP rfc_addr
|
/* .IP rfc_addr
|
||||||
/* String of the form "ipv4addr" or "ipv6:ipv6addr" for use
|
/* String of the form "ipv4addr" or "ipv6:ipv6addr" for use
|
||||||
/* in Received: message headers.
|
/* in Received: message headers.
|
||||||
|
/* .IP dest_addr
|
||||||
|
/* Server address, used by the Dovecot authentication server.
|
||||||
/* .IP name_status
|
/* .IP name_status
|
||||||
/* The name_status result field specifies how the name
|
/* The name_status result field specifies how the name
|
||||||
/* information should be interpreted:
|
/* information should be interpreted:
|
||||||
@ -104,6 +109,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <htable.h>
|
||||||
|
|
||||||
/* Utility library. */
|
/* Utility library. */
|
||||||
|
|
||||||
@ -120,75 +126,51 @@
|
|||||||
#include <mail_proto.h>
|
#include <mail_proto.h>
|
||||||
#include <valid_mailhost_addr.h>
|
#include <valid_mailhost_addr.h>
|
||||||
#include <mail_params.h>
|
#include <mail_params.h>
|
||||||
|
#include <haproxy_srvr.h>
|
||||||
|
|
||||||
/* Application-specific. */
|
/* Application-specific. */
|
||||||
|
|
||||||
#include "smtpd.h"
|
#include "smtpd.h"
|
||||||
|
|
||||||
/* smtpd_peer_init - initialize peer information */
|
static INET_PROTO_INFO *proto_info;
|
||||||
|
|
||||||
void smtpd_peer_init(SMTPD_STATE *state)
|
|
||||||
{
|
|
||||||
const char *myname = "smtpd_peer_init";
|
|
||||||
SOCKADDR_SIZE sa_length;
|
|
||||||
struct sockaddr *sa;
|
|
||||||
INET_PROTO_INFO *proto_info = inet_proto_info();
|
|
||||||
|
|
||||||
sa = (struct sockaddr *) & (state->sockaddr);
|
|
||||||
sa_length = sizeof(state->sockaddr);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Look up the peer address information.
|
|
||||||
*
|
|
||||||
* XXX If we make local endpoint (getsockname) information available to
|
* XXX If we make local endpoint (getsockname) information available to
|
||||||
* Milter applications as {if_name} and {if_addr}, then we also must be
|
* Milter applications as {if_name} and {if_addr}, then we also must be able
|
||||||
* able to provide this via the XCLIENT command for Milter testing.
|
* to provide this via the XCLIENT command for Milter testing.
|
||||||
*
|
*
|
||||||
* XXX If we make local or remote port information available to policy
|
* XXX If we make local port information available to policy servers or Milter
|
||||||
* servers or Milter applications, then we must also make this testable
|
* applications, then we must also make this testable with the XCLIENT
|
||||||
* with the XCLIENT command, otherwise there will be confusion.
|
* command, otherwise there will be confusion.
|
||||||
*
|
*
|
||||||
* XXX If we make local or remote port information available via logging,
|
* XXX If we make local port information available via logging, then we must
|
||||||
* then we must also support these attributes with the XFORWARD command.
|
* also support these attributes with the XFORWARD command.
|
||||||
*
|
*
|
||||||
* XXX If support were to be added for Milter applications in down-stream
|
* XXX If support were to be added for Milter applications in down-stream MTAs,
|
||||||
* MTAs, then consistency demands that we propagate a lot of Sendmail
|
* then consistency demands that we propagate a lot of Sendmail macro
|
||||||
* macro information via the XFORWARD command. Otherwise we could end up
|
* information via the XFORWARD command. Otherwise we could end up with a
|
||||||
* with a very confusing situation.
|
* very confusing situation.
|
||||||
*/
|
*/
|
||||||
if (getpeername(vstream_fileno(state->client), sa, &sa_length) >= 0) {
|
|
||||||
errno = 0;
|
/* smtpd_peer_sockaddr_to_hostaddr - client address/port to printable form */
|
||||||
}
|
|
||||||
|
static int smtpd_peer_sockaddr_to_hostaddr(SMTPD_STATE *state)
|
||||||
|
{
|
||||||
|
const char *myname = "smtpd_peer_sockaddr_to_hostaddr";
|
||||||
|
struct sockaddr *sa = (struct sockaddr *) & (state->sockaddr);
|
||||||
|
SOCKADDR_SIZE sa_length = state->sockaddr_len;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If peer went away, give up.
|
* XXX If we're given an IPv6 (or IPv4) connection from, e.g., inetd,
|
||||||
|
* while Postfix IPv6 (or IPv4) support is turned off, don't (skip to the
|
||||||
|
* final else clause, pretend the origin is localhost[127.0.0.1], and
|
||||||
|
* become an open relay).
|
||||||
*/
|
*/
|
||||||
if (errno != 0 && errno != ENOTSOCK) {
|
if (sa->sa_family == AF_INET
|
||||||
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
|
|
||||||
state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
|
|
||||||
state->addr = mystrdup(CLIENT_ADDR_UNKNOWN);
|
|
||||||
state->rfc_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
|
|
||||||
state->addr_family = AF_UNSPEC;
|
|
||||||
state->name_status = SMTPD_PEER_CODE_PERM;
|
|
||||||
state->reverse_name_status = SMTPD_PEER_CODE_PERM;
|
|
||||||
state->port = mystrdup(CLIENT_PORT_UNKNOWN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert the client address to printable address and hostname.
|
|
||||||
*
|
|
||||||
* XXX If we're given an IPv6 (or IPv4) connection from, e.g., inetd, while
|
|
||||||
* Postfix IPv6 (or IPv4) support is turned off, don't (skip to the final
|
|
||||||
* else clause, pretend the origin is localhost[127.0.0.1], and become an
|
|
||||||
* open relay).
|
|
||||||
*/
|
|
||||||
else if (errno == 0
|
|
||||||
&& (sa->sa_family == AF_INET
|
|
||||||
#ifdef AF_INET6
|
#ifdef AF_INET6
|
||||||
|| sa->sa_family == AF_INET6
|
|| sa->sa_family == AF_INET6
|
||||||
#endif
|
#endif
|
||||||
)) {
|
) {
|
||||||
MAI_HOSTNAME_STR client_name;
|
|
||||||
MAI_HOSTADDR_STR client_addr;
|
MAI_HOSTADDR_STR client_addr;
|
||||||
MAI_SERVPORT_STR client_port;
|
MAI_SERVPORT_STR client_port;
|
||||||
int aierr;
|
int aierr;
|
||||||
@ -290,13 +272,32 @@ void smtpd_peer_init(SMTPD_STATE *state)
|
|||||||
state->rfc_addr = mystrdup(client_addr.buf);
|
state->rfc_addr = mystrdup(client_addr.buf);
|
||||||
state->addr_family = sa->sa_family;
|
state->addr_family = sa->sa_family;
|
||||||
}
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It's not Internet.
|
||||||
|
*/
|
||||||
|
else {
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* smtpd_peer_sockaddr_to_hostname - client hostname lookup */
|
||||||
|
|
||||||
|
static void smtpd_peer_sockaddr_to_hostname(SMTPD_STATE *state)
|
||||||
|
{
|
||||||
|
struct sockaddr *sa = (struct sockaddr *) & (state->sockaddr);
|
||||||
|
SOCKADDR_SIZE sa_length = state->sockaddr_len;
|
||||||
|
MAI_HOSTNAME_STR client_name;
|
||||||
|
int aierr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Look up and sanity check the client hostname.
|
* Look up and sanity check the client hostname.
|
||||||
*
|
*
|
||||||
* It is unsafe to allow numeric hostnames, especially because there
|
* It is unsafe to allow numeric hostnames, especially because there exists
|
||||||
* exists pressure to turn off the name->addr double check. In that
|
* pressure to turn off the name->addr double check. In that case an
|
||||||
* case an attacker could trivally bypass access restrictions.
|
* attacker could trivally bypass access restrictions.
|
||||||
*
|
*
|
||||||
* sockaddr_to_hostname() already rejects malformed or numeric names.
|
* sockaddr_to_hostname() already rejects malformed or numeric names.
|
||||||
*/
|
*/
|
||||||
@ -332,10 +333,10 @@ void smtpd_peer_init(SMTPD_STATE *state)
|
|||||||
state->reverse_name_status = SMTPD_PEER_CODE_OK;
|
state->reverse_name_status = SMTPD_PEER_CODE_OK;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reject the hostname if it does not list the peer address.
|
* Reject the hostname if it does not list the peer address. Without
|
||||||
* Without further validation or qualification, such information
|
* further validation or qualification, such information must not be
|
||||||
* must not be allowed to enter the audit trail, as people would
|
* allowed to enter the audit trail, as people would draw false
|
||||||
* draw false conclusions.
|
* conclusions.
|
||||||
*/
|
*/
|
||||||
aierr = hostname_to_sockaddr_pf(state->name, state->addr_family,
|
aierr = hostname_to_sockaddr_pf(state->name, state->addr_family,
|
||||||
(char *) 0, 0, &res0);
|
(char *) 0, 0, &res0);
|
||||||
@ -363,27 +364,222 @@ void smtpd_peer_init(SMTPD_STATE *state)
|
|||||||
freeaddrinfo(res0);
|
freeaddrinfo(res0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* smtpd_peer_hostaddr_to_sockaddr - convert numeric string to binary */
|
||||||
|
|
||||||
|
static void smtpd_peer_hostaddr_to_sockaddr(SMTPD_STATE *state)
|
||||||
|
{
|
||||||
|
const char *myname = "smtpd_peer_hostaddr_to_sockaddr";
|
||||||
|
struct addrinfo *res;
|
||||||
|
int aierr;
|
||||||
|
|
||||||
|
if ((aierr = hostaddr_to_sockaddr(state->addr, state->port,
|
||||||
|
SOCK_STREAM, &res)) != 0)
|
||||||
|
msg_fatal("%s: cannot convert client address/port to string: %s",
|
||||||
|
myname, MAI_STRERROR(aierr));
|
||||||
|
if (res->ai_addrlen > sizeof(state->sockaddr))
|
||||||
|
msg_panic("%s: address length > struct sockaddr_storage", myname);
|
||||||
|
memcpy((char *) &(state->sockaddr), res->ai_addr, res->ai_addrlen);
|
||||||
|
state->sockaddr_len = res->ai_addrlen;
|
||||||
|
freeaddrinfo(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* smtpd_peer_not_inet - non-socket or non-Internet endpoint */
|
||||||
|
|
||||||
|
static void smtpd_peer_not_inet(SMTPD_STATE *state)
|
||||||
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If it's not Internet, assume the client is local, and avoid using the
|
* If it's not Internet, assume the client is local, and avoid using the
|
||||||
* naming service because that can hang when the machine is disconnected.
|
* naming service because that can hang when the machine is disconnected.
|
||||||
*/
|
*/
|
||||||
else {
|
|
||||||
state->name = mystrdup("localhost");
|
state->name = mystrdup("localhost");
|
||||||
state->reverse_name = mystrdup("localhost");
|
state->reverse_name = mystrdup("localhost");
|
||||||
|
#ifdef AF_INET6
|
||||||
if (proto_info->sa_family_list[0] == PF_INET6) {
|
if (proto_info->sa_family_list[0] == PF_INET6) {
|
||||||
state->addr = mystrdup("::1"); /* XXX bogus. */
|
state->addr = mystrdup("::1"); /* XXX bogus. */
|
||||||
state->rfc_addr = mystrdup(IPV6_COL "::1"); /* XXX bogus. */
|
state->rfc_addr = mystrdup(IPV6_COL "::1"); /* XXX bogus. */
|
||||||
} else {
|
} else
|
||||||
state->addr = mystrdup("127.0.0.1");/* XXX bogus. */
|
#endif
|
||||||
state->rfc_addr = mystrdup("127.0.0.1"); /* XXX bogus. */
|
{
|
||||||
|
state->addr = mystrdup("127.0.0.1"); /* XXX bogus. */
|
||||||
|
state->rfc_addr = mystrdup("127.0.0.1");/* XXX bogus. */
|
||||||
}
|
}
|
||||||
state->addr_family = AF_UNSPEC;
|
state->addr_family = AF_UNSPEC;
|
||||||
state->name_status = SMTPD_PEER_CODE_OK;
|
state->name_status = SMTPD_PEER_CODE_OK;
|
||||||
state->reverse_name_status = SMTPD_PEER_CODE_OK;
|
state->reverse_name_status = SMTPD_PEER_CODE_OK;
|
||||||
state->port = mystrdup("0"); /* XXX bogus. */
|
state->port = mystrdup("0"); /* XXX bogus. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* smtpd_peer_no_client - peer went away, or peer info unavailable */
|
||||||
|
|
||||||
|
static void smtpd_peer_no_client(SMTPD_STATE *state)
|
||||||
|
{
|
||||||
|
smtpd_peer_reset(state);
|
||||||
|
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||||
|
state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||||
|
state->addr = mystrdup(CLIENT_ADDR_UNKNOWN);
|
||||||
|
state->rfc_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
|
||||||
|
state->addr_family = AF_UNSPEC;
|
||||||
|
state->name_status = SMTPD_PEER_CODE_PERM;
|
||||||
|
state->reverse_name_status = SMTPD_PEER_CODE_PERM;
|
||||||
|
state->port = mystrdup(CLIENT_PORT_UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* smtpd_peer_from_pass_attr - initialize from attribute hash */
|
||||||
|
|
||||||
|
static void smtpd_peer_from_pass_attr(SMTPD_STATE *state)
|
||||||
|
{
|
||||||
|
HTABLE *attr = (HTABLE *) vstream_context(state->client);
|
||||||
|
const char *cp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract the client endpoint information from the attribute hash.
|
||||||
|
*/
|
||||||
|
if ((cp = htable_find(attr, MAIL_ATTR_ACT_CLIENT_ADDR)) == 0)
|
||||||
|
msg_fatal("missing client address from proxy");
|
||||||
|
if (strrchr(cp, ':') != 0) {
|
||||||
|
if (valid_ipv6_hostaddr(cp, DO_GRIPE) == 0)
|
||||||
|
msg_fatal("bad IPv6 client address syntax from proxy: %s", cp);
|
||||||
|
state->addr = mystrdup(cp);
|
||||||
|
state->rfc_addr = concatenate(IPV6_COL, cp, (char *) 0);
|
||||||
|
state->addr_family = AF_INET6;
|
||||||
|
} else {
|
||||||
|
if (valid_ipv4_hostaddr(cp, DO_GRIPE) == 0)
|
||||||
|
msg_fatal("bad IPv4 client address syntax from proxy: %s", cp);
|
||||||
|
state->addr = mystrdup(cp);
|
||||||
|
state->rfc_addr = mystrdup(cp);
|
||||||
|
state->addr_family = AF_INET;
|
||||||
}
|
}
|
||||||
|
if ((cp = htable_find(attr, MAIL_ATTR_ACT_CLIENT_PORT)) == 0)
|
||||||
|
msg_fatal("missing client port from proxy");
|
||||||
|
if (valid_hostport(cp, DO_GRIPE) == 0)
|
||||||
|
msg_fatal("bad TCP client port number syntax from proxy: %s", cp);
|
||||||
|
state->port = mystrdup(cp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Avoid surprises in the Dovecot authentication server.
|
||||||
|
*/
|
||||||
|
if ((cp = htable_find(attr, MAIL_ATTR_ACT_SERVER_ADDR)) == 0)
|
||||||
|
msg_fatal("missing server address from proxy");
|
||||||
|
if (valid_hostaddr(cp, DO_GRIPE) == 0)
|
||||||
|
msg_fatal("bad IPv6 client address syntax from proxy: %s", cp);
|
||||||
|
state->dest_addr = mystrdup(cp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert the client address from string to binary form.
|
||||||
|
*/
|
||||||
|
smtpd_peer_hostaddr_to_sockaddr(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* smtpd_peer_from_default - try to initialize peer information from socket */
|
||||||
|
|
||||||
|
static void smtpd_peer_from_default(SMTPD_STATE *state)
|
||||||
|
{
|
||||||
|
SOCKADDR_SIZE sa_length = sizeof(state->sockaddr);
|
||||||
|
struct sockaddr *sa = (struct sockaddr *) & (state->sockaddr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The "no client" routine provides surrogate information so that the
|
||||||
|
* application can produce sensible logging when a client disconnects
|
||||||
|
* before the server wakes up. The "not inet" routine provides surrogate
|
||||||
|
* state for (presumably) local IPC channels.
|
||||||
|
*/
|
||||||
|
if (getpeername(vstream_fileno(state->client), sa, &sa_length) < 0) {
|
||||||
|
if (errno == ENOTSOCK)
|
||||||
|
smtpd_peer_not_inet(state);
|
||||||
|
else
|
||||||
|
smtpd_peer_no_client(state);
|
||||||
|
} else {
|
||||||
|
state->sockaddr_len = sa_length;
|
||||||
|
if (smtpd_peer_sockaddr_to_hostaddr(state) < 0)
|
||||||
|
smtpd_peer_not_inet(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* smtpd_peer_from_proxy - get endpoint info from proxy agent */
|
||||||
|
|
||||||
|
static void smtpd_peer_from_proxy(SMTPD_STATE *state)
|
||||||
|
{
|
||||||
|
typedef struct {
|
||||||
|
const char *name;
|
||||||
|
int (*endpt_lookup) (SMTPD_STATE *);
|
||||||
|
} SMTPD_ENDPT_LOOKUP_INFO;
|
||||||
|
static const SMTPD_ENDPT_LOOKUP_INFO smtpd_endpt_lookup_info[] = {
|
||||||
|
HAPROXY_PROTO_NAME, smtpd_peer_from_haproxy,
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
const SMTPD_ENDPT_LOOKUP_INFO *pp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the proxy information is unavailable, we can't maintain an audit
|
||||||
|
* trail or enforce access control, therefore we forcibly hang up.
|
||||||
|
*/
|
||||||
|
for (pp = smtpd_endpt_lookup_info; /* see below */ ; pp++) {
|
||||||
|
if (pp->name == 0)
|
||||||
|
msg_fatal("unsupported %s value: %s",
|
||||||
|
VAR_SMTPD_UPROXY_PROTO, var_smtpd_uproxy_proto);
|
||||||
|
if (strcmp(var_smtpd_uproxy_proto, pp->name) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (pp->endpt_lookup(state) < 0) {
|
||||||
|
smtpd_peer_no_client(state);
|
||||||
|
state->flags |= SMTPD_FLAG_HANGUP;
|
||||||
|
} else {
|
||||||
|
smtpd_peer_hostaddr_to_sockaddr(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* smtpd_peer_init - initialize peer information */
|
||||||
|
|
||||||
|
void smtpd_peer_init(SMTPD_STATE *state)
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize.
|
||||||
|
*/
|
||||||
|
if (proto_info == 0)
|
||||||
|
proto_info = inet_proto_info();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare for partial initialization after error.
|
||||||
|
*/
|
||||||
|
memset((char *) &(state->sockaddr), 0, sizeof(state->sockaddr));
|
||||||
|
state->sockaddr_len = 0;
|
||||||
|
state->name = 0;
|
||||||
|
state->reverse_name = 0;
|
||||||
|
state->addr = 0;
|
||||||
|
state->namaddr = 0;
|
||||||
|
state->rfc_addr = 0;
|
||||||
|
state->port = 0;
|
||||||
|
state->dest_addr = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine the remote SMTP client address and port.
|
||||||
|
*
|
||||||
|
* XXX In stand-alone mode, don't assume that the peer will be a local
|
||||||
|
* process. That could introduce a gaping hole when the SMTP daemon is
|
||||||
|
* hooked up to the network via inetd or some other super-server.
|
||||||
|
*/
|
||||||
|
if (vstream_context(state->client) != 0) {
|
||||||
|
smtpd_peer_from_pass_attr(state);
|
||||||
|
if (*var_smtpd_uproxy_proto != 0)
|
||||||
|
msg_warn("ignoring non-empty %s setting behind postscreen",
|
||||||
|
VAR_SMTPD_UPROXY_PROTO);
|
||||||
|
} else if (SMTPD_STAND_ALONE(state) || *var_smtpd_uproxy_proto == 0) {
|
||||||
|
smtpd_peer_from_default(state);
|
||||||
|
} else {
|
||||||
|
smtpd_peer_from_proxy(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine the remote SMTP client hostname. Note: some of the handlers
|
||||||
|
* above provide surrogate endpoint information in case of error. In that
|
||||||
|
* case, leave the surrogate information alone.
|
||||||
|
*/
|
||||||
|
if (state->name == 0)
|
||||||
|
smtpd_peer_sockaddr_to_hostname(state);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do the name[addr]:port formatting for pretty reports.
|
* Do the name[addr]:port formatting for pretty reports.
|
||||||
@ -396,10 +592,18 @@ void smtpd_peer_init(SMTPD_STATE *state)
|
|||||||
|
|
||||||
void smtpd_peer_reset(SMTPD_STATE *state)
|
void smtpd_peer_reset(SMTPD_STATE *state)
|
||||||
{
|
{
|
||||||
|
if (state->name)
|
||||||
myfree(state->name);
|
myfree(state->name);
|
||||||
|
if (state->reverse_name)
|
||||||
myfree(state->reverse_name);
|
myfree(state->reverse_name);
|
||||||
|
if (state->addr)
|
||||||
myfree(state->addr);
|
myfree(state->addr);
|
||||||
|
if (state->namaddr)
|
||||||
myfree(state->namaddr);
|
myfree(state->namaddr);
|
||||||
|
if (state->rfc_addr)
|
||||||
myfree(state->rfc_addr);
|
myfree(state->rfc_addr);
|
||||||
|
if (state->port)
|
||||||
myfree(state->port);
|
myfree(state->port);
|
||||||
|
if (state->dest_addr)
|
||||||
|
myfree(state->dest_addr);
|
||||||
}
|
}
|
||||||
|
@ -214,7 +214,8 @@ void smtpd_sasl_activate(SMTPD_STATE *state, const char *sasl_opts_name,
|
|||||||
if ((state->sasl_server =
|
if ((state->sasl_server =
|
||||||
XSASL_SERVER_CREATE(smtpd_sasl_impl, &create_args,
|
XSASL_SERVER_CREATE(smtpd_sasl_impl, &create_args,
|
||||||
stream = state->client,
|
stream = state->client,
|
||||||
server_addr = "", /* need smtpd_peer.c update */
|
server_addr = (state->dest_addr ?
|
||||||
|
state->dest_addr : ""),
|
||||||
client_addr = ADDR_OR_EMPTY(state->addr,
|
client_addr = ADDR_OR_EMPTY(state->addr,
|
||||||
CLIENT_ADDR_UNKNOWN),
|
CLIENT_ADDR_UNKNOWN),
|
||||||
service = SMTPD_SASL_SERVICE,
|
service = SMTPD_SASL_SERVICE,
|
||||||
|
@ -31,11 +31,11 @@ SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \
|
|||||||
vstream_popen.c vstring.c vstring_vstream.c watchdog.c writable.c \
|
vstream_popen.c vstring.c vstring_vstream.c watchdog.c writable.c \
|
||||||
write_buf.c write_wait.c sane_basename.c format_tv.c allspace.c \
|
write_buf.c write_wait.c sane_basename.c format_tv.c allspace.c \
|
||||||
allascii.c load_file.c killme_after.c vstream_tweak.c \
|
allascii.c load_file.c killme_after.c vstream_tweak.c \
|
||||||
unix_pass_listen.c unix_pass_trigger.c edit_file.c inet_windowsize.c \
|
pass_trigger.c edit_file.c inet_windowsize.c \
|
||||||
unix_pass_fd_fix.c dict_cache.c valid_utf_8.c dict_thash.c \
|
unix_pass_fd_fix.c dict_cache.c valid_utf_8.c dict_thash.c \
|
||||||
ip_match.c nbbio.c stream_pass_connect.c base32_code.c dict_test.c \
|
ip_match.c nbbio.c base32_code.c dict_test.c \
|
||||||
dict_fail.c msg_rate_delay.c dict_surrogate.c warn_stat.c \
|
dict_fail.c msg_rate_delay.c dict_surrogate.c warn_stat.c \
|
||||||
dict_sockmap.c line_number.c
|
dict_sockmap.c line_number.c recv_pass_attr.c pass_accept.c
|
||||||
OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
|
OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
|
||||||
attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
|
attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
|
||||||
attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
|
attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
|
||||||
@ -68,11 +68,11 @@ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
|
|||||||
vstream_popen.o vstring.o vstring_vstream.o watchdog.o writable.o \
|
vstream_popen.o vstring.o vstring_vstream.o watchdog.o writable.o \
|
||||||
write_buf.o write_wait.o sane_basename.o format_tv.o allspace.o \
|
write_buf.o write_wait.o sane_basename.o format_tv.o allspace.o \
|
||||||
allascii.o load_file.o killme_after.o vstream_tweak.o \
|
allascii.o load_file.o killme_after.o vstream_tweak.o \
|
||||||
unix_pass_listen.o unix_pass_trigger.o edit_file.o inet_windowsize.o \
|
pass_trigger.o edit_file.o inet_windowsize.o \
|
||||||
unix_pass_fd_fix.o dict_cache.o valid_utf_8.o dict_thash.o \
|
unix_pass_fd_fix.o dict_cache.o valid_utf_8.o dict_thash.o \
|
||||||
ip_match.o nbbio.o stream_pass_connect.o base32_code.o dict_test.o \
|
ip_match.o nbbio.o base32_code.o dict_test.o \
|
||||||
dict_fail.o msg_rate_delay.o dict_surrogate.o warn_stat.o \
|
dict_fail.o msg_rate_delay.o dict_surrogate.o warn_stat.o \
|
||||||
dict_sockmap.o line_number.o
|
dict_sockmap.o line_number.o recv_pass_attr.o pass_accept.o
|
||||||
HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
|
HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
|
||||||
chroot_uid.h cidr_match.h clean_env.h connect.h ctable.h dict.h \
|
chroot_uid.h cidr_match.h clean_env.h connect.h ctable.h dict.h \
|
||||||
dict_cdb.h dict_cidr.h dict_db.h dict_dbm.h dict_env.h dict_ht.h \
|
dict_cdb.h dict_cidr.h dict_db.h dict_dbm.h dict_env.h dict_ht.h \
|
||||||
@ -111,7 +111,8 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
|
|||||||
attr_scan0 host_port attr_scan_plain attr_print_plain htable \
|
attr_scan0 host_port attr_scan_plain attr_print_plain htable \
|
||||||
unix_recv_fd unix_send_fd stream_recv_fd stream_send_fd hex_code \
|
unix_recv_fd unix_send_fd stream_recv_fd stream_send_fd hex_code \
|
||||||
myaddrinfo myaddrinfo4 inet_proto sane_basename format_tv \
|
myaddrinfo myaddrinfo4 inet_proto sane_basename format_tv \
|
||||||
valid_utf_8 ip_match base32_code msg_rate_delay netstring
|
valid_utf_8 ip_match base32_code msg_rate_delay netstring \
|
||||||
|
vstream
|
||||||
|
|
||||||
LIB_DIR = ../../lib
|
LIB_DIR = ../../lib
|
||||||
INC_DIR = ../../include
|
INC_DIR = ../../include
|
||||||
@ -446,6 +447,11 @@ netstring: $(LIB)
|
|||||||
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
|
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
|
||||||
mv junk $@.o
|
mv junk $@.o
|
||||||
|
|
||||||
|
vstream: $(LIB)
|
||||||
|
mv $@.o junk
|
||||||
|
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
|
||||||
|
mv junk $@.o
|
||||||
|
|
||||||
tests: valid_hostname_test mac_expand_test dict_test unescape_test \
|
tests: valid_hostname_test mac_expand_test dict_test unescape_test \
|
||||||
hex_quote_test ctable_test inet_addr_list_test base64_code_test \
|
hex_quote_test ctable_test inet_addr_list_test base64_code_test \
|
||||||
attr_scan64_test attr_scan0_test dict_pcre_test host_port_test \
|
attr_scan64_test attr_scan0_test dict_pcre_test host_port_test \
|
||||||
@ -1203,6 +1209,7 @@ exec_command.o: exec_command.h
|
|||||||
exec_command.o: msg.h
|
exec_command.o: msg.h
|
||||||
exec_command.o: sys_defs.h
|
exec_command.o: sys_defs.h
|
||||||
fifo_listen.o: fifo_listen.c
|
fifo_listen.o: fifo_listen.c
|
||||||
|
fifo_listen.o: htable.h
|
||||||
fifo_listen.o: iostuff.h
|
fifo_listen.o: iostuff.h
|
||||||
fifo_listen.o: listen.h
|
fifo_listen.o: listen.h
|
||||||
fifo_listen.o: msg.h
|
fifo_listen.o: msg.h
|
||||||
@ -1329,6 +1336,7 @@ inet_connect.o: sock_addr.h
|
|||||||
inet_connect.o: sys_defs.h
|
inet_connect.o: sys_defs.h
|
||||||
inet_connect.o: timed_connect.h
|
inet_connect.o: timed_connect.h
|
||||||
inet_listen.o: host_port.h
|
inet_listen.o: host_port.h
|
||||||
|
inet_listen.o: htable.h
|
||||||
inet_listen.o: inet_listen.c
|
inet_listen.o: inet_listen.c
|
||||||
inet_listen.o: inet_proto.h
|
inet_listen.o: inet_proto.h
|
||||||
inet_listen.o: iostuff.h
|
inet_listen.o: iostuff.h
|
||||||
@ -1572,6 +1580,23 @@ open_lock.o: sys_defs.h
|
|||||||
open_lock.o: vbuf.h
|
open_lock.o: vbuf.h
|
||||||
open_lock.o: vstream.h
|
open_lock.o: vstream.h
|
||||||
open_lock.o: vstring.h
|
open_lock.o: vstring.h
|
||||||
|
pass_accept.o: attr.h
|
||||||
|
pass_accept.o: htable.h
|
||||||
|
pass_accept.o: iostuff.h
|
||||||
|
pass_accept.o: listen.h
|
||||||
|
pass_accept.o: msg.h
|
||||||
|
pass_accept.o: pass_accept.c
|
||||||
|
pass_accept.o: sys_defs.h
|
||||||
|
pass_accept.o: vbuf.h
|
||||||
|
pass_accept.o: vstream.h
|
||||||
|
pass_trigger.o: connect.h
|
||||||
|
pass_trigger.o: events.h
|
||||||
|
pass_trigger.o: iostuff.h
|
||||||
|
pass_trigger.o: msg.h
|
||||||
|
pass_trigger.o: mymalloc.h
|
||||||
|
pass_trigger.o: pass_trigger.c
|
||||||
|
pass_trigger.o: sys_defs.h
|
||||||
|
pass_trigger.o: trigger.h
|
||||||
peekfd.o: iostuff.h
|
peekfd.o: iostuff.h
|
||||||
peekfd.o: peekfd.c
|
peekfd.o: peekfd.c
|
||||||
peekfd.o: sys_defs.h
|
peekfd.o: sys_defs.h
|
||||||
@ -1608,6 +1633,15 @@ readlline.o: sys_defs.h
|
|||||||
readlline.o: vbuf.h
|
readlline.o: vbuf.h
|
||||||
readlline.o: vstream.h
|
readlline.o: vstream.h
|
||||||
readlline.o: vstring.h
|
readlline.o: vstring.h
|
||||||
|
recv_pass_attr.o: attr.h
|
||||||
|
recv_pass_attr.o: htable.h
|
||||||
|
recv_pass_attr.o: iostuff.h
|
||||||
|
recv_pass_attr.o: listen.h
|
||||||
|
recv_pass_attr.o: mymalloc.h
|
||||||
|
recv_pass_attr.o: recv_pass_attr.c
|
||||||
|
recv_pass_attr.o: sys_defs.h
|
||||||
|
recv_pass_attr.o: vbuf.h
|
||||||
|
recv_pass_attr.o: vstream.h
|
||||||
ring.o: ring.c
|
ring.o: ring.c
|
||||||
ring.o: ring.h
|
ring.o: ring.h
|
||||||
safe_getenv.o: safe.h
|
safe_getenv.o: safe.h
|
||||||
@ -1720,16 +1754,12 @@ stream_connect.o: iostuff.h
|
|||||||
stream_connect.o: msg.h
|
stream_connect.o: msg.h
|
||||||
stream_connect.o: stream_connect.c
|
stream_connect.o: stream_connect.c
|
||||||
stream_connect.o: sys_defs.h
|
stream_connect.o: sys_defs.h
|
||||||
|
stream_listen.o: htable.h
|
||||||
stream_listen.o: iostuff.h
|
stream_listen.o: iostuff.h
|
||||||
stream_listen.o: listen.h
|
stream_listen.o: listen.h
|
||||||
stream_listen.o: msg.h
|
stream_listen.o: msg.h
|
||||||
stream_listen.o: stream_listen.c
|
stream_listen.o: stream_listen.c
|
||||||
stream_listen.o: sys_defs.h
|
stream_listen.o: sys_defs.h
|
||||||
stream_pass_connect.o: connect.h
|
|
||||||
stream_pass_connect.o: iostuff.h
|
|
||||||
stream_pass_connect.o: msg.h
|
|
||||||
stream_pass_connect.o: stream_pass_connect.c
|
|
||||||
stream_pass_connect.o: sys_defs.h
|
|
||||||
stream_recv_fd.o: iostuff.h
|
stream_recv_fd.o: iostuff.h
|
||||||
stream_recv_fd.o: msg.h
|
stream_recv_fd.o: msg.h
|
||||||
stream_recv_fd.o: stream_recv_fd.c
|
stream_recv_fd.o: stream_recv_fd.c
|
||||||
@ -1739,6 +1769,7 @@ stream_send_fd.o: msg.h
|
|||||||
stream_send_fd.o: stream_send_fd.c
|
stream_send_fd.o: stream_send_fd.c
|
||||||
stream_send_fd.o: sys_defs.h
|
stream_send_fd.o: sys_defs.h
|
||||||
stream_test.o: connect.h
|
stream_test.o: connect.h
|
||||||
|
stream_test.o: htable.h
|
||||||
stream_test.o: iostuff.h
|
stream_test.o: iostuff.h
|
||||||
stream_test.o: listen.h
|
stream_test.o: listen.h
|
||||||
stream_test.o: msg.h
|
stream_test.o: msg.h
|
||||||
@ -1798,6 +1829,7 @@ unix_connect.o: sane_connect.h
|
|||||||
unix_connect.o: sys_defs.h
|
unix_connect.o: sys_defs.h
|
||||||
unix_connect.o: timed_connect.h
|
unix_connect.o: timed_connect.h
|
||||||
unix_connect.o: unix_connect.c
|
unix_connect.o: unix_connect.c
|
||||||
|
unix_listen.o: htable.h
|
||||||
unix_listen.o: iostuff.h
|
unix_listen.o: iostuff.h
|
||||||
unix_listen.o: listen.h
|
unix_listen.o: listen.h
|
||||||
unix_listen.o: msg.h
|
unix_listen.o: msg.h
|
||||||
@ -1810,20 +1842,6 @@ unix_pass_fd_fix.o: sys_defs.h
|
|||||||
unix_pass_fd_fix.o: unix_pass_fd_fix.c
|
unix_pass_fd_fix.o: unix_pass_fd_fix.c
|
||||||
unix_pass_fd_fix.o: vbuf.h
|
unix_pass_fd_fix.o: vbuf.h
|
||||||
unix_pass_fd_fix.o: vstring.h
|
unix_pass_fd_fix.o: vstring.h
|
||||||
unix_pass_listen.o: iostuff.h
|
|
||||||
unix_pass_listen.o: listen.h
|
|
||||||
unix_pass_listen.o: msg.h
|
|
||||||
unix_pass_listen.o: sane_accept.h
|
|
||||||
unix_pass_listen.o: sys_defs.h
|
|
||||||
unix_pass_listen.o: unix_pass_listen.c
|
|
||||||
unix_pass_trigger.o: connect.h
|
|
||||||
unix_pass_trigger.o: events.h
|
|
||||||
unix_pass_trigger.o: iostuff.h
|
|
||||||
unix_pass_trigger.o: msg.h
|
|
||||||
unix_pass_trigger.o: mymalloc.h
|
|
||||||
unix_pass_trigger.o: sys_defs.h
|
|
||||||
unix_pass_trigger.o: trigger.h
|
|
||||||
unix_pass_trigger.o: unix_pass_trigger.c
|
|
||||||
unix_recv_fd.o: iostuff.h
|
unix_recv_fd.o: iostuff.h
|
||||||
unix_recv_fd.o: msg.h
|
unix_recv_fd.o: msg.h
|
||||||
unix_recv_fd.o: sys_defs.h
|
unix_recv_fd.o: sys_defs.h
|
||||||
|
@ -22,9 +22,6 @@
|
|||||||
extern int unix_connect(const char *, int, int);
|
extern int unix_connect(const char *, int, int);
|
||||||
extern int inet_connect(const char *, int, int);
|
extern int inet_connect(const char *, int, int);
|
||||||
extern int stream_connect(const char *, int, int);
|
extern int stream_connect(const char *, int, int);
|
||||||
extern int stream_pass_connect(const char *, int, int);
|
|
||||||
|
|
||||||
#define unix_pass_connect unix_connect
|
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
* Utility library.
|
* Utility library.
|
||||||
*/
|
*/
|
||||||
#include <iostuff.h>
|
#include <iostuff.h>
|
||||||
|
#include <htable.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Listener external interface.
|
* Listener external interface.
|
||||||
@ -24,15 +25,13 @@ extern int inet_listen(const char *, int, int);
|
|||||||
extern int fifo_listen(const char *, int, int);
|
extern int fifo_listen(const char *, int, int);
|
||||||
extern int stream_listen(const char *, int, int);
|
extern int stream_listen(const char *, int, int);
|
||||||
|
|
||||||
#define unix_pass_listen unix_listen
|
|
||||||
#define stream_pass_listen stream_listen
|
|
||||||
|
|
||||||
extern int inet_accept(int);
|
extern int inet_accept(int);
|
||||||
extern int unix_accept(int);
|
extern int unix_accept(int);
|
||||||
extern int stream_accept(int);
|
extern int stream_accept(int);
|
||||||
extern int unix_pass_accept(int);
|
|
||||||
|
|
||||||
#define stream_pass_accept stream_accept
|
extern int recv_pass_attr(int, HTABLE **, int, ssize_t);
|
||||||
|
extern int pass_accept(int);
|
||||||
|
extern int pass_accept_attr(int, HTABLE **);
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
|
@ -148,6 +148,8 @@ void msg_printf(int level, const char *format,...)
|
|||||||
|
|
||||||
void msg_vprintf(int level, const char *format, va_list ap)
|
void msg_vprintf(int level, const char *format, va_list ap)
|
||||||
{
|
{
|
||||||
|
int saved_errno = errno;
|
||||||
|
|
||||||
if (msg_vprintf_lock == 0) {
|
if (msg_vprintf_lock == 0) {
|
||||||
msg_vprintf_lock = 1;
|
msg_vprintf_lock = 1;
|
||||||
/* On-the-fly initialization for debugging test programs only. */
|
/* On-the-fly initialization for debugging test programs only. */
|
||||||
@ -158,6 +160,7 @@ void msg_vprintf(int level, const char *format, va_list ap)
|
|||||||
msg_text(level, vstring_str(msg_buffer));
|
msg_text(level, vstring_str(msg_buffer));
|
||||||
msg_vprintf_lock = 0;
|
msg_vprintf_lock = 0;
|
||||||
}
|
}
|
||||||
|
errno = saved_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* msg_text - sanitize and log pre-formatted text */
|
/* msg_text - sanitize and log pre-formatted text */
|
||||||
|
106
postfix/src/util/pass_accept.c
Normal file
106
postfix/src/util/pass_accept.c
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/*++
|
||||||
|
/* NAME
|
||||||
|
/* pass_accept 3
|
||||||
|
/* SUMMARY
|
||||||
|
/* start UNIX-domain file descriptor listener
|
||||||
|
/* SYNOPSIS
|
||||||
|
/* #include <listen.h>
|
||||||
|
/*
|
||||||
|
/* int pass_accept(listen_fd)
|
||||||
|
/* int listen_fd;
|
||||||
|
/*
|
||||||
|
/* int pass_accept_attr(listen_fd, attr)
|
||||||
|
/* int listen_fd;
|
||||||
|
/* HTABLE **attr;
|
||||||
|
/* DESCRIPTION
|
||||||
|
/* This module implements a listener that receives one attribute list
|
||||||
|
/* and file descriptor over each a local connection that is made to it.
|
||||||
|
/*
|
||||||
|
/* Arguments:
|
||||||
|
/* .IP attr
|
||||||
|
/* Pointer to attribute list pointer. In case of error, or
|
||||||
|
/* no attributes, the attribute list pointer is set to null.
|
||||||
|
/* .IP listen_fd
|
||||||
|
/* File descriptor returned by LOCAL_LISTEN().
|
||||||
|
/* DIAGNOSTICS
|
||||||
|
/* Warnings: I/O errors, timeout.
|
||||||
|
/* LICENSE
|
||||||
|
/* .ad
|
||||||
|
/* .fi
|
||||||
|
/* The Secure Mailer license must be distributed with this software.
|
||||||
|
/* AUTHOR(S)
|
||||||
|
/* Wietse Venema
|
||||||
|
/* IBM T.J. Watson Research
|
||||||
|
/* P.O. Box 704
|
||||||
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*--*/
|
||||||
|
|
||||||
|
/* System library. */
|
||||||
|
|
||||||
|
#include <sys_defs.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/* Utility library. */
|
||||||
|
|
||||||
|
#include <msg.h>
|
||||||
|
#include <listen.h>
|
||||||
|
#include <attr.h>
|
||||||
|
|
||||||
|
#define PASS_ACCEPT_TMOUT 100
|
||||||
|
|
||||||
|
/* pass_accept - accept descriptor */
|
||||||
|
|
||||||
|
int pass_accept(int listen_fd)
|
||||||
|
{
|
||||||
|
const char *myname = "pass_accept";
|
||||||
|
int accept_fd;
|
||||||
|
int recv_fd = -1;
|
||||||
|
|
||||||
|
accept_fd = LOCAL_ACCEPT(listen_fd);
|
||||||
|
if (accept_fd < 0) {
|
||||||
|
if (errno != EAGAIN)
|
||||||
|
msg_warn("%s: cannot accept connection: %m", myname);
|
||||||
|
return (-1);
|
||||||
|
} else {
|
||||||
|
if (read_wait(accept_fd, PASS_ACCEPT_TMOUT) < 0)
|
||||||
|
msg_warn("%s: timeout receiving file descriptor: %m", myname);
|
||||||
|
else if ((recv_fd = LOCAL_RECV_FD(accept_fd)) < 0)
|
||||||
|
msg_warn("%s: cannot receive file descriptor: %m", myname);
|
||||||
|
if (close(accept_fd) < 0)
|
||||||
|
msg_warn("%s: close: %m", myname);
|
||||||
|
return (recv_fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pass_accept_attr - accept attribute list and descriptor */
|
||||||
|
|
||||||
|
int pass_accept_attr(int listen_fd, HTABLE **attr)
|
||||||
|
{
|
||||||
|
const char *myname = "pass_accept_attr";
|
||||||
|
int accept_fd;
|
||||||
|
int recv_fd = -1;
|
||||||
|
|
||||||
|
*attr = 0;
|
||||||
|
accept_fd = LOCAL_ACCEPT(listen_fd);
|
||||||
|
if (accept_fd < 0) {
|
||||||
|
if (errno != EAGAIN)
|
||||||
|
msg_warn("%s: cannot accept connection: %m", myname);
|
||||||
|
return (-1);
|
||||||
|
} else {
|
||||||
|
if (read_wait(accept_fd, PASS_ACCEPT_TMOUT) < 0)
|
||||||
|
msg_warn("%s: timeout receiving file descriptor: %m", myname);
|
||||||
|
else if ((recv_fd = LOCAL_RECV_FD(accept_fd)) < 0)
|
||||||
|
msg_warn("%s: cannot receive file descriptor: %m", myname);
|
||||||
|
else if (read_wait(accept_fd, PASS_ACCEPT_TMOUT) < 0
|
||||||
|
|| recv_pass_attr(accept_fd, attr, PASS_ACCEPT_TMOUT, 0) < 0) {
|
||||||
|
msg_warn("%s: cannot receive connection attributes: %m", myname);
|
||||||
|
if (close(recv_fd) < 0)
|
||||||
|
msg_warn("%s: close: %m", myname);
|
||||||
|
recv_fd = -1;
|
||||||
|
}
|
||||||
|
if (close(accept_fd) < 0)
|
||||||
|
msg_warn("%s: close: %m", myname);
|
||||||
|
return (recv_fd);
|
||||||
|
}
|
||||||
|
}
|
@ -1,19 +1,19 @@
|
|||||||
/*++
|
/*++
|
||||||
/* NAME
|
/* NAME
|
||||||
/* unix_pass_trigger 3
|
/* pass_trigger 3
|
||||||
/* SUMMARY
|
/* SUMMARY
|
||||||
/* wakeup UNIX-domain file descriptor listener
|
/* trigger file descriptor listener
|
||||||
/* SYNOPSIS
|
/* SYNOPSIS
|
||||||
/* #include <trigger.h>
|
/* #include <trigger.h>
|
||||||
/*
|
/*
|
||||||
/* int unix_pass_trigger(service, buf, len, timeout)
|
/* int pass_trigger(service, buf, len, timeout)
|
||||||
/* const char *service;
|
/* const char *service;
|
||||||
/* const char *buf;
|
/* const char *buf;
|
||||||
/* ssize_t len;
|
/* ssize_t len;
|
||||||
/* int timeout;
|
/* int timeout;
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* unix_pass_trigger() wakes up the named UNIX-domain server by sending
|
/* pass_trigger() connects to the named local server by sending
|
||||||
/* a brief connection to it and writing the named buffer.
|
/* a file descriptor to it and writing the named buffer.
|
||||||
/*
|
/*
|
||||||
/* The connection is closed by a background thread. Some kernels
|
/* The connection is closed by a background thread. Some kernels
|
||||||
/* cannot handle client-side disconnect before the server has
|
/* cannot handle client-side disconnect before the server has
|
||||||
@ -32,7 +32,8 @@
|
|||||||
/* DIAGNOSTICS
|
/* DIAGNOSTICS
|
||||||
/* The result is zero in case of success, -1 in case of problems.
|
/* The result is zero in case of success, -1 in case of problems.
|
||||||
/* SEE ALSO
|
/* SEE ALSO
|
||||||
/* unix_pass_connect(3), UNIX-domain client
|
/* unix_connect(3), local client
|
||||||
|
/* stream_connect(3), streams-based client
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
@ -60,45 +61,45 @@
|
|||||||
#include <events.h>
|
#include <events.h>
|
||||||
#include <trigger.h>
|
#include <trigger.h>
|
||||||
|
|
||||||
struct unix_pass_trigger {
|
struct pass_trigger {
|
||||||
int fd;
|
int connect_fd;
|
||||||
char *service;
|
char *service;
|
||||||
int *pair;
|
int pass_fd[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* unix_pass_trigger_event - disconnect from peer */
|
/* pass_trigger_event - disconnect from peer */
|
||||||
|
|
||||||
static void unix_pass_trigger_event(int event, char *context)
|
static void pass_trigger_event(int event, char *context)
|
||||||
{
|
{
|
||||||
struct unix_pass_trigger *up = (struct unix_pass_trigger *) context;
|
struct pass_trigger *pp = (struct pass_trigger *) context;
|
||||||
static const char *myname = "unix_pass_trigger_event";
|
static const char *myname = "pass_trigger_event";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disconnect.
|
* Disconnect.
|
||||||
*/
|
*/
|
||||||
if (event == EVENT_TIME)
|
if (event == EVENT_TIME)
|
||||||
msg_warn("%s: read timeout for service %s", myname, up->service);
|
msg_warn("%s: read timeout for service %s", myname, pp->service);
|
||||||
event_disable_readwrite(up->fd);
|
event_disable_readwrite(pp->connect_fd);
|
||||||
event_cancel_timer(unix_pass_trigger_event, context);
|
event_cancel_timer(pass_trigger_event, context);
|
||||||
/* Don't combine multiple close() calls into one boolean expression. */
|
/* Don't combine multiple close() calls into one boolean expression. */
|
||||||
if (close(up->fd) < 0)
|
if (close(pp->connect_fd) < 0)
|
||||||
msg_warn("%s: close %s: %m", myname, up->service);
|
msg_warn("%s: close %s: %m", myname, pp->service);
|
||||||
if (close(up->pair[0]) < 0)
|
if (close(pp->pass_fd[0]) < 0)
|
||||||
msg_warn("%s: close pipe: %m", myname);
|
msg_warn("%s: close pipe: %m", myname);
|
||||||
if (close(up->pair[1]) < 0)
|
if (close(pp->pass_fd[1]) < 0)
|
||||||
msg_warn("%s: close pipe: %m", myname);
|
msg_warn("%s: close pipe: %m", myname);
|
||||||
myfree(up->service);
|
myfree(pp->service);
|
||||||
myfree((char *) up);
|
myfree((char *) pp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unix_pass_trigger - wakeup UNIX-domain server */
|
/* pass_trigger - wakeup local server */
|
||||||
|
|
||||||
int unix_pass_trigger(const char *service, const char *buf, ssize_t len, int timeout)
|
int pass_trigger(const char *service, const char *buf, ssize_t len, int timeout)
|
||||||
{
|
{
|
||||||
const char *myname = "unix_pass_trigger";
|
const char *myname = "pass_trigger";
|
||||||
int pair[2];
|
int pass_fd[2];
|
||||||
struct unix_pass_trigger *up;
|
struct pass_trigger *pp;
|
||||||
int fd;
|
int connect_fd;
|
||||||
|
|
||||||
if (msg_verbose > 1)
|
if (msg_verbose > 1)
|
||||||
msg_info("%s: service %s", myname, service);
|
msg_info("%s: service %s", myname, service);
|
||||||
@ -106,36 +107,37 @@ int unix_pass_trigger(const char *service, const char *buf, ssize_t len, int
|
|||||||
/*
|
/*
|
||||||
* Connect...
|
* Connect...
|
||||||
*/
|
*/
|
||||||
if ((fd = unix_pass_connect(service, BLOCKING, timeout)) < 0) {
|
if ((connect_fd = LOCAL_CONNECT(service, BLOCKING, timeout)) < 0) {
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_warn("%s: connect to %s: %m", myname, service);
|
msg_warn("%s: connect to %s: %m", myname, service);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
close_on_exec(fd, CLOSE_ON_EXEC);
|
close_on_exec(connect_fd, CLOSE_ON_EXEC);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a pipe, and send one pipe end to the server.
|
* Create a pipe, and send one pipe end to the server.
|
||||||
*/
|
*/
|
||||||
if (pipe(pair) < 0)
|
if (pipe(pass_fd) < 0)
|
||||||
msg_fatal("%s: pipe: %m", myname);
|
msg_fatal("%s: pipe: %m", myname);
|
||||||
close_on_exec(pair[0], CLOSE_ON_EXEC);
|
close_on_exec(pass_fd[0], CLOSE_ON_EXEC);
|
||||||
close_on_exec(pair[1], CLOSE_ON_EXEC);
|
close_on_exec(pass_fd[1], CLOSE_ON_EXEC);
|
||||||
if (unix_send_fd(fd, pair[0]) < 0)
|
if (LOCAL_SEND_FD(connect_fd, pass_fd[0]) < 0)
|
||||||
msg_fatal("%s: send file descriptor: %m", myname);
|
msg_fatal("%s: send file descriptor: %m", myname);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Stash away context.
|
* Stash away context.
|
||||||
*/
|
*/
|
||||||
up = (struct unix_pass_trigger *) mymalloc(sizeof(*up));
|
pp = (struct pass_trigger *) mymalloc(sizeof(*pp));
|
||||||
up->fd = fd;
|
pp->connect_fd = connect_fd;
|
||||||
up->service = mystrdup(service);
|
pp->service = mystrdup(service);
|
||||||
up->pair = pair;
|
pp->pass_fd[0] = pass_fd[0];
|
||||||
|
pp->pass_fd[1] = pass_fd[1];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write the request...
|
* Write the request...
|
||||||
*/
|
*/
|
||||||
if (write_buf(pair[1], buf, len, timeout) < 0
|
if (write_buf(pass_fd[1], buf, len, timeout) < 0
|
||||||
|| write_buf(pair[1], "", 1, timeout) < 0)
|
|| write_buf(pass_fd[1], "", 1, timeout) < 0)
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_warn("%s: write to %s: %m", myname, service);
|
msg_warn("%s: write to %s: %m", myname, service);
|
||||||
|
|
||||||
@ -143,7 +145,7 @@ int unix_pass_trigger(const char *service, const char *buf, ssize_t len, int
|
|||||||
* Wakeup when the peer disconnects, or when we lose patience.
|
* Wakeup when the peer disconnects, or when we lose patience.
|
||||||
*/
|
*/
|
||||||
if (timeout > 0)
|
if (timeout > 0)
|
||||||
event_request_timer(unix_pass_trigger_event, (char *) up, timeout + 100);
|
event_request_timer(pass_trigger_event, (char *) pp, timeout + 100);
|
||||||
event_enable_read(fd, unix_pass_trigger_event, (char *) up);
|
event_enable_read(connect_fd, pass_trigger_event, (char *) pp);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
93
postfix/src/util/recv_pass_attr.c
Normal file
93
postfix/src/util/recv_pass_attr.c
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/*++
|
||||||
|
/* NAME
|
||||||
|
/* recv_pass_attr 3
|
||||||
|
/* SUMMARY
|
||||||
|
/* predicate if string is all numerical
|
||||||
|
/* SYNOPSIS
|
||||||
|
/* #include <listen.h>
|
||||||
|
/*
|
||||||
|
/* int recv_pass_attr(fd, attr, timeout, bufsize)
|
||||||
|
/* int fd;
|
||||||
|
/* HTABLE **attr;
|
||||||
|
/* int timeout;
|
||||||
|
/* ssize_t bufsize;
|
||||||
|
/* DESCRIPTION
|
||||||
|
/* recv_pass_attr() receives named attributes over the specified
|
||||||
|
/* The result value is zero for success, -1 for error.
|
||||||
|
/*
|
||||||
|
/* Arguments:
|
||||||
|
/* .IP fd
|
||||||
|
/* The file descriptor to read from.
|
||||||
|
/* .IP attr
|
||||||
|
/* Pointer to attribute list pointer. The target is set to
|
||||||
|
/* zero on error or when the received attribute list is empty,
|
||||||
|
/* ohterwise it is assigned a pointer to non-empty attribute
|
||||||
|
/* list.
|
||||||
|
/* .IP timeout
|
||||||
|
/* The deadline for receiving all attributes.
|
||||||
|
/* .IP bufsize
|
||||||
|
/* The read buffer size. Specify 1 to avoid reading past the
|
||||||
|
/* end of the attribute list.
|
||||||
|
/* LICENSE
|
||||||
|
/* .ad
|
||||||
|
/* .fi
|
||||||
|
/* The Secure Mailer license must be distributed with this software.
|
||||||
|
/* AUTHOR(S)
|
||||||
|
/* Wietse Venema
|
||||||
|
/* IBM T.J. Watson Research
|
||||||
|
/* P.O. Box 704
|
||||||
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*--*/
|
||||||
|
|
||||||
|
/* System library. */
|
||||||
|
|
||||||
|
#include <sys_defs.h>
|
||||||
|
|
||||||
|
/* Utility library. */
|
||||||
|
|
||||||
|
#include <iostuff.h>
|
||||||
|
#include <htable.h>
|
||||||
|
#include <vstream.h>
|
||||||
|
#include <attr.h>
|
||||||
|
#include <mymalloc.h>
|
||||||
|
#include <listen.h>
|
||||||
|
|
||||||
|
/* recv_pass_attr - receive connection attributes */
|
||||||
|
|
||||||
|
int recv_pass_attr(int fd, HTABLE **attr, int timeout, ssize_t bufsize)
|
||||||
|
{
|
||||||
|
VSTREAM *fp;
|
||||||
|
int stream_err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up a temporary VSTREAM to receive the attributes.
|
||||||
|
*
|
||||||
|
* XXX We use one-character reads to simplify the implementation.
|
||||||
|
*/
|
||||||
|
fp = vstream_fdopen(fd, O_RDWR);
|
||||||
|
vstream_control(fp,
|
||||||
|
VSTREAM_CTL_BUFSIZE, bufsize,
|
||||||
|
VSTREAM_CTL_TIMEOUT, timeout,
|
||||||
|
VSTREAM_CTL_START_DEADLINE,
|
||||||
|
VSTREAM_CTL_END);
|
||||||
|
(void) attr_scan(fp, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_HASH, *attr = htable_create(1),
|
||||||
|
ATTR_TYPE_END);
|
||||||
|
stream_err = (vstream_feof(fp) || vstream_ferror(fp));
|
||||||
|
vstream_fdclose(fp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Error reporting and recovery.
|
||||||
|
*/
|
||||||
|
if (stream_err) {
|
||||||
|
htable_free(*attr, myfree);
|
||||||
|
*attr = 0;
|
||||||
|
return (-1);
|
||||||
|
} else {
|
||||||
|
if ((*attr)->used == 0) {
|
||||||
|
htable_free(*attr, myfree);
|
||||||
|
*attr = 0;
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
}
|
@ -1,86 +0,0 @@
|
|||||||
/*++
|
|
||||||
/* NAME
|
|
||||||
/* stream_pass_connect 3
|
|
||||||
/* SUMMARY
|
|
||||||
/* connect to stream-based descriptor listener
|
|
||||||
/* SYNOPSIS
|
|
||||||
/* #include <connect.h>
|
|
||||||
/*
|
|
||||||
/* int stream_pass_connect(path, block_mode, timeout)
|
|
||||||
/* const char *path;
|
|
||||||
/* int block_mode;
|
|
||||||
/* int timeout;
|
|
||||||
/* DESCRIPTION
|
|
||||||
/* stream_pass_connect() connects to a stream-based descriptor
|
|
||||||
/* listener for the specified pathname, and returns the resulting
|
|
||||||
/* file descriptor. The next operation is to stream_send_fd()
|
|
||||||
/* a file descriptor and then close() the connection once the
|
|
||||||
/* server has received the file descriptor.
|
|
||||||
/*
|
|
||||||
/* Arguments:
|
|
||||||
/* .IP path
|
|
||||||
/* Null-terminated string with listener endpoint name.
|
|
||||||
/* .IP block_mode
|
|
||||||
/* Either NON_BLOCKING for a non-blocking stream, or BLOCKING for
|
|
||||||
/* blocking mode. However, a stream connection succeeds or fails
|
|
||||||
/* immediately.
|
|
||||||
/* .IP timeout
|
|
||||||
/* This argument is ignored; it is present for compatibility with
|
|
||||||
/* other interfaces. Stream connections succeed or fail immediately.
|
|
||||||
/* DIAGNOSTICS
|
|
||||||
/* The result is -1 in case the connection could not be made.
|
|
||||||
/* Fatal errors: other system call failures.
|
|
||||||
/* LICENSE
|
|
||||||
/* .ad
|
|
||||||
/* .fi
|
|
||||||
/* The Secure Mailer license must be distributed with this software.
|
|
||||||
/* AUTHOR(S)
|
|
||||||
/* Wietse Venema
|
|
||||||
/* IBM T.J. Watson Research
|
|
||||||
/* P.O. Box 704
|
|
||||||
/* Yorktown Heights, NY 10598, USA
|
|
||||||
/*--*/
|
|
||||||
|
|
||||||
/* System library. */
|
|
||||||
|
|
||||||
#include <sys_defs.h>
|
|
||||||
|
|
||||||
#ifdef STREAM_CONNECTIONS
|
|
||||||
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Utility library. */
|
|
||||||
|
|
||||||
#include <msg.h>
|
|
||||||
#include <connect.h>
|
|
||||||
|
|
||||||
/* stream_pass_connect - connect to stream-based descriptor listener */
|
|
||||||
|
|
||||||
int stream_pass_connect(const char *path, int block_mode, int unused_timeout)
|
|
||||||
{
|
|
||||||
#ifdef STREAM_CONNECTIONS
|
|
||||||
const char *myname = "stream_pass_connect";
|
|
||||||
int fifo;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The requested file system object must exist, otherwise we can't reach
|
|
||||||
* the server.
|
|
||||||
*/
|
|
||||||
if ((fifo = open(path, O_WRONLY | O_NONBLOCK, 0)) < 0)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is for {unix,inet}_connect() compatibility.
|
|
||||||
*/
|
|
||||||
non_blocking(fifo, block_mode);
|
|
||||||
|
|
||||||
return (fifo);
|
|
||||||
#else
|
|
||||||
msg_fatal("stream connections are not implemented");
|
|
||||||
#endif
|
|
||||||
}
|
|
@ -436,10 +436,6 @@ extern int opterr;
|
|||||||
#define LOCAL_TRIGGER stream_trigger
|
#define LOCAL_TRIGGER stream_trigger
|
||||||
#define LOCAL_SEND_FD stream_send_fd
|
#define LOCAL_SEND_FD stream_send_fd
|
||||||
#define LOCAL_RECV_FD stream_recv_fd
|
#define LOCAL_RECV_FD stream_recv_fd
|
||||||
#define PASS_CONNECT stream_pass_connect
|
|
||||||
#define PASS_LISTEN stream_pass_listen
|
|
||||||
#define PASS_ACCEPT stream_pass_accept
|
|
||||||
#define PASS_TRIGGER stream_pass_trigger
|
|
||||||
#define HAS_VOLATILE_LOCKS
|
#define HAS_VOLATILE_LOCKS
|
||||||
#define BROKEN_READ_SELECT_ON_TCP_SOCKET
|
#define BROKEN_READ_SELECT_ON_TCP_SOCKET
|
||||||
#define CANT_WRITE_BEFORE_SENDING_FD
|
#define CANT_WRITE_BEFORE_SENDING_FD
|
||||||
@ -1410,13 +1406,6 @@ extern int inet_pton(int, const char *, void *);
|
|||||||
#define LOCAL_RECV_FD unix_recv_fd
|
#define LOCAL_RECV_FD unix_recv_fd
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PASS_LISTEN
|
|
||||||
#define PASS_CONNECT unix_pass_connect
|
|
||||||
#define PASS_LISTEN unix_pass_listen
|
|
||||||
#define PASS_ACCEPT unix_pass_accept
|
|
||||||
#define PASS_TRIGGER unix_pass_trigger
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined (HAVE_SYS_NDIR_H) && !defined (HAVE_SYS_DIR_H) \
|
#if !defined (HAVE_SYS_NDIR_H) && !defined (HAVE_SYS_DIR_H) \
|
||||||
&& !defined (HAVE_NDIR_H)
|
&& !defined (HAVE_NDIR_H)
|
||||||
#define HAVE_DIRENT_H
|
#define HAVE_DIRENT_H
|
||||||
|
@ -18,9 +18,7 @@ extern int unix_trigger(const char *, const char *, ssize_t, int);
|
|||||||
extern int inet_trigger(const char *, const char *, ssize_t, int);
|
extern int inet_trigger(const char *, const char *, ssize_t, int);
|
||||||
extern int fifo_trigger(const char *, const char *, ssize_t, int);
|
extern int fifo_trigger(const char *, const char *, ssize_t, int);
|
||||||
extern int stream_trigger(const char *, const char *, ssize_t, int);
|
extern int stream_trigger(const char *, const char *, ssize_t, int);
|
||||||
extern int unix_pass_trigger(const char *, const char *, ssize_t, int);
|
extern int pass_trigger(const char *, const char *, ssize_t, int);
|
||||||
|
|
||||||
#define stream_pass_trigger stream_trigger
|
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
|
@ -1,85 +0,0 @@
|
|||||||
/*++
|
|
||||||
/* NAME
|
|
||||||
/* unix_pass_listen 3
|
|
||||||
/* SUMMARY
|
|
||||||
/* start UNIX-domain file descriptor listener
|
|
||||||
/* SYNOPSIS
|
|
||||||
/* #include <listen.h>
|
|
||||||
/*
|
|
||||||
/* int unix_pass_listen(path, backlog, block_mode)
|
|
||||||
/* const char *path;
|
|
||||||
/* int backlog;
|
|
||||||
/* int block_mode;
|
|
||||||
/*
|
|
||||||
/* int unix_pass_accept(fd)
|
|
||||||
/* int fd;
|
|
||||||
/* DESCRIPTION
|
|
||||||
/* This module implements a listener that receives one file descriptor
|
|
||||||
/* across each UNIX-domain connection that is made to it.
|
|
||||||
/*
|
|
||||||
/* unix_pass_listen() creates a listener endpoint with the specified
|
|
||||||
/* permissions, and returns a file descriptor to be used for accepting
|
|
||||||
/* descriptors.
|
|
||||||
/*
|
|
||||||
/* unix_pass_accept() accepts a descriptor.
|
|
||||||
/*
|
|
||||||
/* Arguments:
|
|
||||||
/* .IP path
|
|
||||||
/* Null-terminated string with connection destination.
|
|
||||||
/* .IP backlog
|
|
||||||
/* This argument exists for compatibility and is ignored.
|
|
||||||
/* .IP block_mode
|
|
||||||
/* Either NON_BLOCKING or BLOCKING. This does not affect the
|
|
||||||
/* mode of accepted connections.
|
|
||||||
/* .IP fd
|
|
||||||
/* File descriptor returned by unix_pass_listen().
|
|
||||||
/* DIAGNOSTICS
|
|
||||||
/* Fatal errors: unix_pass_listen() aborts upon any system call failure.
|
|
||||||
/* unix_pass_accept() leaves all error handling up to the caller.
|
|
||||||
/* LICENSE
|
|
||||||
/* .ad
|
|
||||||
/* .fi
|
|
||||||
/* The Secure Mailer license must be distributed with this software.
|
|
||||||
/* AUTHOR(S)
|
|
||||||
/* Wietse Venema
|
|
||||||
/* IBM T.J. Watson Research
|
|
||||||
/* P.O. Box 704
|
|
||||||
/* Yorktown Heights, NY 10598, USA
|
|
||||||
/*--*/
|
|
||||||
|
|
||||||
/* System library. */
|
|
||||||
|
|
||||||
#include <sys_defs.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
/* Utility library. */
|
|
||||||
|
|
||||||
#include <msg.h>
|
|
||||||
#include <sane_accept.h>
|
|
||||||
#include <listen.h>
|
|
||||||
|
|
||||||
/* unix_pass_accept - accept descriptor */
|
|
||||||
|
|
||||||
int unix_pass_accept(int listen_fd)
|
|
||||||
{
|
|
||||||
const char *myname = "unix_pass_accept";
|
|
||||||
int accept_fd;
|
|
||||||
int recv_fd = -1;
|
|
||||||
|
|
||||||
accept_fd = sane_accept(listen_fd, (struct sockaddr *) 0, (SOCKADDR_SIZE *) 0);
|
|
||||||
if (accept_fd < 0) {
|
|
||||||
if (errno != EAGAIN)
|
|
||||||
msg_warn("%s: accept connection: %m", myname);
|
|
||||||
return (-1);
|
|
||||||
} else {
|
|
||||||
if (read_wait(accept_fd, 100) < 0)
|
|
||||||
msg_warn("%s: timeout receiving file descriptor: %m", myname);
|
|
||||||
else if ((recv_fd = unix_recv_fd(accept_fd)) < 0)
|
|
||||||
msg_warn("%s: cannot receive file descriptor: %m", myname);
|
|
||||||
if (close(accept_fd) < 0)
|
|
||||||
msg_warn("%s: close: %m", myname);
|
|
||||||
return (recv_fd);
|
|
||||||
}
|
|
||||||
}
|
|
@ -21,6 +21,10 @@
|
|||||||
/* int valid_ipv6_hostaddr(addr, gripe)
|
/* int valid_ipv6_hostaddr(addr, gripe)
|
||||||
/* const char *addr;
|
/* const char *addr;
|
||||||
/* int gripe;
|
/* int gripe;
|
||||||
|
/*
|
||||||
|
/* int valid_hostport(port, gripe)
|
||||||
|
/* const char *port;
|
||||||
|
/* int gripe;
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* valid_hostname() scrutinizes a hostname: the name should
|
/* valid_hostname() scrutinizes a hostname: the name should
|
||||||
/* be no longer than VALID_HOSTNAME_LEN characters, should
|
/* be no longer than VALID_HOSTNAME_LEN characters, should
|
||||||
@ -42,6 +46,9 @@
|
|||||||
/* These routines operate silently unless the gripe parameter
|
/* These routines operate silently unless the gripe parameter
|
||||||
/* specifies a non-zero value. The macros DO_GRIPE and DONT_GRIPE
|
/* specifies a non-zero value. The macros DO_GRIPE and DONT_GRIPE
|
||||||
/* provide suitable constants.
|
/* provide suitable constants.
|
||||||
|
/*
|
||||||
|
/* valid_hostport() requires that the input is a valid string
|
||||||
|
/* representation of a TCP or UDP port number.
|
||||||
/* BUGS
|
/* BUGS
|
||||||
/* valid_hostmumble() does not guarantee that string lengths
|
/* valid_hostmumble() does not guarantee that string lengths
|
||||||
/* fit the buffer sizes defined in myaddrinfo(3h).
|
/* fit the buffer sizes defined in myaddrinfo(3h).
|
||||||
@ -65,6 +72,7 @@
|
|||||||
#include <sys_defs.h>
|
#include <sys_defs.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
/* Utility library. */
|
/* Utility library. */
|
||||||
|
|
||||||
@ -337,6 +345,32 @@ int valid_ipv6_hostaddr(const char *addr, int gripe)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* valid_hostport - validate numeric port */
|
||||||
|
|
||||||
|
int valid_hostport(const char *str, int gripe)
|
||||||
|
{
|
||||||
|
const char *myname = "valid_hostport";
|
||||||
|
int port;
|
||||||
|
|
||||||
|
if (str[0] == '0' && str[1] != 0) {
|
||||||
|
if (gripe)
|
||||||
|
msg_warn("%s: leading zero in port number: %.100s", myname, str);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
if (alldig(str) == 0) {
|
||||||
|
if (gripe)
|
||||||
|
msg_warn("%s: non-numeric port number: %.100s", myname, str);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
if (strlen(str) > strlen("65535")
|
||||||
|
|| (port = atoi(str)) > 65535 || port < 0) {
|
||||||
|
if (gripe)
|
||||||
|
msg_warn("%s: out-of-range port number: %.100s", myname, str);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -23,6 +23,7 @@ extern int valid_hostname(const char *, int);
|
|||||||
extern int valid_hostaddr(const char *, int);
|
extern int valid_hostaddr(const char *, int);
|
||||||
extern int valid_ipv4_hostaddr(const char *, int);
|
extern int valid_ipv4_hostaddr(const char *, int);
|
||||||
extern int valid_ipv6_hostaddr(const char *, int);
|
extern int valid_ipv6_hostaddr(const char *, int);
|
||||||
|
extern int valid_hostport(const char *, int);
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
|
@ -324,16 +324,21 @@
|
|||||||
/* This involves allocation of additional memory that normally isn't
|
/* This involves allocation of additional memory that normally isn't
|
||||||
/* used.
|
/* used.
|
||||||
/* .IP "VSTREAM_CTL_BUFSIZE (ssize_t)"
|
/* .IP "VSTREAM_CTL_BUFSIZE (ssize_t)"
|
||||||
/* Specify a non-default write buffer size, or zero to implement
|
/* Specify a non-default buffer size, or zero to implement
|
||||||
/* a no-op. Requests to shrink an existing buffer size are
|
/* a no-op. Requests to resize a fixed-size buffer (stderr)
|
||||||
/* ignored. Requests to change a fixed-size buffer (stdin,
|
/* are not allowed.
|
||||||
/* stdout, stderr) are not allowed.
|
|
||||||
/*
|
/*
|
||||||
/* NOTE: the VSTREAM_CTL_BUFSIZE request specifies intent, not
|
/* NOTE: the VSTREAM_CTL_BUFSIZE request specifies intent, not
|
||||||
/* reality. Actual buffer sizes are not updated immediately.
|
/* reality. Actual buffer sizes are not updated immediately.
|
||||||
/* Instead, an existing write buffer will be resized when it
|
/* Instead, a write buffer size will be updated when writing
|
||||||
/* is full, and an existing read buffer will be resized when
|
/* to a stream for the first time, or when writing to a full
|
||||||
/* the buffer is filled.
|
/* buffer, and a read buffer size will be updated when reading
|
||||||
|
/* from a stream for the first time, or when reading from an
|
||||||
|
/* empty buffer.
|
||||||
|
/*
|
||||||
|
/* NOTE: the vstream_*printf() routines may silently expand a
|
||||||
|
/* buffer, so that the result of some %letter specifiers can
|
||||||
|
/* be written to contiguous memory.
|
||||||
/*
|
/*
|
||||||
/* NOTE: the VSTREAM_CTL_BUFSIZE argument type is ssize_t, not
|
/* NOTE: the VSTREAM_CTL_BUFSIZE argument type is ssize_t, not
|
||||||
/* int. Use an explicit cast to avoid problems on LP64
|
/* int. Use an explicit cast to avoid problems on LP64
|
||||||
@ -621,10 +626,17 @@ static void vstream_buf_alloc(VBUF *bp, ssize_t len)
|
|||||||
ssize_t used = bp->ptr - bp->data;
|
ssize_t used = bp->ptr - bp->data;
|
||||||
const char *myname = "vstream_buf_alloc";
|
const char *myname = "vstream_buf_alloc";
|
||||||
|
|
||||||
if (len < bp->len)
|
/*
|
||||||
msg_panic("%s: attempt to shrink buffer", myname);
|
* Don't shrink a non-empty read buffer, or a non-flushed write buffer.
|
||||||
|
*/
|
||||||
|
if (len <= 0)
|
||||||
|
msg_panic("%s: bad buffer length: %ld", myname, (long) len);
|
||||||
|
if (len < bp->len
|
||||||
|
&& (((bp->flags & VSTREAM_FLAG_READ) && bp->cnt != 0)
|
||||||
|
|| ((bp->flags & VSTREAM_FLAG_WRITE) && bp->cnt != bp->len)))
|
||||||
|
msg_panic("%s: attempt to shrink non-empty buffer", myname);
|
||||||
if (bp->flags & VSTREAM_FLAG_FIXED)
|
if (bp->flags & VSTREAM_FLAG_FIXED)
|
||||||
msg_panic("%s: unable to extend fixed-size buffer", myname);
|
msg_panic("%s: attempt to resize fixed-length buffer", myname);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Late buffer allocation allows the user to override the default policy.
|
* Late buffer allocation allows the user to override the default policy.
|
||||||
@ -842,7 +854,7 @@ static int vstream_buf_get_ready(VBUF *bp)
|
|||||||
* allocation gives the application a chance to override the default
|
* allocation gives the application a chance to override the default
|
||||||
* buffering policy.
|
* buffering policy.
|
||||||
*/
|
*/
|
||||||
if (bp->len < stream->req_bufsize)
|
if (bp->len != stream->req_bufsize)
|
||||||
vstream_buf_alloc(bp, stream->req_bufsize);
|
vstream_buf_alloc(bp, stream->req_bufsize);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -956,6 +968,8 @@ static int vstream_buf_put_ready(VBUF *bp)
|
|||||||
if (VSTREAM_FFLUSH_SOME(stream))
|
if (VSTREAM_FFLUSH_SOME(stream))
|
||||||
return (VSTREAM_EOF);
|
return (VSTREAM_EOF);
|
||||||
}
|
}
|
||||||
|
if (bp->len > stream->req_bufsize)
|
||||||
|
vstream_buf_alloc(bp, stream->req_bufsize);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1467,8 +1481,7 @@ void vstream_control(VSTREAM *stream, int name,...)
|
|||||||
if (req_bufsize < 0)
|
if (req_bufsize < 0)
|
||||||
msg_panic("VSTREAM_CTL_BUFSIZE with negative size: %ld",
|
msg_panic("VSTREAM_CTL_BUFSIZE with negative size: %ld",
|
||||||
(long) req_bufsize);
|
(long) req_bufsize);
|
||||||
if (stream != VSTREAM_ERR
|
if (req_bufsize > 0 && stream != VSTREAM_ERR)
|
||||||
&& req_bufsize > stream->req_bufsize)
|
|
||||||
stream->req_bufsize = req_bufsize;
|
stream->req_bufsize = req_bufsize;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1578,3 +1591,44 @@ const char *vstream_peek_data(VSTREAM *vp)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TEST
|
||||||
|
|
||||||
|
static void copy_line(ssize_t bufsize)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
vstream_control(VSTREAM_IN, VSTREAM_CTL_BUFSIZE, bufsize, VSTREAM_CTL_END);
|
||||||
|
vstream_control(VSTREAM_OUT, VSTREAM_CTL_BUFSIZE, bufsize, VSTREAM_CTL_END);
|
||||||
|
while ((c = VSTREAM_GETC(VSTREAM_IN)) != VSTREAM_EOF) {
|
||||||
|
VSTREAM_PUTC(c, VSTREAM_OUT);
|
||||||
|
if (c == '\n')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
vstream_fflush(VSTREAM_OUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void printf_number(void)
|
||||||
|
{
|
||||||
|
vstream_printf("%d\n", __MAXINT__(int));
|
||||||
|
vstream_fflush(VSTREAM_OUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exercise some of the features.
|
||||||
|
*/
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test buffer expansion and shrinking. Formatted print may silently
|
||||||
|
* expand the write buffer and cause multiple bytes to be written.
|
||||||
|
*/
|
||||||
|
copy_line(1); /* one-byte read/write */
|
||||||
|
copy_line(2); /* two-byte read/write */
|
||||||
|
copy_line(1); /* one-byte read/write */
|
||||||
|
printf_number(); /* multi-byte write */
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -207,6 +207,8 @@ extern const char *vstream_peek_data(VSTREAM *);
|
|||||||
extern int vstream_tweak_sock(VSTREAM *);
|
extern int vstream_tweak_sock(VSTREAM *);
|
||||||
extern int vstream_tweak_tcp(VSTREAM *);
|
extern int vstream_tweak_tcp(VSTREAM *);
|
||||||
|
|
||||||
|
#define vstream_flags(stream) ((const int) (stream)->buf.flags)
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
|
Loading…
x
Reference in New Issue
Block a user