2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-22 09:57:34 +00:00

postfix-3.6-20200920

This commit is contained in:
Wietse Venema 2020-09-20 00:00:00 -05:00 committed by Viktor Dukhovni
parent c3f7b853c3
commit e4f3f9ea70
76 changed files with 1186 additions and 500 deletions

2
postfix/.indent.pro vendored
View File

@ -1,4 +1,4 @@
-TABOUNCE
-TABOUNCE_STATE
-TADDR_MATCH_LIST
-TADDR_PATTERN
-TALIAS_TOKEN

View File

@ -25057,6 +25057,8 @@ Apologies for any names omitted.
mantools/man2html, mantools/readme2html, proto/*_README.html,
proto/INSTALL.html, proto/postconf.html.prolog, html/index.html.
20200830
Refactor: moved the SASL mechanism filter code from the
Postfix SMTP client to a library module, so that it can be
reused in the Postfix SMTP server. Files: smtp/smtp_sasl_proto.c,
@ -25071,3 +25073,83 @@ Apologies for any names omitted.
wants to anounce EXTERNAL support for which Postfix support
does not exist. Files: smtpd/smtpd.[hc], smtpd_sasl_glue.[hc],
global/mail_params.h, proto/postconf.proto, mantools/postlink.
20200906
Cleanup: missing file. File: src/postqueue/.indent.pro.
Cleanup: uninitialized value in unit test code. File:
global/haproxy_srvr.c.
Cleanup: duplicate 'const' in argument declaration. File:
src/global/sasl_mech_filter.c.
20200906-18
Baseline is postfix-3.6-20200906.
Other debt: internal protocol identification. Each server
sends the name of the internal protocol that it implements,
and each client logs a warning if it receives the wrong
protocol name. With this, a client-server mismatch results
in a better error message. It is a good idea to "postfix
stop" before updating, or before backing out to an earlier
relase. To make this work consistently, a few internal
protocols were converted from "client speaks first" to
"server speaks first". Files: anvil/anvil.c, bounce/bounce.c,
cleanup/cleanup.c, flush/flush.c, global/abounce.c,
global/anvil_clnt.c, global/bounce.c, global/clnt_stream.c,
global/clnt_stream.h, global/defer.c, global/deliver_pass.c,
global/deliver_request.c, global/dict_proxy.c, global/flush_clnt.c,
global/mail_command_client.c, global/mail_proto.h,
global/mail_stream.c, global/mail_version.h, global/post_mail.c,
global/resolve_clnt.c, global/rewrite_clnt.c, global/scache_clnt.c,
global/trace.c, global/verify_clnt.c, local/forward.c,
master/event_server.c, master/mail_server.h, master/multi_server.c,
oqmgr/qmgr_deliver.c, pickup/pickup.c, postdrop/postdrop.c,
postqueue/postqueue.c, postscreen/postscreen_starttls.c,
proxymap/proxymap.c, qmgr/qmgr_deliver.c, scache/scache.c,
showq/showq.c, tls/tls_mgr.c, tls/tls_proxy_clnt.c,
tlsmgr/tlsmgr.c, tlsproxy/tlsproxy.c,
trivial-rewrite/trivial-rewrite.c, util/attr.h, util/attr_clnt.c,
util/attr_clnt.h, util/attr_print0.c, util/attr_print64.c,
util/attr_print_plain.c, util/attr_scan0.c, util/attr_scan64.c,
util/attr_scan_plain.c, util/auto_clnt.c, util/auto_clnt.h,
verify/verify.c.
Debt: during the conversion of some internal protocols to
"server speaks first", took the opportunity to improve how
event-driven client implementations handle a server that
is locked up. Files: global/abounce.c,
postscreen/postscreen_starttls.c.
20200919
Cleanup: eliminated a silly optimization for lazy clients
that read the "server speaks first" protocol announcement
after sending a client request. Files: src/anvil/anvil.c,
src/bounce/bounce.c, src/flush/flush.c, src/global/abounce.c,
src/global/anvil_clnt.c, src/global/deliver_pass.c,
src/global/deliver_request.c, src/global/dict_proxy.c,
src/global/mail_command_client.c, src/global/mail_stream.c,
src/global/resolve_clnt.c, src/global/rewrite_clnt.c,
src/global/scache_clnt.c, src/global/verify_clnt.c,
src/local/forward.c, src/oqmgr/qmgr_deliver.c, src/pickup/pickup.c,
src/postqueue/postqueue.c, src/postscreen/postscreen_starttls.c,
src/proxymap/proxymap.c, src/qmgr/qmgr_deliver.c,
src/scache/scache.c, src/showq/showq.c, src/tlsmgr/tlsmgr.c,
src/tlsproxy/tlsproxy.c, src/tls/tls_mgr.c,
src/tls/tls_proxy_clnt.c, src/trivial-rewrite/trivial-rewrite.c,
src/verify/verify.c.
Cleanup: factored out some duplicate showq client code.
File: postqueue/postqueue.c.
20200920
Cleanup: deleted the percentm module. It was obsoleted in
19971027 by the vbuf_print() string formatter for VSTREAM
and VSTRING objects. Files: util/percentm.[hc].
Cleanup: replaced hard-coded 'private' with named constant.
File: global/scache_clnt.c.

View File

@ -25,6 +25,22 @@ more recent Eclipse Public License 2.0. Recipients can choose to take
the software under the license of their choice. Those who are more
comfortable with the IPL can continue with that license.
Incompatible change with snapshot 20200920
==========================================
Internal protocols have changed. You need to "postfix stop" before
updating, or before backing out to an earlier release, otherwise
long-running daemons (pickup, qmgr, verify, tlsproxy, postscreen)
may fail to communicate with the rest of Postfix (warnings, timeouts).
The purpose of this change is to produce better error messages, for
example, when someone configures the discard daemon as a bounce
service in master.cf, or vice versa.
This change will break third-party code that implements a
Postfix-internal protocol such as qpsmtpd. Programs that depend on
Postfix internal details are not supported.
Incompatible change with snapshot 20200705
==========================================

View File

@ -1,5 +1,23 @@
Wish list:
Does tlsproxy terminate to soon after 'postfix reload'?
The documented order of relay/recipient restrictions differs
from the implementation. This may need a new compatibility
parameter. For example:
http://postfix.1071664.n5.nabble.com/Relay-attempt-questions-td103646.html
Hardening the half-dane behavior: some sites may rely on
current behavior which allows original MX domain name for
certificate matches. Requires a new (compatibility) parameter
setting?
multi_server applications could be migrated to event_server;
after accept(), they would have to set up their own read
event callback for handling requests.
Maybe expand %m to "application error" when errno == 0.
smtp_sasl_tls_security_options = noanonymous, and make
smtp_sasl_security_options default dependent on the
smtp_sasl_tls_security_options default (i.e. reverse the

View File

@ -162,11 +162,12 @@ CLEANUP(8) CLEANUP(8)
Postfix 2.6 the default protocol is 2.
<b><a href="postconf.5.html#milter_default_action">milter_default_action</a> (tempfail)</b>
The default action when a Milter (mail filter) application is
unavailable or mis-configured.
The default action when a Milter (mail filter) response is
unavailable (for example, bad Postfix configuration or Milter
failure).
<b><a href="postconf.5.html#milter_macro_daemon_name">milter_macro_daemon_name</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
The {daemon_name} macro value for Milter (mail filter) applica-
The {daemon_name} macro value for Milter (mail filter) applica-
tions.
<b><a href="postconf.5.html#milter_macro_v">milter_macro_v</a> ($<a href="postconf.5.html#mail_name">mail_name</a> $<a href="postconf.5.html#mail_version">mail_version</a>)</b>
@ -177,45 +178,45 @@ CLEANUP(8) CLEANUP(8)
tion, and for negotiating protocol options.
<b><a href="postconf.5.html#milter_command_timeout">milter_command_timeout</a> (30s)</b>
The time limit for sending an SMTP command to a Milter (mail
The time limit for sending an SMTP command to a Milter (mail
filter) application, and for receiving the response.
<b><a href="postconf.5.html#milter_content_timeout">milter_content_timeout</a> (300s)</b>
The time limit for sending message content to a Milter (mail
The time limit for sending message content to a Milter (mail
filter) application, and for receiving the response.
<b><a href="postconf.5.html#milter_connect_macros">milter_connect_macros</a> (see 'postconf -d' output)</b>
The macros that are sent to Milter (mail filter) applications
The macros that are sent to Milter (mail filter) applications
after completion of an SMTP connection.
<b><a href="postconf.5.html#milter_helo_macros">milter_helo_macros</a> (see 'postconf -d' output)</b>
The macros that are sent to Milter (mail filter) applications
The macros that are sent to Milter (mail filter) applications
after the SMTP HELO or EHLO command.
<b><a href="postconf.5.html#milter_mail_macros">milter_mail_macros</a> (see 'postconf -d' output)</b>
The macros that are sent to Milter (mail filter) applications
The macros that are sent to Milter (mail filter) applications
after the SMTP MAIL FROM command.
<b><a href="postconf.5.html#milter_rcpt_macros">milter_rcpt_macros</a> (see 'postconf -d' output)</b>
The macros that are sent to Milter (mail filter) applications
The macros that are sent to Milter (mail filter) applications
after the SMTP RCPT TO command.
<b><a href="postconf.5.html#milter_data_macros">milter_data_macros</a> (see 'postconf -d' output)</b>
The macros that are sent to version 4 or higher Milter (mail
The macros that are sent to version 4 or higher Milter (mail
filter) applications after the SMTP DATA command.
<b><a href="postconf.5.html#milter_unknown_command_macros">milter_unknown_command_macros</a> (see 'postconf -d' output)</b>
The macros that are sent to version 3 or higher Milter (mail
The macros that are sent to version 3 or higher Milter (mail
filter) applications after an unknown SMTP command.
<b><a href="postconf.5.html#milter_end_of_data_macros">milter_end_of_data_macros</a> (see 'postconf -d' output)</b>
The macros that are sent to Milter (mail filter) applications
The macros that are sent to Milter (mail filter) applications
after the message end-of-data.
Available in Postfix version 2.5 and later:
<b><a href="postconf.5.html#milter_end_of_header_macros">milter_end_of_header_macros</a> (see 'postconf -d' output)</b>
The macros that are sent to Milter (mail filter) applications
The macros that are sent to Milter (mail filter) applications
after the end of the message header.
Available in Postfix version 2.7 and later:
@ -227,8 +228,8 @@ CLEANUP(8) CLEANUP(8)
Available in Postfix version 3.1 and later:
<b><a href="postconf.5.html#milter_macro_defaults">milter_macro_defaults</a> (empty)</b>
Optional list of <i>name=value</i> pairs that specify default values
for arbitrary macros that Postfix may send to Milter applica-
Optional list of <i>name=value</i> pairs that specify default values
for arbitrary macros that Postfix may send to Milter applica-
tions.
<b>MIME PROCESSING CONTROLS</b>
@ -254,91 +255,91 @@ CLEANUP(8) CLEANUP(8)
ing information.
<b><a href="postconf.5.html#strict_mime_encoding_domain">strict_mime_encoding_domain</a> (no)</b>
Reject mail with invalid Content-Transfer-Encoding: information
Reject mail with invalid Content-Transfer-Encoding: information
for the message/* or multipart/* MIME content types.
Available in Postfix version 2.5 and later:
<b><a href="postconf.5.html#detect_8bit_encoding_header">detect_8bit_encoding_header</a> (yes)</b>
Automatically detect 8BITMIME body content by looking at Con-
tent-Transfer-Encoding: message headers; historically, this
Automatically detect 8BITMIME body content by looking at Con-
tent-Transfer-Encoding: message headers; historically, this
behavior was hard-coded to be "always on".
<b>AUTOMATIC BCC RECIPIENT CONTROLS</b>
Postfix can automatically add BCC (blind carbon copy) when mail enters
Postfix can automatically add BCC (blind carbon copy) when mail enters
the mail system:
<b><a href="postconf.5.html#always_bcc">always_bcc</a> (empty)</b>
Optional address that receives a "blind carbon copy" of each
Optional address that receives a "blind carbon copy" of each
message that is received by the Postfix mail system.
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#sender_bcc_maps">sender_bcc_maps</a> (empty)</b>
Optional BCC (blind carbon-copy) address lookup tables, indexed
Optional BCC (blind carbon-copy) address lookup tables, indexed
by sender address.
<b><a href="postconf.5.html#recipient_bcc_maps">recipient_bcc_maps</a> (empty)</b>
Optional BCC (blind carbon-copy) address lookup tables, indexed
Optional BCC (blind carbon-copy) address lookup tables, indexed
by recipient address.
<b>ADDRESS TRANSFORMATION CONTROLS</b>
Address rewriting is delegated to the <a href="trivial-rewrite.8.html"><b>trivial-rewrite</b>(8)</a> daemon. The
Address rewriting is delegated to the <a href="trivial-rewrite.8.html"><b>trivial-rewrite</b>(8)</a> daemon. The
<a href="cleanup.8.html"><b>cleanup</b>(8)</a> server implements table driven address mapping.
<b><a href="postconf.5.html#empty_address_recipient">empty_address_recipient</a> (MAILER-DAEMON)</b>
The recipient of mail addressed to the null address.
<b><a href="postconf.5.html#canonical_maps">canonical_maps</a> (empty)</b>
Optional address mapping lookup tables for message headers and
Optional address mapping lookup tables for message headers and
envelopes.
<b><a href="postconf.5.html#recipient_canonical_maps">recipient_canonical_maps</a> (empty)</b>
Optional address mapping lookup tables for envelope and header
Optional address mapping lookup tables for envelope and header
recipient addresses.
<b><a href="postconf.5.html#sender_canonical_maps">sender_canonical_maps</a> (empty)</b>
Optional address mapping lookup tables for envelope and header
Optional address mapping lookup tables for envelope and header
sender addresses.
<b><a href="postconf.5.html#masquerade_classes">masquerade_classes</a> (envelope_sender, header_sender, header_recipient)</b>
What addresses are subject to address masquerading.
<b><a href="postconf.5.html#masquerade_domains">masquerade_domains</a> (empty)</b>
Optional list of domains whose subdomain structure will be
Optional list of domains whose subdomain structure will be
stripped off in email addresses.
<b><a href="postconf.5.html#masquerade_exceptions">masquerade_exceptions</a> (empty)</b>
Optional list of user names that are not subjected to address
masquerading, even when their addresses match $<a href="postconf.5.html#masquerade_domains">masquer</a>-
Optional list of user names that are not subjected to address
masquerading, even when their addresses match $<a href="postconf.5.html#masquerade_domains">masquer</a>-
<a href="postconf.5.html#masquerade_domains">ade_domains</a>.
<b><a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a> (canonical, virtual)</b>
What address lookup tables copy an address extension from the
What address lookup tables copy an address extension from the
lookup key to the lookup result.
Available before Postfix version 2.0:
<b><a href="postconf.5.html#virtual_maps">virtual_maps</a> (empty)</b>
Optional lookup tables with a) names of domains for which all
addresses are aliased to addresses in other local or remote
Optional lookup tables with a) names of domains for which all
addresses are aliased to addresses in other local or remote
domains, and b) addresses that are aliased to addresses in other
local or remote domains.
Available in Postfix version 2.0 and later:
<b><a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> ($<a href="postconf.5.html#virtual_maps">virtual_maps</a>)</b>
Optional lookup tables that alias specific mail addresses or
Optional lookup tables that alias specific mail addresses or
domains to other local or remote address.
Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#canonical_classes">canonical_classes</a> (envelope_sender, envelope_recipient, header_sender,</b>
<b><a href="postconf.5.html#canonical_classes">canonical_classes</a> (envelope_sender, envelope_recipient, header_sender,</b>
<b>header_recipient)</b>
What addresses are subject to <a href="postconf.5.html#canonical_maps">canonical_maps</a> address mapping.
<b><a href="postconf.5.html#recipient_canonical_classes">recipient_canonical_classes</a> (envelope_recipient, header_recipient)</b>
What addresses are subject to <a href="postconf.5.html#recipient_canonical_maps">recipient_canonical_maps</a> address
What addresses are subject to <a href="postconf.5.html#recipient_canonical_maps">recipient_canonical_maps</a> address
mapping.
<b><a href="postconf.5.html#sender_canonical_classes">sender_canonical_classes</a> (envelope_sender, header_sender)</b>
@ -346,8 +347,8 @@ CLEANUP(8) CLEANUP(8)
ping.
<b><a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> (empty)</b>
Don't rewrite message headers from remote clients at all when
this parameter is empty; otherwise, rewrite message headers and
Don't rewrite message headers from remote clients at all when
this parameter is empty; otherwise, rewrite message headers and
append the specified domain name to incomplete addresses.
<b>RESOURCE AND RATE CONTROLS</b>
@ -357,7 +358,7 @@ CLEANUP(8) CLEANUP(8)
<a href="showq.8.html"><b>showq</b>(8)</a> queue displays.
<b><a href="postconf.5.html#header_size_limit">header_size_limit</a> (102400)</b>
The maximal amount of memory in bytes for storing a message
The maximal amount of memory in bytes for storing a message
header.
<b><a href="postconf.5.html#hopcount_limit">hopcount_limit</a> (50)</b>
@ -365,17 +366,17 @@ CLEANUP(8) CLEANUP(8)
in the primary message headers.
<b><a href="postconf.5.html#in_flow_delay">in_flow_delay</a> (1s)</b>
Time to pause before accepting a new message, when the message
Time to pause before accepting a new message, when the message
arrival rate exceeds the message delivery rate.
<b><a href="postconf.5.html#message_size_limit">message_size_limit</a> (10240000)</b>
The maximal size in bytes of a message, including envelope
The maximal size in bytes of a message, including envelope
information.
Available in Postfix version 2.0 and later:
<b><a href="postconf.5.html#header_address_token_limit">header_address_token_limit</a> (10240)</b>
The maximal number of address tokens are allowed in an address
The maximal number of address tokens are allowed in an address
message header.
<b><a href="postconf.5.html#mime_boundary_length_limit">mime_boundary_length_limit</a> (2048)</b>
@ -391,7 +392,7 @@ CLEANUP(8) CLEANUP(8)
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#virtual_alias_expansion_limit">virtual_alias_expansion_limit</a> (1000)</b>
The maximal number of addresses that virtual alias expansion
The maximal number of addresses that virtual alias expansion
produces from each original recipient.
<b><a href="postconf.5.html#virtual_alias_recursion_limit">virtual_alias_recursion_limit</a> (1000)</b>
@ -400,50 +401,50 @@ CLEANUP(8) CLEANUP(8)
Available in Postfix version 3.0 and later:
<b><a href="postconf.5.html#virtual_alias_address_length_limit">virtual_alias_address_length_limit</a> (1000)</b>
The maximal length of an email address after virtual alias
The maximal length of an email address after virtual alias
expansion.
<b>SMTPUTF8 CONTROLS</b>
Preliminary SMTPUTF8 support is introduced with Postfix 3.0.
<b><a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> (yes)</b>
Enable preliminary SMTPUTF8 support for the protocols described
Enable preliminary SMTPUTF8 support for the protocols described
in <a href="http://tools.ietf.org/html/rfc6531">RFC 6531</a>..6533.
<b><a href="postconf.5.html#smtputf8_autodetect_classes">smtputf8_autodetect_classes</a> (sendmail, verify)</b>
Detect that a message requires SMTPUTF8 support for the speci-
Detect that a message requires SMTPUTF8 support for the speci-
fied mail origin classes.
Available in Postfix version 3.2 and later:
<b><a href="postconf.5.html#enable_idna2003_compatibility">enable_idna2003_compatibility</a> (no)</b>
Enable 'transitional' compatibility between IDNA2003 and
IDNA2008, when converting UTF-8 domain names to/from the ASCII
Enable 'transitional' compatibility between IDNA2003 and
IDNA2008, when converting UTF-8 domain names to/from the ASCII
form that is used for DNS lookups.
<b>MISCELLANEOUS CONTROLS</b>
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
figuration files.
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
How much time a Postfix daemon process may take to handle a
How much time a Postfix daemon process may take to handle a
request before it is terminated by a built-in watchdog timer.
<b><a href="postconf.5.html#delay_logging_resolution_limit">delay_logging_resolution_limit</a> (2)</b>
The maximal number of digits after the decimal point when log-
The maximal number of digits after the decimal point when log-
ging sub-second delay values.
<b><a href="postconf.5.html#delay_warning_time">delay_warning_time</a> (0h)</b>
The time after which the sender receives a copy of the message
The time after which the sender receives a copy of the message
headers of mail that is still queued.
<b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
The time limit for sending or receiving information over an
The time limit for sending or receiving information over an
internal communication channel.
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
The maximum amount of time that an idle Postfix daemon process
The maximum amount of time that an idle Postfix daemon process
waits for an incoming connection before terminating voluntarily.
<b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
@ -454,7 +455,7 @@ CLEANUP(8) CLEANUP(8)
The internet hostname of this mail system.
<b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
The domain name that locally-posted mail appears to come from,
The domain name that locally-posted mail appears to come from,
and that locally posted mail is delivered to.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
@ -467,21 +468,21 @@ CLEANUP(8) CLEANUP(8)
The location of the Postfix top-level queue directory.
<b><a href="postconf.5.html#soft_bounce">soft_bounce</a> (no)</b>
Safety net to keep mail queued that would otherwise be returned
Safety net to keep mail queued that would otherwise be returned
to the sender.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
A prefix that is prepended to the process name in syslog
A prefix that is prepended to the process name in syslog
records, so that, for example, "smtpd" becomes "prefix/smtpd".
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#enable_original_recipient">enable_original_recipient</a> (yes)</b>
Enable support for the original recipient address after an
address is rewritten to a different address (for example with
Enable support for the original recipient address after an
address is rewritten to a different address (for example with
aliasing or with canonical mapping).
Available in Postfix 3.3 and later:
@ -492,7 +493,7 @@ CLEANUP(8) CLEANUP(8)
Available in Postfix 3.5 and later:
<b>info_log_address_format (external)</b>
The email address form that will be used in non-debug logging
The email address form that will be used in non-debug logging
(info, warning, etc.).
<b>FILES</b>

View File

@ -169,8 +169,8 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8)
explicit ".example.com" pattern.
<b><a href="postconf.5.html#relayhost">relayhost</a> (empty)</b>
The next-hop destination of non-local mail; overrides non-local
domains in recipient addresses.
The next-hop destination(s) for non-local mail; overrides
non-<a href="ADDRESS_CLASS_README.html#local_domain_class">local domains</a> in recipient addresses.
<b><a href="postconf.5.html#transport_maps">transport_maps</a> (empty)</b>
Optional lookup tables with mappings from recipient address to

View File

@ -164,8 +164,9 @@ The mail filter protocol version and optional protocol extensions
for communication with a Milter application; prior to Postfix 2.6
the default protocol is 2.
.IP "\fBmilter_default_action (tempfail)\fR"
The default action when a Milter (mail filter) application is
unavailable or mis\-configured.
The default action when a Milter (mail filter) response is
unavailable (for example, bad Postfix configuration or Milter
failure).
.IP "\fBmilter_macro_daemon_name ($myhostname)\fR"
The {daemon_name} macro value for Milter (mail filter) applications.
.IP "\fBmilter_macro_v ($mail_name $mail_version)\fR"

View File

@ -175,7 +175,7 @@ A list of Postfix features where the pattern "example.com" also
matches subdomains of example.com,
instead of requiring an explicit ".example.com" pattern.
.IP "\fBrelayhost (empty)\fR"
The next\-hop destination of non\-local mail; overrides non\-local
The next\-hop destination(s) for non\-local mail; overrides non\-local
domains in recipient addresses.
.IP "\fBtransport_maps (empty)\fR"
Optional lookup tables with mappings from recipient address to

View File

@ -1006,6 +1006,21 @@ static void post_jail_init(char *unused_name, char **unused_argv)
MAIL_VERSION_STAMP_DECLARE;
/* post_accept - announce our protocol */
static void post_accept(VSTREAM *stream, char *unused_name,
char **unused_argv, HTABLE *unused_table)
{
/*
* Announce the protocol.
*/
attr_print_plain(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_ANVIL),
ATTR_TYPE_END);
(void) vstream_fflush(stream);
}
/* main - pass control to the multi-threaded skeleton */
int main(int argc, char **argv)
@ -1024,6 +1039,7 @@ int main(int argc, char **argv)
multi_server_main(argc, argv, anvil_service,
CA_MAIL_SERVER_TIME_TABLE(time_table),
CA_MAIL_SERVER_POST_INIT(post_jail_init),
CA_MAIL_SERVER_POST_ACCEPT(post_accept),
CA_MAIL_SERVER_SOLITARY,
CA_MAIL_SERVER_PRE_DISCONN(anvil_service_done),
CA_MAIL_SERVER_EXIT(anvil_status_dump),

View File

@ -527,6 +527,14 @@ static void bounce_service(VSTREAM *client, char *service_name, char **argv)
if (mail_queue_name_ok(service_name) == 0)
msg_fatal("malformed service name: %s", service_name);
/*
* Announce the protocol.
*/
attr_print(client, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_BOUNCE),
ATTR_TYPE_END);
(void) vstream_fflush(client);
/*
* Read and validate the first parameter of the client request. Let the
* request-specific protocol routines take care of the remainder.

View File

@ -144,8 +144,9 @@
/* for communication with a Milter application; prior to Postfix 2.6
/* the default protocol is 2.
/* .IP "\fBmilter_default_action (tempfail)\fR"
/* The default action when a Milter (mail filter) application is
/* unavailable or mis-configured.
/* The default action when a Milter (mail filter) response is
/* unavailable (for example, bad Postfix configuration or Milter
/* failure).
/* .IP "\fBmilter_macro_daemon_name ($myhostname)\fR"
/* The {daemon_name} macro value for Milter (mail filter) applications.
/* .IP "\fBmilter_macro_v ($mail_name $mail_version)\fR"
@ -503,6 +504,7 @@ static void cleanup_service(VSTREAM *src, char *unused_service, char **argv)
* about the whole operation.
*/
attr_print(src, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP),
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, state->queue_id),
ATTR_TYPE_END);
if (attr_scan(src, ATTR_FLAG_STRICT,

View File

@ -699,6 +699,14 @@ static int flush_request_receive(VSTREAM *client_stream, VSTRING *request)
{
int count;
/*
* Announce the protocol.
*/
attr_print(client_stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_FLUSH),
ATTR_TYPE_END);
(void) vstream_fflush(client_stream);
/*
* Kluge: choose the protocol depending on the request size.
*/

View File

@ -169,6 +169,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -202,10 +207,11 @@ typedef struct {
int command; /* bounce request type */
int flags; /* bounce options */
char *id; /* queue ID for logging */
VSTRING *request; /* serialized request */
ABOUNCE_FN callback; /* application callback */
void *context; /* application context */
VSTREAM *fp; /* server I/O handle */
} ABOUNCE;
} ABOUNCE_STATE;
/*
* Encapsulate common code.
@ -215,11 +221,6 @@ typedef struct {
event_request_timer((callback), (context), (timeout)); \
} while (0)
#define ABOUNCE_EVENT_DISABLE(fd, callback, context) do { \
event_cancel_timer((callback), (context)); \
event_disable_readwrite(fd); \
} while (0)
/*
* If we set the reply timeout too short, then we make the problem worse by
* increasing overload. With 1000s timeout mail will keep flowing, but there
@ -228,11 +229,30 @@ typedef struct {
*/
#define ABOUNCE_TIMEOUT 1000
/*
* The initial buffer size for a serialized request.
*/
#define ABOUNCE_BUFSIZE VSTREAM_BUFSIZE
/*
* We share most of the verp and non-verp code paths.
*/
#define ABOUNCE_NO_VERP ((char *) 0)
/*
* SLMs.
*/
#define STR(x) vstring_str(x)
#define LEN(x) VSTRING_LEN(x)
/* abounce_done - deliver status to application and clean up pseudo thread */
static void abounce_done(ABOUNCE *ap, int status)
static void abounce_done(ABOUNCE_STATE *ap, int status)
{
(void) vstream_fclose(ap->fp);
if (ap->fp) {
event_disable_readwrite(vstream_fileno(ap->fp));
(void) vstream_fclose(ap->fp);
}
if (status != 0 && (ap->flags & BOUNCE_FLAG_CLEAN) == 0)
msg_info("%s: status=deferred (%s failed)", ap->id,
ap->command == BOUNCE_CMD_FLUSH ? "bounce" :
@ -242,65 +262,125 @@ static void abounce_done(ABOUNCE *ap, int status)
"whatever");
ap->callback(status, ap->context);
myfree(ap->id);
vstring_free(ap->request);
myfree((void *) ap);
}
/* abounce_event - resume pseudo thread after server reply event */
/* abounce_receive - receive server reply */
static void abounce_event(int event, void *context)
static void abounce_receive(int event, void *context)
{
ABOUNCE *ap = (ABOUNCE *) context;
ABOUNCE_STATE *ap = (ABOUNCE_STATE *) context;
int status;
ABOUNCE_EVENT_DISABLE(vstream_fileno(ap->fp), abounce_event, context);
abounce_done(ap, (event != EVENT_TIME
&& attr_scan(ap->fp, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
ATTR_TYPE_END) == 1) ? status : -1);
if (event != EVENT_TIME)
event_cancel_timer(abounce_receive, context);
if (event == EVENT_READ
&& attr_scan(ap->fp, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
ATTR_TYPE_END) == 1) {
abounce_done(ap, status);
} else {
abounce_done(ap, -1);
}
}
/* abounce_request_verp - suspend pseudo thread until server reply event */
/* abounce_send - send the request and suspend until the server replies */
static void abounce_request_verp(const char *class, const char *service,
int command, int flags,
const char *queue, const char *id,
const char *encoding,
int smtputf8,
const char *sender,
const char *dsn_envid,
int dsn_ret,
const char *verp,
ABOUNCE_FN callback,
void *context)
static void abounce_send(int event, void *context)
{
ABOUNCE *ap;
ABOUNCE_STATE *ap = (ABOUNCE_STATE *) context;
/*
* Save pseudo thread state. Connect to the server. Send the request and
* suspend the pseudo thread until the server replies (or dies).
* Receive the server's protocol name announcement. At this point the
* server is ready to receive a request without blocking the sender. Send
* the request and suspend until the server replies (or dies).
*/
ap = (ABOUNCE *) mymalloc(sizeof(*ap));
if (event != EVENT_TIME)
event_cancel_timer(abounce_send, context);
non_blocking(vstream_fileno(ap->fp), BLOCKING);
if (event == EVENT_READ
&& attr_scan(ap->fp, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_BOUNCE),
ATTR_TYPE_END) == 0
&& vstream_fwrite(ap->fp, STR(ap->request),
LEN(ap->request)) == LEN(ap->request)
&& vstream_fflush(ap->fp) == 0) {
ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_receive,
(void *) ap, ABOUNCE_TIMEOUT);
} else {
abounce_done(ap, -1);
}
}
/* abounce_connect - connect and suspend until the server replies */
static void abounce_connect(const char *class, const char *service,
int command, int flags,
const char *queue, const char *id,
const char *encoding, int smtputf8,
const char *sender,
const char *dsn_envid, int dsn_ret,
const char *verp, ABOUNCE_FN callback,
void *context)
{
ABOUNCE_STATE *ap;
/*
* Save pseudo thread state. Connect to the server. Prior to Postfix 3.6
* the asynchronous bounce flush/warn client called mail_connect_wait()
* which sleeps and retries several times before terminating with a fatal
* error. This block-and-sleep behavior was not consistent with a) the
* rest of the code in this module, and with b) the synchronous bounce
* client which gives up immediately. It should be safe to give up
* immediately because that leaves the bounce/defer/trace logs in the
* queue. In particular, this should not increase the simultaneous number
* of asynchronous bounce/defer/trace flush/warn requests that are in
* flight.
*/
ap = (ABOUNCE_STATE *) mymalloc(sizeof(*ap));
ap->command = command;
ap->flags = flags;
ap->id = mystrdup(id);
ap->request = vstring_alloc(ABOUNCE_BUFSIZE);
ap->callback = callback;
ap->context = context;
ap->fp = mail_connect_wait(class, service);
ap->fp = mail_connect(class, service, NON_BLOCKING);
if (attr_print(ap->fp, ATTR_FLAG_NONE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, command),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id),
SEND_ATTR_STR(MAIL_ATTR_ENCODING, encoding),
SEND_ATTR_INT(MAIL_ATTR_SMTPUTF8, smtputf8),
SEND_ATTR_STR(MAIL_ATTR_SENDER, sender),
SEND_ATTR_STR(MAIL_ATTR_DSN_ENVID, dsn_envid),
SEND_ATTR_INT(MAIL_ATTR_DSN_RET, dsn_ret),
SEND_ATTR_STR(MAIL_ATTR_VERPDL, verp),
ATTR_TYPE_END) == 0
&& vstream_fflush(ap->fp) == 0) {
ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_event,
/*
* Format the request now, so that we don't have to save a lot of
* arguments now and format the request later.
*/
if (ap->fp != 0) {
/* Note: all code paths must terminate or enable I/O events. */
VSTREAM *mp = vstream_memopen(ap->request, O_WRONLY);
if (attr_print(mp, ATTR_FLAG_MORE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, command),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id),
SEND_ATTR_STR(MAIL_ATTR_ENCODING, encoding),
SEND_ATTR_INT(MAIL_ATTR_SMTPUTF8, smtputf8),
SEND_ATTR_STR(MAIL_ATTR_SENDER, sender),
SEND_ATTR_STR(MAIL_ATTR_DSN_ENVID, dsn_envid),
SEND_ATTR_INT(MAIL_ATTR_DSN_RET, dsn_ret),
ATTR_TYPE_END) != 0
|| (verp != 0
&& attr_print(mp, ATTR_FLAG_MORE,
SEND_ATTR_STR(MAIL_ATTR_VERPDL, verp),
ATTR_TYPE_END) != 0)
|| attr_print(mp, ATTR_FLAG_NONE,
ATTR_TYPE_END) != 0
|| vstream_fclose(mp) != 0)
msg_panic("abounce_connect: write request to memory stream: %m");
/*
* Suspend until the server replies (or dies).
*/
ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_send,
(void *) ap, ABOUNCE_TIMEOUT);
} else {
abounce_done(ap, -1);
@ -316,9 +396,9 @@ void abounce_flush_verp(int flags, const char *queue, const char *id,
ABOUNCE_FN callback,
void *context)
{
abounce_request_verp(MAIL_CLASS_PRIVATE, var_bounce_service,
BOUNCE_CMD_VERP, flags, queue, id, encoding, smtputf8,
sender, dsn_envid, dsn_ret, verp, callback, context);
abounce_connect(MAIL_CLASS_PRIVATE, var_bounce_service,
BOUNCE_CMD_VERP, flags, queue, id, encoding, smtputf8,
sender, dsn_envid, dsn_ret, verp, callback, context);
}
/* adefer_flush_verp - asynchronous defer flush */
@ -330,52 +410,9 @@ void adefer_flush_verp(int flags, const char *queue, const char *id,
ABOUNCE_FN callback, void *context)
{
flags |= BOUNCE_FLAG_DELRCPT;
abounce_request_verp(MAIL_CLASS_PRIVATE, var_defer_service,
BOUNCE_CMD_VERP, flags, queue, id, encoding, smtputf8,
sender, dsn_envid, dsn_ret, verp, callback, context);
}
/* abounce_request - suspend pseudo thread until server reply event */
static void abounce_request(const char *class, const char *service,
int command, int flags,
const char *queue, const char *id,
const char *encoding, int smtputf8,
const char *sender,
const char *dsn_envid, int dsn_ret,
ABOUNCE_FN callback, void *context)
{
ABOUNCE *ap;
/*
* Save pseudo thread state. Connect to the server. Send the request and
* suspend the pseudo thread until the server replies (or dies).
*/
ap = (ABOUNCE *) mymalloc(sizeof(*ap));
ap->command = command;
ap->flags = flags;
ap->id = mystrdup(id);
ap->callback = callback;
ap->context = context;
ap->fp = mail_connect_wait(class, service);
if (attr_print(ap->fp, ATTR_FLAG_NONE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, command),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id),
SEND_ATTR_STR(MAIL_ATTR_ENCODING, encoding),
SEND_ATTR_INT(MAIL_ATTR_SMTPUTF8, smtputf8),
SEND_ATTR_STR(MAIL_ATTR_SENDER, sender),
SEND_ATTR_STR(MAIL_ATTR_DSN_ENVID, dsn_envid),
SEND_ATTR_INT(MAIL_ATTR_DSN_RET, dsn_ret),
ATTR_TYPE_END) == 0
&& vstream_fflush(ap->fp) == 0) {
ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_event,
(void *) ap, ABOUNCE_TIMEOUT);
} else {
abounce_done(ap, -1);
}
abounce_connect(MAIL_CLASS_PRIVATE, var_defer_service,
BOUNCE_CMD_VERP, flags, queue, id, encoding, smtputf8,
sender, dsn_envid, dsn_ret, verp, callback, context);
}
/* abounce_flush - asynchronous bounce flush */
@ -386,9 +423,9 @@ void abounce_flush(int flags, const char *queue, const char *id,
int dsn_ret, ABOUNCE_FN callback,
void *context)
{
abounce_request(MAIL_CLASS_PRIVATE, var_bounce_service, BOUNCE_CMD_FLUSH,
abounce_connect(MAIL_CLASS_PRIVATE, var_bounce_service, BOUNCE_CMD_FLUSH,
flags, queue, id, encoding, smtputf8, sender, dsn_envid,
dsn_ret, callback, context);
dsn_ret, ABOUNCE_NO_VERP, callback, context);
}
/* adefer_flush - asynchronous defer flush */
@ -399,9 +436,9 @@ void adefer_flush(int flags, const char *queue, const char *id,
int dsn_ret, ABOUNCE_FN callback, void *context)
{
flags |= BOUNCE_FLAG_DELRCPT;
abounce_request(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_FLUSH,
abounce_connect(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_FLUSH,
flags, queue, id, encoding, smtputf8, sender, dsn_envid,
dsn_ret, callback, context);
dsn_ret, ABOUNCE_NO_VERP, callback, context);
}
/* adefer_warn - send copy of defer log to sender as warning bounce */
@ -411,9 +448,9 @@ void adefer_warn(int flags, const char *queue, const char *id,
const char *sender, const char *dsn_envid,
int dsn_ret, ABOUNCE_FN callback, void *context)
{
abounce_request(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_WARN,
abounce_connect(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_WARN,
flags, queue, id, encoding, smtputf8, sender, dsn_envid,
dsn_ret, callback, context);
dsn_ret, ABOUNCE_NO_VERP, callback, context);
}
/* atrace_flush - asynchronous trace flush */
@ -423,7 +460,7 @@ void atrace_flush(int flags, const char *queue, const char *id,
const char *sender, const char *dsn_envid,
int dsn_ret, ABOUNCE_FN callback, void *context)
{
abounce_request(MAIL_CLASS_PRIVATE, var_trace_service, BOUNCE_CMD_TRACE,
abounce_connect(MAIL_CLASS_PRIVATE, var_trace_service, BOUNCE_CMD_TRACE,
flags, queue, id, encoding, smtputf8, sender, dsn_envid,
dsn_ret, callback, context);
dsn_ret, ABOUNCE_NO_VERP, callback, context);
}

View File

@ -170,6 +170,15 @@
#define ANVIL_IDENT(service, addr) \
printable(concatenate(service, ":", addr, (char *) 0), '?')
/* anvil_clnt_handshake - receive server protocol announcement */
static int anvil_clnt_handshake(VSTREAM *stream)
{
return (attr_scan_plain(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_ANVIL),
ATTR_TYPE_END));
}
/* anvil_clnt_create - instantiate connection rate service client */
ANVIL_CLNT *anvil_clnt_create(void)
@ -186,6 +195,9 @@ ANVIL_CLNT *anvil_clnt_create(void)
#else
anvil_clnt = attr_clnt_create(var_anvil_service, var_ipc_timeout, 0, 0);
#endif
attr_clnt_control(anvil_clnt,
ATTR_CLNT_CTL_HANDSHAKE, anvil_clnt_handshake,
ATTR_CLNT_CTL_END);
return ((ANVIL_CLNT *) anvil_clnt);
}

View File

@ -186,6 +186,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -310,6 +315,7 @@ int bounce_append_intern(int flags, const char *id, MSG_STATS *stats,
if (mail_command_client(MAIL_CLASS_PRIVATE, var_soft_bounce ?
var_defer_service : var_bounce_service,
MAIL_ATTR_PROTO_BOUNCE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id),
@ -353,6 +359,7 @@ int bounce_flush(int flags, const char *queue, const char *id,
if (var_soft_bounce)
return (-1);
if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service,
MAIL_ATTR_PROTO_BOUNCE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_FLUSH),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
@ -387,6 +394,7 @@ int bounce_flush_verp(int flags, const char *queue, const char *id,
if (var_soft_bounce)
return (-1);
if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service,
MAIL_ATTR_PROTO_BOUNCE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_VERP),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
@ -494,6 +502,7 @@ int bounce_one_intern(int flags, const char *queue, const char *id,
my_dsn.action = "failed";
if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service,
MAIL_ATTR_PROTO_BOUNCE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_ONE),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),

View File

@ -6,11 +6,15 @@
/* SYNOPSIS
/* #include <clnt_stream.h>
/*
/* CLNT_STREAM *clnt_stream_create(class, service, timeout, ttl)
/* typedef void (*CLNT_STREAM_HANDSHAKE_FN)(VSTREAM *)
/*
/* CLNT_STREAM *clnt_stream_create(class, service, timeout, ttl,
/* handshake)
/* const char *class;
/* const char *service;
/* int timeout;
/* int ttl;
/* CLNT_STREAM_HANDSHAKE_FN *handshake;
/*
/* VSTREAM *clnt_stream_access(clnt_stream)
/* CLNT_STREAM *clnt_stream;
@ -33,6 +37,8 @@
/*
/* clnt_stream_access() returns an open stream to the service specified
/* to clnt_stream_create(). The stream instance may change between calls.
/* This function returns null when the handshake function returned an
/* error.
/*
/* clnt_stream_recover() recovers from a server-initiated disconnect
/* that happened in the middle of an I/O operation.
@ -49,6 +55,10 @@
/* Idle time after which the client disconnects.
/* .IP ttl
/* Upper bound on the time that a connection is allowed to persist.
/* .IP handshake
/* Null pointer, or pointer to function that will be called
/* at the start of a new connection and that returns 0 in case
/* of success.
/* DIAGNOSTICS
/* Warnings: communication failure. Fatal error: mail system is down,
/* out of memory.
@ -63,6 +73,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -93,6 +108,7 @@ struct CLNT_STREAM {
VSTREAM *vstream; /* buffered I/O */
int timeout; /* time before client disconnect */
int ttl; /* time before client disconnect */
CLNT_STREAM_HANDSHAKE_FN handshake;
char *class; /* server class */
char *service; /* server name */
};
@ -205,6 +221,7 @@ void clnt_stream_recover(CLNT_STREAM *clnt_stream)
VSTREAM *clnt_stream_access(CLNT_STREAM *clnt_stream)
{
CLNT_STREAM_HANDSHAKE_FN handshake;
/*
* Open a stream or restart the idle timer.
@ -213,20 +230,26 @@ VSTREAM *clnt_stream_access(CLNT_STREAM *clnt_stream)
*/
if (clnt_stream->vstream == 0) {
clnt_stream_open(clnt_stream);
handshake = clnt_stream->handshake;
} else if (readable(vstream_fileno(clnt_stream->vstream))) {
clnt_stream_close(clnt_stream);
clnt_stream_open(clnt_stream);
handshake = clnt_stream->handshake;
} else {
event_request_timer(clnt_stream_event, (void *) clnt_stream,
clnt_stream->timeout);
handshake = 0;
}
if (handshake != 0 && handshake(clnt_stream->vstream) != 0)
return (0);
return (clnt_stream->vstream);
}
/* clnt_stream_create - create client stream connection */
CLNT_STREAM *clnt_stream_create(const char *class, const char *service,
int timeout, int ttl)
int timeout, int ttl,
CLNT_STREAM_HANDSHAKE_FN handshake)
{
CLNT_STREAM *clnt_stream;
@ -237,6 +260,7 @@ CLNT_STREAM *clnt_stream_create(const char *class, const char *service,
clnt_stream->vstream = 0;
clnt_stream->timeout = timeout;
clnt_stream->ttl = ttl;
clnt_stream->handshake = handshake;
clnt_stream->class = mystrdup(class);
clnt_stream->service = mystrdup(service);
return (clnt_stream);

View File

@ -20,9 +20,12 @@
* External interface.
*/
typedef struct CLNT_STREAM CLNT_STREAM;
typedef int (*CLNT_STREAM_HANDSHAKE_FN)(VSTREAM *);
extern CLNT_STREAM *clnt_stream_create(const char *, const char *, int, int);
extern CLNT_STREAM *clnt_stream_create(const char *, const char *, int, int,
CLNT_STREAM_HANDSHAKE_FN);
extern VSTREAM *clnt_stream_access(CLNT_STREAM *);
extern const char *clnt_stream_path(CLNT_STREAM *);
extern void clnt_stream_recover(CLNT_STREAM *);
extern void clnt_stream_free(CLNT_STREAM *);
@ -35,6 +38,11 @@ extern void clnt_stream_free(CLNT_STREAM *);
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
#endif

View File

@ -153,6 +153,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -257,6 +262,7 @@ int defer_append_intern(int flags, const char *id, MSG_STATS *stats,
my_dsn.action = "delayed";
if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service,
MAIL_ATTR_PROTO_BOUNCE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id),
@ -301,6 +307,7 @@ int defer_flush(int flags, const char *queue, const char *id,
flags |= BOUNCE_FLAG_DELRCPT;
if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service,
MAIL_ATTR_PROTO_BOUNCE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_FLUSH),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
@ -325,6 +332,7 @@ int defer_warn(int flags, const char *queue, const char *id,
const char *sender, const char *envid, int dsn_ret)
{
if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service,
MAIL_ATTR_PROTO_BOUNCE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_WARN),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),

View File

@ -49,6 +49,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -79,15 +84,13 @@
static int deliver_pass_initial_reply(VSTREAM *stream)
{
int stat;
if (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &stat),
ATTR_TYPE_END) != 1) {
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_DELIVER),
ATTR_TYPE_END) != 0) {
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
stat = -1;
return (-1);
}
return (stat);
return (0);
}
/* deliver_pass_send_request - send delivery request to delivery process */

View File

@ -92,6 +92,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -135,13 +140,13 @@ static int deliver_request_initial(VSTREAM *stream)
* delivery request; otherwise the queue manager could block in write().
*/
if (msg_verbose)
msg_info("deliver_request_initial: send initial status");
msg_info("deliver_request_initial: send initial response");
attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_INT(MAIL_ATTR_STATUS, 0),
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_DELIVER),
ATTR_TYPE_END);
if ((err = vstream_fflush(stream)) != 0)
if (msg_verbose)
msg_warn("send initial status: %m");
msg_warn("send initial response: %m");
return (err);
}

View File

@ -41,6 +41,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -89,6 +94,15 @@ typedef struct {
static CLNT_STREAM *proxymap_stream; /* read-only maps */
static CLNT_STREAM *proxywrite_stream; /* read-write maps */
/* dict_proxy_handshake - receive server protocol announcement */
static int dict_proxy_handshake(VSTREAM *stream)
{
return (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_PROXYMAP),
ATTR_TYPE_END));
}
/* dict_proxy_sequence - find first/next entry */
static int dict_proxy_sequence(DICT *dict, int function,
@ -118,12 +132,13 @@ static int dict_proxy_sequence(DICT *dict, int function,
stream = clnt_stream_access(dict_proxy->clnt);
errno = 0;
count += 1;
if (attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_SEQUENCE),
SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
SEND_ATTR_INT(MAIL_ATTR_FUNC, function),
ATTR_TYPE_END) != 0
if (stream == 0
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_SEQUENCE),
SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
SEND_ATTR_INT(MAIL_ATTR_FUNC, function),
ATTR_TYPE_END) != 0
|| vstream_fflush(stream)
|| attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
@ -131,7 +146,7 @@ static int dict_proxy_sequence(DICT *dict, int function,
RECV_ATTR_STR(MAIL_ATTR_VALUE, dict_proxy->result),
ATTR_TYPE_END) != 3) {
if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT))
msg_warn("%s: service %s: %m", myname, VSTREAM_PATH(stream));
msg_warn("%s: service %s: %m", myname, dict_proxy->service);
} else {
if (msg_verbose)
msg_info("%s: table=%s flags=%s func=%d -> status=%d key=%s val=%s",
@ -196,19 +211,20 @@ static const char *dict_proxy_lookup(DICT *dict, const char *key)
stream = clnt_stream_access(dict_proxy->clnt);
errno = 0;
count += 1;
if (attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_LOOKUP),
SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
SEND_ATTR_STR(MAIL_ATTR_KEY, key),
ATTR_TYPE_END) != 0
if (stream == 0
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_LOOKUP),
SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
SEND_ATTR_STR(MAIL_ATTR_KEY, key),
ATTR_TYPE_END) != 0
|| vstream_fflush(stream)
|| attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
RECV_ATTR_STR(MAIL_ATTR_VALUE, dict_proxy->result),
ATTR_TYPE_END) != 2) {
if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT))
msg_warn("%s: service %s: %m", myname, VSTREAM_PATH(stream));
msg_warn("%s: service %s: %m", myname, dict_proxy->service);
} else {
if (msg_verbose)
msg_info("%s: table=%s flags=%s key=%s -> status=%d result=%s",
@ -266,19 +282,20 @@ static int dict_proxy_update(DICT *dict, const char *key, const char *value)
stream = clnt_stream_access(dict_proxy->clnt);
errno = 0;
count += 1;
if (attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_UPDATE),
SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
SEND_ATTR_STR(MAIL_ATTR_KEY, key),
SEND_ATTR_STR(MAIL_ATTR_VALUE, value),
ATTR_TYPE_END) != 0
if (stream == 0
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_UPDATE),
SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
SEND_ATTR_STR(MAIL_ATTR_KEY, key),
SEND_ATTR_STR(MAIL_ATTR_VALUE, value),
ATTR_TYPE_END) != 0
|| vstream_fflush(stream)
|| attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
ATTR_TYPE_END) != 1) {
if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT))
msg_warn("%s: service %s: %m", myname, VSTREAM_PATH(stream));
msg_warn("%s: service %s: %m", myname, dict_proxy->service);
} else {
if (msg_verbose)
msg_info("%s: table=%s flags=%s key=%s value=%s -> status=%d",
@ -335,19 +352,20 @@ static int dict_proxy_delete(DICT *dict, const char *key)
stream = clnt_stream_access(dict_proxy->clnt);
errno = 0;
count += 1;
if (attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_DELETE),
SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
SEND_ATTR_STR(MAIL_ATTR_KEY, key),
ATTR_TYPE_END) != 0
if (stream == 0
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_DELETE),
SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
SEND_ATTR_STR(MAIL_ATTR_KEY, key),
ATTR_TYPE_END) != 0
|| vstream_fflush(stream)
|| attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
ATTR_TYPE_END) != 1) {
if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno !=
ENOENT))
msg_warn("%s: service %s: %m", myname, VSTREAM_PATH(stream));
msg_warn("%s: service %s: %m", myname, dict_proxy->service);
} else {
if (msg_verbose)
msg_info("%s: table=%s flags=%s key=%s -> status=%d",
@ -443,7 +461,8 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags)
prefix = kludge = concatenate(var_queue_dir, "/",
MAIL_CLASS_PRIVATE, (char *) 0);
*pstream = clnt_stream_create(prefix, service, var_ipc_idle_limit,
var_ipc_ttl_limit);
var_ipc_ttl_limit,
dict_proxy_handshake);
if (kludge)
myfree(kludge);
myfree(relative_path);
@ -473,18 +492,19 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags)
for (;;) {
stream = clnt_stream_access(dict_proxy->clnt);
errno = 0;
if (attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_OPEN),
SEND_ATTR_STR(MAIL_ATTR_TABLE, dict_proxy->dict.name),
if (stream == 0
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_OPEN),
SEND_ATTR_STR(MAIL_ATTR_TABLE, dict_proxy->dict.name),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, dict_proxy->inst_flags),
ATTR_TYPE_END) != 0
ATTR_TYPE_END) != 0
|| vstream_fflush(stream)
|| attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
RECV_ATTR_INT(MAIL_ATTR_FLAGS, &server_flags),
ATTR_TYPE_END) != 2) {
if (msg_verbose || (errno != EPIPE && errno != ENOENT))
msg_warn("%s: service %s: %m", VSTREAM_PATH(stream), myname);
msg_warn("%s: service %s: %m", myname, dict_proxy->service);
} else {
if (msg_verbose)
msg_info("%s: connect to map=%s status=%d server_flags=%s",

View File

@ -71,6 +71,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -125,6 +130,7 @@ int flush_purge(void)
status = FLUSH_STAT_DENY;
else
status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
MAIL_ATTR_PROTO_FLUSH,
SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_PURGE),
ATTR_TYPE_END);
@ -151,6 +157,7 @@ int flush_refresh(void)
status = FLUSH_STAT_DENY;
else
status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
MAIL_ATTR_PROTO_FLUSH,
SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_REFRESH),
ATTR_TYPE_END);
@ -182,6 +189,7 @@ int flush_send_site(const char *site)
VAR_RELAY_DOMAINS "=$mydestination to flush "
"mail for domain \"%s\"", site);
status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
MAIL_ATTR_PROTO_FLUSH,
SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_SEND_SITE),
SEND_ATTR_STR(MAIL_ATTR_SITE, site),
ATTR_TYPE_END);
@ -210,6 +218,7 @@ int flush_send_file(const char *queue_id)
* Require that the service is turned on.
*/
status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
MAIL_ATTR_PROTO_FLUSH,
SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_SEND_FILE),
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id),
ATTR_TYPE_END);
@ -242,6 +251,7 @@ int flush_add(const char *site, const char *queue_id)
VAR_RELAY_DOMAINS "=$mydestination to update "
"fast-flush logfile for domain \"%s\"", site);
status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
MAIL_ATTR_PROTO_FLUSH,
SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_ADD),
SEND_ATTR_STR(MAIL_ATTR_SITE, site),
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id),

View File

@ -403,7 +403,6 @@ static const char *haproxy_srvr_parse_v2_hdr(const char *str, ssize_t *str_len,
return ("unsupported network protocol");
}
/* For now, skip and ignore TLVs. */
*non_proxy = 0;
*str_len = PP2_HEADER_LEN + ntohs(hdr_v2->len);
return (0);
@ -434,6 +433,8 @@ const char *haproxy_srvr_parse(const char *str, ssize_t *str_len,
if (proto_info == 0)
proto_info = inet_proto_info();
*non_proxy = 0;
/*
* XXX We don't accept connections with the "UNKNOWN" protocol type,
* because those would sidestep address-based access control mechanisms.
@ -471,7 +472,6 @@ const char *haproxy_srvr_parse(const char *str, ssize_t *str_len,
}
myfree(saved_str);
*non_proxy = 0;
return (err);
}

View File

@ -6,9 +6,10 @@
/* SYNOPSIS
/* #include <mail_proto.h>
/*
/* int mail_command_client(class, name, type, attr, ...)
/* int mail_command_client(class, name, proto, type, attr, ...)
/* const char *class;
/* const char *name;
/* const char *proto;
/* int type;
/* const char *attr;
/* DESCRIPTION
@ -21,6 +22,8 @@
/* Service type: MAIL_CLASS_PUBLIC or MAIL_CLASS_PRIVATE
/* .IP name
/* Service name (master.cf).
/* .IP proto
/* The expected protocol name in the server announcement.
/* .IP "type, attr, ..."
/* Attribute information as defined in attr_print(3).
/* DIAGNOSTICS
@ -65,7 +68,8 @@
/* mail_command_client - single-command transaction with completion status */
int mail_command_client(const char *class, const char *name,...)
int mail_command_client(const char *class, const char *name,
const char *proto,...)
{
va_list ap;
VSTREAM *stream;
@ -82,14 +86,20 @@ int mail_command_client(const char *class, const char *name,...)
msg_warn("connect to %s/%s: %m", class, name);
return (-1);
}
va_start(ap, name);
status = attr_vprint(stream, ATTR_FLAG_NONE, ap);
va_end(ap);
if (status != 0) {
if (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, proto),
ATTR_TYPE_END) != 0) {
msg_warn("read %s: %m", VSTREAM_PATH(stream));
status = -1;
} else if (va_start(ap, proto),
(status = attr_vprint(stream, ATTR_FLAG_NONE, ap)),
va_end(ap),
(status != 0)) {
msg_warn("write %s: %m", VSTREAM_PATH(stream));
status = -1;
} else if (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &status), 0) != 1) {
RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
ATTR_TYPE_END) != 1) {
msg_warn("write/read %s: %m", VSTREAM_PATH(stream));
status = -1;
}

View File

@ -114,11 +114,32 @@
*/
extern VSTREAM *mail_connect(const char *, const char *, int);
extern VSTREAM *mail_connect_wait(const char *, const char *);
extern int mail_command_client(const char *, const char *,...);
extern int mail_command_client(const char *, const char *, const char *,...);
extern int mail_command_server(VSTREAM *,...);
extern int mail_trigger(const char *, const char *, const char *, ssize_t);
extern char *mail_pathname(const char *, const char *);
/*
* Each Postfix internal service identifies the protocol that it intends to
* use. On the receiver end, this information does not contribute to the
* reported number of received attributes (it is a constant).
*/
#define MAIL_ATTR_PROTO "protocol"
#define MAIL_ATTR_PROTO_ANVIL "anvil_protocol"
#define MAIL_ATTR_PROTO_BOUNCE "delivery_status_protocol"
#define MAIL_ATTR_PROTO_CLEANUP "cleanup_protocol"
#define MAIL_ATTR_PROTO_DELIVER "delivery_request_protocol"
#define MAIL_ATTR_PROTO_FLUSH "queue_flush_protocol"
#define MAIL_ATTR_PROTO_POSTDROP "postdrop_protocol"
#define MAIL_ATTR_PROTO_PROXYMAP "proxymap_protocol"
#define MAIL_ATTR_PROTO_SCACHE "connection_cache_protocol"
#define MAIL_ATTR_PROTO_SHOWQ "mail_queue_list_protocol"
#define MAIL_ATTR_PROTO_TLSMGR "tlsmgr_protocol"
#define MAIL_ATTR_PROTO_TLSPROXY "tlsproxy_protocol"
#define MAIL_ATTR_PROTO_TRIVIAL "trivial_rewrite_protocol"
#define MAIL_ATTR_PROTO_VERIFY "address_verification_prrotocol"
/*
* Attribute names.
*/

View File

@ -105,6 +105,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -440,7 +445,8 @@ MAIL_STREAM *mail_stream_service(const char *class, const char *name)
id_buf = vstring_alloc(10);
stream = mail_connect_wait(class, name);
if (attr_scan(stream, ATTR_FLAG_MISSING,
if (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP),
RECV_ATTR_STR(MAIL_ATTR_QUEUEID, id_buf), 0) != 1) {
vstream_fclose(stream);
return (0);
@ -492,7 +498,8 @@ MAIL_STREAM *mail_stream_command(const char *command)
CA_VSTREAM_CTL_PATH(command),
CA_VSTREAM_CTL_END);
if (attr_scan(stream, ATTR_FLAG_MISSING,
if (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_POSTDROP),
RECV_ATTR_STR(MAIL_ATTR_QUEUEID, id_buf), 0) != 1) {
if ((status = vstream_pclose(stream)) != 0)
msg_warn("command \"%s\" exited with status %d", command, status);

View File

@ -20,7 +20,7 @@
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
#define MAIL_RELEASE_DATE "20200830"
#define MAIL_RELEASE_DATE "20200920"
#define MAIL_VERSION_NUMBER "3.6"
#ifdef SNAPSHOT

View File

@ -231,8 +231,18 @@ static void post_mail_init(VSTREAM *stream, const char *sender,
date = mail_date(now.tv_sec);
/*
* XXX Don't flush buffers while sending the initial message records.
* That would cause deadlock between verify(8) and cleanup(8) servers.
* The comment in the next paragraph is likely obsolete. Fix 20030610
* changed the verify server to use asynchronous submission of mail
* probes, to avoid blocking the post_mail client for in_flow_delay
* seconds when the cleanup service receives email messages faster than
* they are delivered. Instead, the post_mail client waits until the
* cleanup server announces its availability to receive input. A similar
* change was made at the end of submission, to avoid blocking the
* post_mail client for up to trigger_timeout seconds when the cleanup
* server attempts to notify a queue manager that is overwhelmed.
*
* XXX Don't flush buffers while sending the initial message records. That
* would cause deadlock between verify(8) and cleanup(8) servers.
*/
vstream_control(stream, VSTREAM_CTL_BUFSIZE, 2 * VSTREAM_BUFSIZE,
VSTREAM_CTL_END);
@ -241,6 +251,7 @@ static void post_mail_init(VSTREAM *stream, const char *sender,
* Negotiate with the cleanup service. Give up if we can't agree.
*/
if (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP),
RECV_ATTR_STR(MAIL_ATTR_QUEUEID, id),
ATTR_TYPE_END) != 1
|| attr_print(stream, ATTR_FLAG_NONE,

View File

@ -152,6 +152,15 @@ void resolve_clnt_init(RESOLVE_REPLY *reply)
reply->flags = 0;
}
/* resolve_clnt_handshake - receive server protocol announcement */
static int resolve_clnt_handshake(VSTREAM *stream)
{
return (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TRIVIAL),
ATTR_TYPE_END));
}
/* resolve_clnt - resolve address to (transport, next hop, recipient) */
void resolve_clnt(const char *class, const char *sender,
@ -219,17 +228,19 @@ void resolve_clnt(const char *class, const char *sender,
rewrite_clnt_stream = clnt_stream_create(MAIL_CLASS_PRIVATE,
var_rewrite_service,
var_ipc_idle_limit,
var_ipc_ttl_limit);
var_ipc_ttl_limit,
resolve_clnt_handshake);
for (;;) {
stream = clnt_stream_access(rewrite_clnt_stream);
errno = 0;
count += 1;
if (attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, class),
SEND_ATTR_STR(MAIL_ATTR_SENDER, sender),
SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),
ATTR_TYPE_END) != 0
if (stream == 0
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, class),
SEND_ATTR_STR(MAIL_ATTR_SENDER, sender),
SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),
ATTR_TYPE_END) != 0
|| vstream_fflush(stream)
|| attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_FLAGS, &server_flags),

View File

@ -39,6 +39,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -77,6 +82,15 @@ static VSTRING *last_rule;
static VSTRING *last_addr;
static VSTRING *last_result;
/* rewrite_clnt_handshake - receive server protocol announcement */
static int rewrite_clnt_handshake(VSTREAM *stream)
{
return (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TRIVIAL),
ATTR_TYPE_END));
}
/* rewrite_clnt - rewrite address to (transport, next hop, recipient) */
VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result)
@ -127,17 +141,19 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result)
rewrite_clnt_stream = clnt_stream_create(MAIL_CLASS_PRIVATE,
var_rewrite_service,
var_ipc_idle_limit,
var_ipc_ttl_limit);
var_ipc_ttl_limit,
rewrite_clnt_handshake);
for (;;) {
stream = clnt_stream_access(rewrite_clnt_stream);
errno = 0;
count += 1;
if (attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, REWRITE_ADDR),
SEND_ATTR_STR(MAIL_ATTR_RULE, rule),
SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),
ATTR_TYPE_END) != 0
if (stream == 0
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, REWRITE_ADDR),
SEND_ATTR_STR(MAIL_ATTR_RULE, rule),
SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),
ATTR_TYPE_END) != 0
|| vstream_fflush(stream)
|| attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_FLAGS, &server_flags),

View File

@ -68,7 +68,7 @@
/* sasl_mech_filter - filter a SASL mechanism list */
const char *sasl_mech_filter(STRING_LIST *filter,
const const char *words)
const char *words)
{
const char myname[] = "sasl_mech_filter";
static VSTRING *buf;

View File

@ -41,6 +41,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -80,6 +85,15 @@ typedef struct {
#define SCACHE_MAX_TRIES 2
/* scache_clnt_handshake - receive server protocol announcement */
static int scache_clnt_handshake(VSTREAM *stream)
{
return (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_SCACHE),
ATTR_TYPE_END));
}
/* scache_clnt_save_endp - save endpoint */
static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl,
@ -414,8 +428,11 @@ SCACHE *scache_clnt_create(const char *server, int timeout,
sp->scache->size = scache_clnt_size;
sp->scache->free = scache_clnt_free;
service = concatenate("local:private/", server, (char *) 0);
service = concatenate("local:" MAIL_CLASS_PRIVATE "/", server, (char *) 0);
sp->auto_clnt = auto_clnt_create(service, timeout, idle_limit, ttl_limit);
auto_clnt_control(sp->auto_clnt,
AUTO_CLNT_CTL_HANDSHAKE, scache_clnt_handshake,
AUTO_CLNT_CTL_END);
myfree(service);
#ifdef CANT_WRITE_BEFORE_SENDING_FD

View File

@ -79,6 +79,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -121,6 +126,7 @@ int trace_append(int flags, const char *id, MSG_STATS *stats,
my_dsn.reason = vstring_str(why);
if (mail_command_client(MAIL_CLASS_PRIVATE, var_trace_service,
MAIL_ATTR_PROTO_BOUNCE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id),
@ -145,6 +151,7 @@ int trace_flush(int flags, const char *queue, const char *id,
const char *dsn_envid, int dsn_ret)
{
if (mail_command_client(MAIL_CLASS_PRIVATE, var_trace_service,
MAIL_ATTR_PROTO_BOUNCE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_TRACE),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),

View File

@ -56,6 +56,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -80,6 +85,15 @@
CLNT_STREAM *vrfy_clnt;
/* verify_clnt_handshake - receive server protocol announcement */
static int verify_clnt_handshake(VSTREAM *stream)
{
return (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_VERIFY),
ATTR_TYPE_END));
}
/* verify_clnt_init - initialize */
static void verify_clnt_init(void)
@ -87,7 +101,8 @@ static void verify_clnt_init(void)
if (vrfy_clnt != 0)
msg_panic("verify_clnt_init: multiple initialization");
vrfy_clnt = clnt_stream_create(MAIL_CLASS_PRIVATE, var_verify_service,
var_ipc_idle_limit, var_ipc_ttl_limit);
var_ipc_idle_limit, var_ipc_ttl_limit,
verify_clnt_handshake);
}
/* verify_clnt_query - request address verification status */
@ -111,10 +126,11 @@ int verify_clnt_query(const char *addr, int *addr_status, VSTRING *why)
stream = clnt_stream_access(vrfy_clnt);
errno = 0;
count += 1;
if (attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, VRFY_REQ_QUERY),
SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),
ATTR_TYPE_END) != 0
if (stream == 0
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, VRFY_REQ_QUERY),
SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),
ATTR_TYPE_END) != 0
|| vstream_fflush(stream)
|| attr_scan(stream, ATTR_FLAG_MISSING,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &request_status),
@ -153,12 +169,13 @@ int verify_clnt_update(const char *addr, int addr_status, const char *why)
for (;;) {
stream = clnt_stream_access(vrfy_clnt);
errno = 0;
if (attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, VRFY_REQ_UPDATE),
SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),
SEND_ATTR_INT(MAIL_ATTR_ADDR_STATUS, addr_status),
SEND_ATTR_STR(MAIL_ATTR_WHY, why),
ATTR_TYPE_END) != 0
if (stream == 0
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, VRFY_REQ_UPDATE),
SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),
SEND_ATTR_INT(MAIL_ATTR_ADDR_STATUS, addr_status),
SEND_ATTR_STR(MAIL_ATTR_WHY, why),
ATTR_TYPE_END) != 0
|| attr_scan(stream, ATTR_FLAG_MISSING,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &request_status),
ATTR_TYPE_END) != 1) {

View File

@ -146,6 +146,7 @@ static FORWARD_INFO *forward_open(DELIVER_REQUEST *request, const char *sender)
}
close_on_exec(vstream_fileno(cleanup), CLOSE_ON_EXEC);
if (attr_scan(cleanup, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP),
RECV_ATTR_STR(MAIL_ATTR_QUEUEID, buffer),
ATTR_TYPE_END) != 1) {
vstream_fclose(cleanup);

View File

@ -273,7 +273,6 @@ static unsigned event_server_generation;
static void (*event_server_pre_disconn) (VSTREAM *, char *, char **);
static void (*event_server_slow_exit) (char *, char **);
static int event_server_watchdog = 1000;
static int event_server_saved_flags;
/* event_server_exit - normal termination */
@ -373,8 +372,7 @@ void event_server_disconnect(VSTREAM *stream)
static void event_server_execute(int unused_event, void *context)
{
VSTREAM *stream = (VSTREAM *) context;
HTABLE *attr = (vstream_flags(stream) == event_server_saved_flags ?
(HTABLE *) vstream_context(stream) : 0);
HTABLE *attr = (HTABLE *) vstream_context(stream);
if (event_server_lock != 0
&& myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK,
@ -432,7 +430,6 @@ static void event_server_wakeup(int fd, HTABLE *attr)
CA_VSTREAM_CTL_END);
myfree(tmp);
timed_ipc_setup(stream);
event_server_saved_flags = vstream_flags(stream);
if (event_server_in_flow_delay && mail_flow_get(1) < 0)
event_request_timer(event_server_execute, (void *) stream,
var_in_flow_delay);

View File

@ -12,6 +12,7 @@
* Utility library.
*/
#include <vstream.h>
#include <htable.h>
/*
* Global library.
@ -45,11 +46,13 @@
#define MAIL_SERVER_SLOW_EXIT 21
#define MAIL_SERVER_BOUNCE_INIT 22
#define MAIL_SERVER_RETIRE_ME 23
#define MAIL_SERVER_POST_ACCEPT 24
typedef void (*MAIL_SERVER_INIT_FN) (char *, char **);
typedef int (*MAIL_SERVER_LOOP_FN) (char *, char **);
typedef void (*MAIL_SERVER_EXIT_FN) (char *, char **);
typedef void (*MAIL_SERVER_ACCEPT_FN) (char *, char **);
typedef void (*MAIL_SERVER_POST_ACCEPT_FN) (VSTREAM *, char *, char **, HTABLE *);
typedef void (*MAIL_SERVER_DISCONN_FN) (VSTREAM *, char *, char **);
typedef void (*MAIL_SERVER_SLOW_EXIT_FN) (char *, char **);
@ -67,6 +70,7 @@ typedef void (*MAIL_SERVER_SLOW_EXIT_FN) (char *, char **);
#define CA_MAIL_SERVER_LOOP(v) MAIL_SERVER_LOOP, CHECK_VAL(MAIL_SERVER, MAIL_SERVER_LOOP_FN, (v))
#define CA_MAIL_SERVER_EXIT(v) MAIL_SERVER_EXIT, CHECK_VAL(MAIL_SERVER, MAIL_SERVER_EXIT_FN, (v))
#define CA_MAIL_SERVER_PRE_ACCEPT(v) MAIL_SERVER_PRE_ACCEPT, CHECK_VAL(MAIL_SERVER, MAIL_SERVER_ACCEPT_FN, (v))
#define CA_MAIL_SERVER_POST_ACCEPT(v) MAIL_SERVER_POST_ACCEPT, CHECK_VAL(MAIL_SERVER, MAIL_SERVER_POST_ACCEPT_FN, (v))
#define CA_MAIL_SERVER_SOLITARY MAIL_SERVER_SOLITARY
#define CA_MAIL_SERVER_UNLIMITED MAIL_SERVER_UNLIMITED
#define CA_MAIL_SERVER_PRE_DISCONN(v) MAIL_SERVER_PRE_DISCONN, CHECK_VAL(MAIL_SERVER, MAIL_SERVER_DISCONN_FN, (v))
@ -83,6 +87,7 @@ CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_INIT_FN);
CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_EXIT_FN);
CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_DISCONN_FN);
CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_ACCEPT_FN);
CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_POST_ACCEPT_FN);
CHECK_PTR_HELPER_DCL(MAIL_SERVER, int);
CHECK_PTR_HELPER_DCL(MAIL_SERVER, char);
CHECK_PPTR_HELPER_DCL(MAIL_SERVER, char);

View File

@ -35,9 +35,6 @@
/* function is run after the program has optionally dropped its
/* privileges. This function should not attempt to preserve state
/* 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
/* master.cf file.
/* The argv argument specifies command-line arguments left over
@ -114,6 +111,14 @@
/* Function to be executed prior to accepting a new connection.
/* .sp
/* Only the last instance of this parameter type is remembered.
/* .IP "CA_MAIL_SERVER_POST_ACCEPT(void *(VSTREAM *stream, char *service_name, char **argv, HTABLE *attr))"
/* Function to be executed after accepting a new connection.
/* The stream, service_name and argv argunents are the same
/* as with the "service" argument. The attr argument is null
/* or a pointer to a table with 'pass' connection attributes.
/* The table is destroyed after the function returns.
/* .sp
/* Only the last instance of this parameter type is remembered.
/* .IP "CA_MAIL_SERVER_PRE_DISCONN(VSTREAM *, char *service_name, char **argv)"
/* A pointer to a function that is called
/* by the multi_server_disconnect() function (see below).
@ -250,11 +255,11 @@ static char **multi_server_argv;
static void (*multi_server_accept) (int, void *);
static void (*multi_server_onexit) (char *, char **);
static void (*multi_server_pre_accept) (char *, char **);
static void (*multi_server_post_accept) (VSTREAM *, char *, char **, HTABLE *);
static VSTREAM *multi_server_lock;
static int multi_server_in_flow_delay;
static unsigned multi_server_generation;
static void (*multi_server_pre_disconn) (VSTREAM *, char *, char **);
static int multi_server_saved_flags;
/* multi_server_exit - normal termination */
@ -336,8 +341,6 @@ void multi_server_disconnect(VSTREAM *stream)
static void multi_server_execute(int unused_event, void *context)
{
VSTREAM *stream = (VSTREAM *) context;
HTABLE *attr = (vstream_flags(stream) == multi_server_saved_flags ?
(HTABLE *) vstream_context(stream) : 0);
if (multi_server_lock != 0
&& myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
@ -358,8 +361,6 @@ static void multi_server_execute(int unused_event, void *context)
} else {
multi_server_disconnect(stream);
}
if (attr)
htable_free(attr, myfree);
}
/* multi_server_enable_read - enable read events */
@ -404,16 +405,20 @@ static void multi_server_wakeup(int fd, HTABLE *attr)
tmp = concatenate(multi_server_name, " socket", (char *) 0);
vstream_control(stream,
CA_VSTREAM_CTL_PATH(tmp),
CA_VSTREAM_CTL_CONTEXT((void *) attr),
CA_VSTREAM_CTL_END);
myfree(tmp);
timed_ipc_setup(stream);
multi_server_saved_flags = vstream_flags(stream);
if (multi_server_in_flow_delay && mail_flow_get(1) < 0)
event_request_timer(multi_server_enable_read, (void *) stream,
var_in_flow_delay);
else
multi_server_enable_read(0, (void *) stream);
if (multi_server_post_accept)
multi_server_post_accept(stream, multi_server_name, multi_server_argv, attr);
else if (attr)
msg_warn("service ignores 'pass' connection attributes");
if (attr)
htable_free(attr, myfree);
}
/* multi_server_accept_local - accept client connection request */
@ -746,6 +751,9 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
case MAIL_SERVER_PRE_ACCEPT:
multi_server_pre_accept = va_arg(ap, MAIL_SERVER_ACCEPT_FN);
break;
case MAIL_SERVER_POST_ACCEPT:
multi_server_post_accept = va_arg(ap, MAIL_SERVER_POST_ACCEPT_FN);
break;
case MAIL_SERVER_PRE_DISCONN:
multi_server_pre_disconn = va_arg(ap, MAIL_SERVER_DISCONN_FN);
break;

View File

@ -109,12 +109,12 @@ static int qmgr_deliver_initial_reply(VSTREAM *stream)
msg_warn("%s: premature disconnect", VSTREAM_PATH(stream));
return (DELIVER_STAT_CRASH);
} else if (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &stat),
ATTR_TYPE_END) != 1) {
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_DELIVER),
ATTR_TYPE_END) != 0) {
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
return (DELIVER_STAT_CRASH);
return (DELIVER_STAT_DEFER);
} else {
return (stat ? DELIVER_STAT_DEFER : 0);
return (0);
}
}

View File

@ -488,6 +488,7 @@ static int pickup_file(PICKUP_INFO *info)
cleanup = mail_connect_wait(MAIL_CLASS_PUBLIC, var_cleanup_service);
if (attr_scan(cleanup, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP),
RECV_ATTR_STR(MAIL_ATTR_QUEUEID, buf),
ATTR_TYPE_END) != 1
|| attr_print(cleanup, ATTR_FLAG_NONE,

View File

@ -9,8 +9,8 @@ OBJS = postconf.o postconf_builtin.o postconf_edit.o postconf_main.o \
postconf_lookup.o postconf_match.o postconf_print.o
HDRS = postconf.h
TESTSRC =
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS) -DLEGACY_DBMS_SUPPORT
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE) -DLEGACY_DBMS_SUPPORT
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=
MAKES = bool_table.h bool_vars.h int_table.h int_vars.h str_table.h \
str_vars.h time_table.h time_vars.h raw_table.h raw_vars.h \

View File

@ -381,6 +381,7 @@ int main(int argc, char **argv)
dst = mail_stream_file(MAIL_QUEUE_MAILDROP, MAIL_CLASS_PUBLIC,
var_pickup_service, 0444);
attr_print(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_POSTDROP),
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, dst->id),
ATTR_TYPE_END);
vstream_fflush(VSTREAM_OUT);

View File

@ -61,14 +61,19 @@ depend: $(MAKES)
# do not edit below this line - it is generated by 'make depend'
postlogd.o: ../../include/check_arg.h
postlogd.o: ../../include/htable.h
postlogd.o: ../../include/logwriter.h
postlogd.o: ../../include/mail_conf.h
postlogd.o: ../../include/mail_params.h
postlogd.o: ../../include/mail_server.h
postlogd.o: ../../include/mail_task.h
postlogd.o: ../../include/mail_version.h
postlogd.o: ../../include/maillog_client.h
postlogd.o: ../../include/msg.h
postlogd.o: ../../include/msg_logger.h
postlogd.o: ../../include/stringops.h
postlogd.o: ../../include/sys_defs.h
postlogd.o: ../../include/vbuf.h
postlogd.o: ../../include/vstream.h
postlogd.o: ../../include/vstring.h
postlogd.o: postlogd.c

1
postfix/src/postqueue/.indent.pro vendored Symbolic link
View File

@ -0,0 +1 @@
../../.indent.pro

View File

@ -341,6 +341,26 @@ static const CONFIG_STR_TABLE str_table[] = {
0,
};
/* showq_client - run the appropriate showq protocol client */
static void showq_client(int mode, VSTREAM *showq)
{
if (attr_scan(showq, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_SHOWQ),
ATTR_TYPE_END) != 0)
msg_fatal_status(EX_SOFTWARE, "malformed showq server response");
switch (mode) {
case PQ_MODE_MAILQ_LIST:
showq_compat(showq);
break;
case PQ_MODE_JSON_LIST:
showq_json(showq);
break;
default:
msg_panic("show_queue: unknown mode %d", mode);
}
}
/* show_queue - show queue status */
static void show_queue(int mode)
@ -361,16 +381,7 @@ static void show_queue(int mode)
* Connect to the show queue service.
*/
if ((showq = mail_connect(MAIL_CLASS_PUBLIC, var_showq_service, BLOCKING)) != 0) {
switch (mode) {
case PQ_MODE_MAILQ_LIST:
showq_compat(showq);
break;
case PQ_MODE_JSON_LIST:
showq_json(showq);
break;
default:
msg_panic("show_queue: unknown mode %d", mode);
}
showq_client(mode, showq);
if (vstream_fclose(showq))
msg_warn("close: %m");
}
@ -407,23 +418,14 @@ static void show_queue(int mode)
CA_VSTREAM_POPEN_END)) == 0) {
stat = -1;
} else {
switch (mode) {
case PQ_MODE_MAILQ_LIST:
showq_compat(showq);
break;
case PQ_MODE_JSON_LIST:
showq_json(showq);
break;
default:
msg_panic("show_queue: unknown mode %d", mode);
}
showq_client(mode, showq);
stat = vstream_pclose(showq);
}
argv_free(argv);
myfree(showq_path);
if (stat != 0)
msg_fatal_status(stat < 0 ? EX_OSERR : EX_SOFTWARE,
"Error running %s", showq_path);
myfree(showq_path);
}
/*

View File

@ -88,6 +88,22 @@ typedef struct {
static char *psc_tlsp_service = 0;
/* Resume the dummy SMTP engine after an event handling error */
#define PSC_STARTTLS_EVENT_ERR_RESUME_RETURN() do { \
event_disable_readwrite(vstream_fileno(tlsproxy_stream)); \
PSC_STARTTLS_EVENT_RESUME_RETURN(starttls_state); \
} while (0);
/* Resume the dummy SMTP engine, possibly after swapping streams */
#define PSC_STARTTLS_EVENT_RESUME_RETURN(starttls_state) do { \
vstream_fclose(tlsproxy_stream); \
starttls_state->resume_event(event, (void *) smtp_state); \
myfree((void *) starttls_state); \
return; \
} while (0)
/* psc_starttls_finish - complete negotiation with TLS proxy */
static void psc_starttls_finish(int event, void *context)
@ -130,10 +146,11 @@ static void psc_starttls_finish(int event, void *context)
* The TLS proxy reports that the TLS engine is not available (due to
* configuration error, or other causes).
*/
event_disable_readwrite(vstream_fileno(tlsproxy_stream));
vstream_fclose(tlsproxy_stream);
msg_warn("%s receiving status from %s service",
event == EVENT_TIME ? "timeout" : "problem", psc_tlsp_service);
PSC_SEND_REPLY(smtp_state,
"454 4.7.0 TLS not available due to local problem\r\n");
PSC_STARTTLS_EVENT_ERR_RESUME_RETURN();
}
/*
@ -145,13 +162,10 @@ static void psc_starttls_finish(int event, void *context)
/*
* Some error: drop the TLS proxy stream.
*/
msg_warn("%s sending file handle to %s service",
event == EVENT_TIME ? "timeout" : "problem",
psc_tlsp_service);
event_disable_readwrite(vstream_fileno(tlsproxy_stream));
vstream_fclose(tlsproxy_stream);
msg_warn("problem sending file handle to %s service", psc_tlsp_service);
PSC_SEND_REPLY(smtp_state,
"454 4.7.0 TLS not available due to local problem\r\n");
PSC_STARTTLS_EVENT_ERR_RESUME_RETURN();
}
/*
@ -163,9 +177,10 @@ static void psc_starttls_finish(int event, void *context)
PSC_SEND_REPLY(smtp_state, "220 2.0.0 Ready to start TLS\r\n");
/*
* Replace our SMTP client stream by the TLS proxy stream. Once the
* TLS handshake is done, the TLS proxy will deliver plaintext SMTP
* commands to postscreen(8).
* Swap the SMTP client stream and the TLS proxy stream, and close
* the direct connection to the SMTP client. The TLS proxy will talk
* directly to the SMTP client, and once the TLS handshake is
* completed, the TLS proxy will talk plaintext to postscreen(8).
*
* Swap the file descriptors from under the VSTREAM so that we don't
* have to worry about loss of user-configurable VSTREAM attributes.
@ -174,15 +189,83 @@ static void psc_starttls_finish(int event, void *context)
vstream_control(smtp_state->smtp_client_stream,
CA_VSTREAM_CTL_SWAP_FD(tlsproxy_stream),
CA_VSTREAM_CTL_END);
vstream_fclose(tlsproxy_stream); /* direct-to-client stream! */
smtp_state->flags |= PSC_STATE_FLAG_USING_TLS;
PSC_STARTTLS_EVENT_RESUME_RETURN(starttls_state);
}
}
/* psc_starttls_first - start negotiation with TLS proxy */
static void psc_starttls_first(int event, void *context)
{
const char *myname = "psc_starttls_first";
PSC_STARTTLS *starttls_state = (PSC_STARTTLS *) context;
PSC_STATE *smtp_state = starttls_state->smtp_state;
VSTREAM *tlsproxy_stream = starttls_state->tlsproxy_stream;
static VSTRING *remote_endpt = 0;
if (msg_verbose)
msg_info("%s: receive server protocol on proxy socket %d"
" for smtp socket %d from [%s]:%s flags=%s",
myname, vstream_fileno(tlsproxy_stream),
vstream_fileno(smtp_state->smtp_client_stream),
smtp_state->smtp_client_addr, smtp_state->smtp_client_port,
psc_print_state_flags(smtp_state->flags, myname));
/*
* We leave read-event notification enabled on the postscreen to TLS
* proxy stream, to avoid two kqueue/epoll/etc. system calls: one here,
* and one when resuming the dummy SMTP engine.
*/
if (event != EVENT_TIME)
event_cancel_timer(psc_starttls_first, (void *) starttls_state);
/*
* Receive and verify the server protocol.
*/
if (event != EVENT_READ
|| attr_scan(tlsproxy_stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TLSPROXY),
ATTR_TYPE_END) != 0) {
msg_warn("%s receiving %s attribute from %s service: %m",
event == EVENT_TIME ? "timeout" : "problem",
MAIL_ATTR_PROTO, psc_tlsp_service);
PSC_SEND_REPLY(smtp_state,
"454 4.7.0 TLS not available due to local problem\r\n");
PSC_STARTTLS_EVENT_ERR_RESUME_RETURN();
}
/*
* Resume the postscreen(8) dummy SMTP engine and clean up.
* Send the data attributes now, and send the client file descriptor in a
* later transaction. We report all errors asynchronously, to avoid
* having to maintain multiple error delivery paths.
*
* XXX The formatted endpoint should be a state member. Then, we can
* simplify all the format strings throughout the program.
*/
starttls_state->resume_event(event, (void *) smtp_state);
myfree((void *) starttls_state);
if (remote_endpt == 0)
remote_endpt = vstring_alloc(20);
vstring_sprintf(remote_endpt, "[%s]:%s", smtp_state->smtp_client_addr,
smtp_state->smtp_client_port);
attr_print(tlsproxy_stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(TLS_ATTR_REMOTE_ENDPT, STR(remote_endpt)),
SEND_ATTR_INT(TLS_ATTR_FLAGS, TLS_PROXY_FLAG_ROLE_SERVER),
SEND_ATTR_INT(TLS_ATTR_TIMEOUT, psc_normal_cmd_time_limit),
SEND_ATTR_INT(TLS_ATTR_TIMEOUT, psc_normal_cmd_time_limit),
SEND_ATTR_STR(TLS_ATTR_SERVERID, MAIL_SERVICE_SMTPD), /* XXX */
ATTR_TYPE_END);
if (vstream_fflush(tlsproxy_stream) != 0) {
msg_warn("error sending request to %s service: %m", psc_tlsp_service);
PSC_SEND_REPLY(smtp_state,
"454 4.7.0 TLS not available due to local problem\r\n");
PSC_STARTTLS_EVENT_ERR_RESUME_RETURN();
}
/*
* Set up a read event for the next phase of the TLS proxy handshake.
*/
PSC_READ_EVENT_REQUEST(vstream_fileno(tlsproxy_stream), psc_starttls_finish,
(void *) starttls_state, TLSPROXY_INIT_TIMEOUT);
}
/* psc_starttls_open - open negotiations with TLS proxy */
@ -193,12 +276,10 @@ void psc_starttls_open(PSC_STATE *smtp_state, EVENT_NOTIFY_FN resume_event)
PSC_STARTTLS *starttls_state;
VSTREAM *tlsproxy_stream;
int fd;
static VSTRING *remote_endpt = 0;
if (psc_tlsp_service == 0) {
psc_tlsp_service = concatenate(MAIL_CLASS_PRIVATE "/",
var_tlsproxy_service, (char *) 0);
remote_endpt = vstring_alloc(20);
}
/*
@ -213,38 +294,16 @@ void psc_starttls_open(PSC_STATE *smtp_state, EVENT_NOTIFY_FN resume_event)
return;
}
if (msg_verbose)
msg_info("%s: send client name/address on proxy socket %d"
msg_info("%s: connecting to proxy socket %d"
" for smtp socket %d from [%s]:%s flags=%s",
myname, fd, vstream_fileno(smtp_state->smtp_client_stream),
smtp_state->smtp_client_addr, smtp_state->smtp_client_port,
psc_print_state_flags(smtp_state->flags, myname));
/*
* Initial handshake. Send the data attributes now, and send the client
* file descriptor in a later transaction. We report all errors
* asynchronously, to avoid having to maintain multiple delivery paths.
*
* XXX The formatted endpoint should be a state member. Then, we can
* simplify all the format strings throughout the program.
*/
tlsproxy_stream = vstream_fdopen(fd, O_RDWR);
vstring_sprintf(remote_endpt, "[%s]:%s", smtp_state->smtp_client_addr,
smtp_state->smtp_client_port);
attr_print(tlsproxy_stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(TLS_ATTR_REMOTE_ENDPT, STR(remote_endpt)),
SEND_ATTR_INT(TLS_ATTR_FLAGS, TLS_PROXY_FLAG_ROLE_SERVER),
SEND_ATTR_INT(TLS_ATTR_TIMEOUT, psc_normal_cmd_time_limit),
SEND_ATTR_INT(TLS_ATTR_TIMEOUT, psc_normal_cmd_time_limit),
SEND_ATTR_STR(TLS_ATTR_SERVERID, MAIL_SERVICE_SMTPD), /* XXX */
ATTR_TYPE_END);
if (vstream_fflush(tlsproxy_stream) != 0) {
msg_warn("error sending request to %s service: %m", psc_tlsp_service);
vstream_fclose(tlsproxy_stream);
PSC_SEND_REPLY(smtp_state,
"454 4.7.0 TLS not available due to local problem\r\n");
event_request_timer(resume_event, (void *) smtp_state, 0);
return;
}
vstream_control(tlsproxy_stream,
VSTREAM_CTL_PATH, psc_tlsp_service,
VSTREAM_CTL_END);
/*
* Set up a read event for the next phase of the TLS proxy handshake.
@ -253,6 +312,6 @@ void psc_starttls_open(PSC_STATE *smtp_state, EVENT_NOTIFY_FN resume_event)
starttls_state->tlsproxy_stream = tlsproxy_stream;
starttls_state->resume_event = resume_event;
starttls_state->smtp_state = smtp_state;
PSC_READ_EVENT_REQUEST(vstream_fileno(tlsproxy_stream), psc_starttls_finish,
PSC_READ_EVENT_REQUEST(vstream_fileno(tlsproxy_stream), psc_starttls_first,
(void *) starttls_state, TLSPROXY_INIT_TIMEOUT);
}

View File

@ -745,6 +745,21 @@ static void pre_accept(char *unused_name, char **unused_argv)
}
}
/* post_accept - anounce our protocol name */
static void post_accept(VSTREAM *stream, char *unused_name, char **unused_argv,
HTABLE *unused_attr)
{
/*
* Announce the protocol.
*/
attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_PROXYMAP),
ATTR_TYPE_END);
(void) vstream_fflush(stream);
}
MAIL_VERSION_STAMP_DECLARE;
/* main - pass control to the multi-threaded skeleton */
@ -782,6 +797,7 @@ int main(int argc, char **argv)
CA_MAIL_SERVER_STR_TABLE(str_table),
CA_MAIL_SERVER_POST_INIT(post_jail_init),
CA_MAIL_SERVER_PRE_ACCEPT(pre_accept),
CA_MAIL_SERVER_POST_ACCEPT(post_accept),
/* XXX CA_MAIL_SERVER_SOLITARY if proxywrite */
0);
}

View File

@ -108,18 +108,16 @@ int qmgr_deliver_concurrency;
static int qmgr_deliver_initial_reply(VSTREAM *stream)
{
int stat;
if (peekfd(vstream_fileno(stream)) < 0) {
msg_warn("%s: premature disconnect", VSTREAM_PATH(stream));
return (DELIVER_STAT_CRASH);
} else if (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &stat),
ATTR_TYPE_END) != 1) {
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_DELIVER),
ATTR_TYPE_END) != 0) {
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
return (DELIVER_STAT_CRASH);
return (DELIVER_STAT_DEFER);
} else {
return (stat ? DELIVER_STAT_DEFER : 0);
return (0);
}
}

View File

@ -544,6 +544,21 @@ static void post_jail_init(char *unused_name, char **unused_argv)
scache_start_time = event_time();
}
/* scache_post_accept - announce our protocol */
static void scache_post_accept(VSTREAM *stream, char *unused_name,
char **unused_argv, HTABLE *unused_table)
{
/*
* Announce the protocol.
*/
attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_SCACHE),
ATTR_TYPE_END);
(void) vstream_fflush(stream);
}
MAIL_VERSION_STAMP_DECLARE;
/* main - pass control to the multi-threaded skeleton */
@ -564,6 +579,7 @@ int main(int argc, char **argv)
multi_server_main(argc, argv, scache_service,
CA_MAIL_SERVER_TIME_TABLE(time_table),
CA_MAIL_SERVER_POST_INIT(post_jail_init),
CA_MAIL_SERVER_POST_ACCEPT(scache_post_accept),
CA_MAIL_SERVER_EXIT(scache_status_dump),
CA_MAIL_SERVER_SOLITARY,
0);

View File

@ -360,6 +360,13 @@ static void showq_service(VSTREAM *client, char *unused_service, char **argv)
if (argv[0])
msg_fatal("unexpected command-line argument: %s", argv[0]);
/*
* Protocol identification.
*/
(void) attr_print(client, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_SHOWQ),
ATTR_TYPE_END);
/*
* Skip any files that have the wrong permissions. If we can't open an
* existing file, assume the system is out of resources or that it is

View File

@ -280,7 +280,6 @@ smtpd_chat.o: ../../include/mail_params.h
smtpd_chat.o: ../../include/mail_proto.h
smtpd_chat.o: ../../include/mail_stream.h
smtpd_chat.o: ../../include/maps.h
smtpd_chat.o: ../../include/match_list.h
smtpd_chat.o: ../../include/milter.h
smtpd_chat.o: ../../include/msg.h
smtpd_chat.o: ../../include/myaddrinfo.h
@ -296,7 +295,6 @@ smtpd_chat.o: ../../include/smtp_reply_footer.h
smtpd_chat.o: ../../include/smtp_stream.h
smtpd_chat.o: ../../include/smtputf8.h
smtpd_chat.o: ../../include/sock_addr.h
smtpd_chat.o: ../../include/string_list.h
smtpd_chat.o: ../../include/stringops.h
smtpd_chat.o: ../../include/sys_defs.h
smtpd_chat.o: ../../include/tls.h
@ -400,7 +398,6 @@ smtpd_expand.o: ../../include/mac_parse.h
smtpd_expand.o: ../../include/mail_params.h
smtpd_expand.o: ../../include/mail_proto.h
smtpd_expand.o: ../../include/mail_stream.h
smtpd_expand.o: ../../include/match_list.h
smtpd_expand.o: ../../include/milter.h
smtpd_expand.o: ../../include/msg.h
smtpd_expand.o: ../../include/myaddrinfo.h
@ -409,7 +406,6 @@ smtpd_expand.o: ../../include/name_code.h
smtpd_expand.o: ../../include/name_mask.h
smtpd_expand.o: ../../include/nvtable.h
smtpd_expand.o: ../../include/sock_addr.h
smtpd_expand.o: ../../include/string_list.h
smtpd_expand.o: ../../include/stringops.h
smtpd_expand.o: ../../include/sys_defs.h
smtpd_expand.o: ../../include/tls.h
@ -428,7 +424,6 @@ smtpd_haproxy.o: ../../include/htable.h
smtpd_haproxy.o: ../../include/iostuff.h
smtpd_haproxy.o: ../../include/mail_params.h
smtpd_haproxy.o: ../../include/mail_stream.h
smtpd_haproxy.o: ../../include/match_list.h
smtpd_haproxy.o: ../../include/milter.h
smtpd_haproxy.o: ../../include/msg.h
smtpd_haproxy.o: ../../include/myaddrinfo.h
@ -438,7 +433,6 @@ smtpd_haproxy.o: ../../include/name_mask.h
smtpd_haproxy.o: ../../include/nvtable.h
smtpd_haproxy.o: ../../include/smtp_stream.h
smtpd_haproxy.o: ../../include/sock_addr.h
smtpd_haproxy.o: ../../include/string_list.h
smtpd_haproxy.o: ../../include/stringops.h
smtpd_haproxy.o: ../../include/sys_defs.h
smtpd_haproxy.o: ../../include/tls.h
@ -456,7 +450,6 @@ smtpd_milter.o: ../../include/dns.h
smtpd_milter.o: ../../include/htable.h
smtpd_milter.o: ../../include/mail_params.h
smtpd_milter.o: ../../include/mail_stream.h
smtpd_milter.o: ../../include/match_list.h
smtpd_milter.o: ../../include/milter.h
smtpd_milter.o: ../../include/myaddrinfo.h
smtpd_milter.o: ../../include/mymalloc.h
@ -468,7 +461,6 @@ smtpd_milter.o: ../../include/quote_flags.h
smtpd_milter.o: ../../include/resolve_clnt.h
smtpd_milter.o: ../../include/sock_addr.h
smtpd_milter.o: ../../include/split_at.h
smtpd_milter.o: ../../include/string_list.h
smtpd_milter.o: ../../include/stringops.h
smtpd_milter.o: ../../include/sys_defs.h
smtpd_milter.o: ../../include/tls.h
@ -491,7 +483,6 @@ smtpd_peer.o: ../../include/iostuff.h
smtpd_peer.o: ../../include/mail_params.h
smtpd_peer.o: ../../include/mail_proto.h
smtpd_peer.o: ../../include/mail_stream.h
smtpd_peer.o: ../../include/match_list.h
smtpd_peer.o: ../../include/milter.h
smtpd_peer.o: ../../include/msg.h
smtpd_peer.o: ../../include/myaddrinfo.h
@ -501,7 +492,6 @@ smtpd_peer.o: ../../include/name_mask.h
smtpd_peer.o: ../../include/nvtable.h
smtpd_peer.o: ../../include/sock_addr.h
smtpd_peer.o: ../../include/split_at.h
smtpd_peer.o: ../../include/string_list.h
smtpd_peer.o: ../../include/stringops.h
smtpd_peer.o: ../../include/sys_defs.h
smtpd_peer.o: ../../include/tls.h
@ -525,7 +515,6 @@ smtpd_proxy.o: ../../include/mail_params.h
smtpd_proxy.o: ../../include/mail_proto.h
smtpd_proxy.o: ../../include/mail_queue.h
smtpd_proxy.o: ../../include/mail_stream.h
smtpd_proxy.o: ../../include/match_list.h
smtpd_proxy.o: ../../include/milter.h
smtpd_proxy.o: ../../include/msg.h
smtpd_proxy.o: ../../include/myaddrinfo.h
@ -537,7 +526,6 @@ smtpd_proxy.o: ../../include/rec_type.h
smtpd_proxy.o: ../../include/record.h
smtpd_proxy.o: ../../include/smtp_stream.h
smtpd_proxy.o: ../../include/sock_addr.h
smtpd_proxy.o: ../../include/string_list.h
smtpd_proxy.o: ../../include/stringops.h
smtpd_proxy.o: ../../include/sys_defs.h
smtpd_proxy.o: ../../include/tls.h
@ -607,7 +595,6 @@ smtpd_sasl_proto.o: ../../include/mail_error.h
smtpd_sasl_proto.o: ../../include/mail_params.h
smtpd_sasl_proto.o: ../../include/mail_proto.h
smtpd_sasl_proto.o: ../../include/mail_stream.h
smtpd_sasl_proto.o: ../../include/match_list.h
smtpd_sasl_proto.o: ../../include/milter.h
smtpd_sasl_proto.o: ../../include/msg.h
smtpd_sasl_proto.o: ../../include/myaddrinfo.h
@ -616,7 +603,6 @@ smtpd_sasl_proto.o: ../../include/name_code.h
smtpd_sasl_proto.o: ../../include/name_mask.h
smtpd_sasl_proto.o: ../../include/nvtable.h
smtpd_sasl_proto.o: ../../include/sock_addr.h
smtpd_sasl_proto.o: ../../include/string_list.h
smtpd_sasl_proto.o: ../../include/stringops.h
smtpd_sasl_proto.o: ../../include/sys_defs.h
smtpd_sasl_proto.o: ../../include/tls.h
@ -641,7 +627,6 @@ smtpd_state.o: ../../include/mail_error.h
smtpd_state.o: ../../include/mail_params.h
smtpd_state.o: ../../include/mail_proto.h
smtpd_state.o: ../../include/mail_stream.h
smtpd_state.o: ../../include/match_list.h
smtpd_state.o: ../../include/milter.h
smtpd_state.o: ../../include/msg.h
smtpd_state.o: ../../include/myaddrinfo.h
@ -650,7 +635,6 @@ smtpd_state.o: ../../include/name_code.h
smtpd_state.o: ../../include/name_mask.h
smtpd_state.o: ../../include/nvtable.h
smtpd_state.o: ../../include/sock_addr.h
smtpd_state.o: ../../include/string_list.h
smtpd_state.o: ../../include/sys_defs.h
smtpd_state.o: ../../include/tls.h
smtpd_state.o: ../../include/vbuf.h
@ -676,7 +660,6 @@ smtpd_xforward.o: ../../include/htable.h
smtpd_xforward.o: ../../include/iostuff.h
smtpd_xforward.o: ../../include/mail_proto.h
smtpd_xforward.o: ../../include/mail_stream.h
smtpd_xforward.o: ../../include/match_list.h
smtpd_xforward.o: ../../include/milter.h
smtpd_xforward.o: ../../include/msg.h
smtpd_xforward.o: ../../include/myaddrinfo.h
@ -685,7 +668,6 @@ smtpd_xforward.o: ../../include/name_code.h
smtpd_xforward.o: ../../include/name_mask.h
smtpd_xforward.o: ../../include/nvtable.h
smtpd_xforward.o: ../../include/sock_addr.h
smtpd_xforward.o: ../../include/string_list.h
smtpd_xforward.o: ../../include/sys_defs.h
smtpd_xforward.o: ../../include/tls.h
smtpd_xforward.o: ../../include/vbuf.h

View File

@ -62,6 +62,7 @@ depend: $(MAKES)
spawn.o: ../../include/argv.h
spawn.o: ../../include/check_arg.h
spawn.o: ../../include/dict.h
spawn.o: ../../include/htable.h
spawn.o: ../../include/mail_conf.h
spawn.o: ../../include/mail_params.h
spawn.o: ../../include/mail_parm_split.h

View File

@ -107,6 +107,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -144,6 +149,15 @@
static ATTR_CLNT *tls_mgr;
/* tls_mgr_handshake - receive server protocol announcement */
static int tls_mgr_handshake(VSTREAM *stream)
{
return (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TLSMGR),
ATTR_TYPE_END));
}
/* tls_mgr_open - create client handle */
static void tls_mgr_open(void)
@ -168,6 +182,7 @@ static void tls_mgr_open(void)
attr_clnt_control(tls_mgr,
ATTR_CLNT_CTL_PROTO, attr_vprint, attr_vscan,
ATTR_CLNT_CTL_HANDSHAKE, tls_mgr_handshake,
ATTR_CLNT_CTL_END);
}

View File

@ -187,6 +187,14 @@ VSTREAM *tls_proxy_open(const char *service, int flags,
* remote peer file descriptor in a later transaction.
*/
tlsproxy_stream = vstream_fdopen(fd, O_RDWR);
if (attr_scan(tlsproxy_stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TLSPROXY),
ATTR_TYPE_END) != 0) {
msg_warn("error receiving %s service initial response",
STR(tlsproxy_service));
vstream_fclose(tlsproxy_stream);
return (0);
}
vstring_sprintf(remote_endpt, "[%s]:%s", peer_addr, peer_port);
attr_print(tlsproxy_stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(TLS_ATTR_REMOTE_ENDPT, STR(remote_endpt)),

View File

@ -1004,6 +1004,22 @@ static void tlsmgr_post_init(char *unused_name, char **unused_argv)
tlsmgr_cache_run_event(NULL_EVENT, (void *) ent);
}
/* tlsmgr_post_accept - announce our protocol */
static void tlsmgr_post_accept(VSTREAM *stream, char *unused_name,
char **unused_argv, HTABLE *unused_table)
{
/*
* Announce the protocol.
*/
attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TLSMGR),
ATTR_TYPE_END);
(void) vstream_fflush(stream);
}
/* tlsmgr_before_exit - save PRNG state before exit */
static void tlsmgr_before_exit(char *unused_service_name, char **unused_argv)
@ -1061,6 +1077,7 @@ int main(int argc, char **argv)
CA_MAIL_SERVER_STR_TABLE(str_table),
CA_MAIL_SERVER_PRE_INIT(tlsmgr_pre_init),
CA_MAIL_SERVER_POST_INIT(tlsmgr_post_init),
CA_MAIL_SERVER_POST_ACCEPT(tlsmgr_post_accept),
CA_MAIL_SERVER_EXIT(tlsmgr_before_exit),
CA_MAIL_SERVER_LOOP(tlsmgr_loop),
CA_MAIL_SERVER_SOLITARY,

View File

@ -1481,6 +1481,12 @@ static void tlsp_service(VSTREAM *plaintext_stream,
CA_VSTREAM_CTL_TIMEOUT(5),
CA_VSTREAM_CTL_END);
(void) attr_print(plaintext_stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TLSPROXY),
ATTR_TYPE_END);
if (vstream_fflush(plaintext_stream) != 0)
msg_warn("write %s attribute: %m", MAIL_ATTR_PROTO);
/*
* Receive postscreen's remote SMTP client address/port and socket.
*/

View File

@ -153,7 +153,7 @@
/* matches subdomains of example.com,
/* instead of requiring an explicit ".example.com" pattern.
/* .IP "\fBrelayhost (empty)\fR"
/* The next-hop destination of non-local mail; overrides non-local
/* The next-hop destination(s) for non-local mail; overrides non-local
/* domains in recipient addresses.
/* .IP "\fBtransport_maps (empty)\fR"
/* Optional lookup tables with mappings from recipient address to
@ -522,6 +522,21 @@ static void pre_accept(char *unused_name, char **unused_argv)
#endif
/* post_accept - anounce our protocol name */
static void post_accept(VSTREAM *stream, char *unused_name, char **unused_argv,
HTABLE *unused_attr)
{
/*
* Announce the protocol.
*/
attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TRIVIAL),
ATTR_TYPE_END);
(void) vstream_fflush(stream);
}
static void check_table_stats(int unused_event, void *unused_context)
{
const char *table;
@ -648,5 +663,6 @@ int main(int argc, char **argv)
#ifdef CHECK_TABLE_STATS_BEFORE_ACCEPT
CA_MAIL_SERVER_PRE_ACCEPT(pre_accept),
#endif
CA_MAIL_SERVER_POST_ACCEPT(post_accept),
0);
}

View File

@ -17,7 +17,7 @@ SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \
msg_output.c msg_syslog.c msg_vstream.c mvect.c myaddrinfo.c myflock.c \
mymalloc.c myrand.c mystrtok.c name_code.c name_mask.c netstring.c \
neuter.c non_blocking.c nvtable.c open_as.c open_limit.c open_lock.c \
peekfd.c percentm.c posix_signals.c printable.c rand_sleep.c \
peekfd.c posix_signals.c printable.c rand_sleep.c \
readlline.c ring.c safe_getenv.c safe_open.c \
sane_accept.c sane_connect.c sane_link.c sane_rename.c \
sane_socketpair.c sane_time.c scan_dir.c set_eugid.c set_ugid.c \
@ -62,7 +62,7 @@ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
msg_output.o msg_syslog.o msg_vstream.o mvect.o myaddrinfo.o myflock.o \
mymalloc.o myrand.o mystrtok.o name_code.o name_mask.o netstring.o \
neuter.o non_blocking.o nvtable.o open_as.o open_limit.o open_lock.o \
peekfd.o percentm.o posix_signals.o printable.o rand_sleep.o \
peekfd.o posix_signals.o printable.o rand_sleep.o \
readlline.o ring.o safe_getenv.o safe_open.o \
sane_accept.o sane_connect.o sane_link.o sane_rename.o \
sane_socketpair.o sane_time.o scan_dir.o set_eugid.o set_ugid.o \
@ -104,7 +104,7 @@ HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
mac_parse.h make_dirs.h mask_addr.h match_list.h msg.h \
msg_output.h msg_syslog.h msg_vstream.h mvect.h myaddrinfo.h myflock.h \
mymalloc.h myrand.h name_code.h name_mask.h netstring.h nvtable.h \
open_as.h open_lock.h percentm.h posix_signals.h readlline.h ring.h \
open_as.h open_lock.h posix_signals.h readlline.h ring.h \
safe.h safe_open.h sane_accept.h sane_connect.h sane_fsops.h \
load_lib.h \
sane_socketpair.h sane_time.h scan_dir.h set_eugid.h set_ugid.h \
@ -1949,6 +1949,8 @@ load_file.o: vbuf.h
load_file.o: vstream.h
load_file.o: warn_stat.h
load_lib.o: load_lib.c
load_lib.o: load_lib.h
load_lib.o: msg.h
load_lib.o: sys_defs.h
logwriter.o: check_arg.h
logwriter.o: iostuff.h
@ -2070,7 +2072,6 @@ msg_output.o: msg_output.c
msg_output.o: msg_output.h
msg_output.o: msg_vstream.h
msg_output.o: mymalloc.h
msg_output.o: percentm.h
msg_output.o: stringops.h
msg_output.o: sys_defs.h
msg_output.o: vbuf.h
@ -2220,12 +2221,6 @@ pass_trigger.o: trigger.h
peekfd.o: iostuff.h
peekfd.o: peekfd.c
peekfd.o: sys_defs.h
percentm.o: check_arg.h
percentm.o: percentm.c
percentm.o: percentm.h
percentm.o: sys_defs.h
percentm.o: vbuf.h
percentm.o: vstring.h
poll_fd.o: iostuff.h
poll_fd.o: msg.h
poll_fd.o: poll_fd.c

View File

@ -45,6 +45,7 @@ typedef int (*ATTR_PRINT_CUSTOM_FN) (ATTR_PRINT_COMMON_FN, VSTREAM *, int, void
#define ATTR_TYPE_LONG 4 /* Unsigned long */
#define ATTR_TYPE_DATA 5 /* Binary data */
#define ATTR_TYPE_FUNC 6 /* Function pointer */
#define ATTR_TYPE_STREQ 7 /* Requires (name, value) match */
/*
* Optional sender-specified grouping for hash or nameval tables.
@ -70,6 +71,7 @@ typedef int (*ATTR_PRINT_CUSTOM_FN) (ATTR_PRINT_COMMON_FN, VSTREAM *, int, void
#define RECV_ATTR_INT(name, val) ATTR_TYPE_INT, CHECK_CPTR(ATTR, char, (name)), CHECK_PTR(ATTR, int, (val))
#define RECV_ATTR_STR(name, val) ATTR_TYPE_STR, CHECK_CPTR(ATTR, char, (name)), CHECK_PTR(ATTR, VSTRING, (val))
#define RECV_ATTR_STREQ(name, val) ATTR_TYPE_STREQ, CHECK_CPTR(ATTR, char, (name)), CHECK_CPTR(ATTR, char, (val))
#define RECV_ATTR_HASH(val) ATTR_TYPE_HASH, CHECK_PTR(ATTR, HTABLE, (val))
#define RECV_ATTR_NV(val) ATTR_TYPE_NV, CHECK_PTR(ATTR, NVTABLE, (val))
#define RECV_ATTR_LONG(name, val) ATTR_TYPE_LONG, CHECK_CPTR(ATTR, char, (name)), CHECK_PTR(ATTR, long, (val))

View File

@ -8,6 +8,7 @@
/*
/* typedef int (*ATTR_CLNT_PRINT_FN) (VSTREAM *, int, va_list);
/* typedef int (*ATTR_CLNT_SCAN_FN) (VSTREAM *, int, va_list);
/* typedef int (*ATTR_CLNT_HANDSHAKE_FN) (VSTREAM *);
/*
/* ATTR_CLNT *attr_clnt_create(server, timeout, max_idle, max_ttl)
/* const char *server;
@ -65,6 +66,9 @@
/* .IP "ATTR_CLNT_CTL_TRY_DELAY(int)"
/* The time in seconds between attempts to send a request
/* (default: 1). Specify a value greater than zero.
/* .IP "ATTR_CLNT_CTL_HANDSHAKE(VSTREAM *)"
/* A pointer to function that will be called at the start of a
/* new connection, and that returns 0 in case of success.
/* DIAGNOSTICS
/* Warnings: communication failure.
/* SEE ALSO
@ -80,6 +84,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -254,6 +263,12 @@ void attr_clnt_control(ATTR_CLNT *client, int name,...)
client->print = va_arg(ap, ATTR_CLNT_PRINT_FN);
client->scan = va_arg(ap, ATTR_CLNT_SCAN_FN);
break;
case ATTR_CLNT_CTL_HANDSHAKE:
auto_clnt_control(client->auto_clnt,
AUTO_CLNT_CTL_HANDSHAKE,
va_arg(ap, ATTR_CLNT_HANDSHAKE_FN),
AUTO_CLNT_CTL_END);
break;
case ATTR_CLNT_CTL_REQ_LIMIT:
client->req_limit = va_arg(ap, int);
if (client->req_limit < 0)

View File

@ -27,6 +27,7 @@
typedef struct ATTR_CLNT ATTR_CLNT;
typedef int (*ATTR_CLNT_PRINT_FN) (VSTREAM *, int, va_list);
typedef int (*ATTR_CLNT_SCAN_FN) (VSTREAM *, int, va_list);
typedef int (*ATTR_CLNT_HANDSHAKE_FN) (VSTREAM *);
extern ATTR_CLNT *attr_clnt_create(const char *, int, int, int);
extern int attr_clnt_request(ATTR_CLNT *, int,...);
@ -38,6 +39,7 @@ extern void attr_clnt_control(ATTR_CLNT *, int,...);
#define ATTR_CLNT_CTL_REQ_LIMIT 2 /* requests per connection */
#define ATTR_CLNT_CTL_TRY_LIMIT 3 /* attempts per request */
#define ATTR_CLNT_CTL_TRY_DELAY 4 /* pause between requests */
#define ATTR_CLNT_CTL_HANDSHAKE 5 /* handshake before first request */
/* LICENSE
/* .ad
@ -48,6 +50,11 @@ extern void attr_clnt_control(ATTR_CLNT *, int,...);
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
#endif

View File

@ -228,6 +228,7 @@ int main(int unused_argc, char **argv)
htable_enter(table, "foo-name", mystrdup("foo-value"));
htable_enter(table, "bar-name", mystrdup("bar-value"));
attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "test"),
SEND_ATTR_INT(ATTR_NAME_INT, 4711),
SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
@ -236,11 +237,15 @@ int main(int unused_argc, char **argv)
SEND_ATTR_LONG(ATTR_NAME_LONG, 4321L),
ATTR_TYPE_END);
attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "test"),
SEND_ATTR_INT(ATTR_NAME_INT, 4711),
SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
SEND_ATTR_DATA(ATTR_NAME_DATA, strlen("whoopee"), "whoopee"),
ATTR_TYPE_END);
attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "not-test"),
ATTR_TYPE_END);
if (vstream_fflush(VSTREAM_OUT) != 0)
msg_fatal("write error: %m");

View File

@ -269,6 +269,7 @@ int main(int unused_argc, char **argv)
htable_enter(table, "foo-name", mystrdup("foo-value"));
htable_enter(table, "bar-name", mystrdup("bar-value"));
attr_print64(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "test"),
SEND_ATTR_INT(ATTR_NAME_INT, 4711),
SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
@ -277,11 +278,15 @@ int main(int unused_argc, char **argv)
SEND_ATTR_LONG(ATTR_NAME_LONG, 4321L),
ATTR_TYPE_END);
attr_print64(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "test"),
SEND_ATTR_INT(ATTR_NAME_INT, 4711),
SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
SEND_ATTR_DATA(ATTR_NAME_DATA, strlen("whoopee"), "whoopee"),
ATTR_TYPE_END);
attr_print64(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "not-test"),
ATTR_TYPE_END);
if (vstream_fflush(VSTREAM_OUT) != 0)
msg_fatal("write error: %m");

View File

@ -224,6 +224,7 @@ int main(int unused_argc, char **argv)
htable_enter(table, "foo-name", mystrdup("foo-value"));
htable_enter(table, "bar-name", mystrdup("bar-value"));
attr_print_plain(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "test"),
SEND_ATTR_INT(ATTR_NAME_INT, 4711),
SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
@ -232,11 +233,15 @@ int main(int unused_argc, char **argv)
SEND_ATTR_LONG(ATTR_NAME_LONG, 4321L),
ATTR_TYPE_END);
attr_print_plain(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "test"),
SEND_ATTR_INT(ATTR_NAME_INT, 4711),
SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
SEND_ATTR_DATA(ATTR_NAME_DATA, strlen("whoopee"), "whoopee"),
ATTR_TYPE_END);
attr_print_plain(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "not-test"),
ATTR_TYPE_END);
if (vstream_fflush(VSTREAM_OUT) != 0)
msg_fatal("write error: %m");

View File

@ -100,6 +100,9 @@
/* This argument is followed by an attribute name and a long pointer.
/* .IP "RECV_ATTR_STR(const char *name, VSTRING *vp)"
/* This argument is followed by an attribute name and a VSTRING pointer.
/* .IP "RECV_ATTR_STREQ(const char *name, const char *value)"
/* The name and value must match what the client sends.
/* This attribute does not increment the result value.
/* .IP "RECV_ATTR_DATA(const char *name, VSTRING *vp)"
/* This argument is followed by an attribute name and a VSTRING pointer.
/* .IP "RECV_ATTR_FUNC(ATTR_SCAN_CUSTOM_FN, void *data)"
@ -278,6 +281,7 @@ int attr_vscan0(VSTREAM *fp, int flags, va_list ap)
int conversions;
ATTR_SCAN_CUSTOM_FN scan_fn;
void *scan_arg;
const char *expect_val;
/*
* Sanity check.
@ -421,6 +425,19 @@ int attr_vscan0(VSTREAM *fp, int flags, va_list ap)
if (scan_fn(attr_scan0, fp, flags | ATTR_FLAG_MORE, scan_arg) < 0)
return (-1);
break;
case ATTR_TYPE_STREQ:
expect_val = va_arg(ap, const char *);
if ((ch = attr_scan0_string(fp, str_buf,
"input attribute value")) < 0)
return (-1);
if (strcmp(expect_val, STR(str_buf)) != 0) {
msg_warn("unexpected %s %s from %s (expected: %s)",
STR(name_buf), STR(str_buf), VSTREAM_PATH(fp),
expect_val);
return (-1);
}
conversions -= 1;
break;
case ATTR_TYPE_HASH:
case ATTR_TYPE_CLOSE:
if ((ch = attr_scan0_string(fp, str_buf,
@ -513,6 +530,7 @@ int main(int unused_argc, char **used_argv)
msg_vstream_init(used_argv[0], VSTREAM_ERR);
if ((ret = attr_scan0(VSTREAM_IN,
ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
RECV_ATTR_STR(ATTR_NAME_STR, str_val),
@ -534,6 +552,7 @@ int main(int unused_argc, char **used_argv)
}
if ((ret = attr_scan0(VSTREAM_IN,
ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
RECV_ATTR_STR(ATTR_NAME_STR, str_val),
@ -550,6 +569,11 @@ int main(int unused_argc, char **used_argv)
} else {
vstream_printf("return: %d\n", ret);
}
if ((ret = attr_scan0(VSTREAM_IN,
ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
ATTR_TYPE_END)) != 0)
vstream_printf("return: %d\n", ret);
if (vstream_fflush(VSTREAM_OUT) != 0)
msg_fatal("write error: %m");

View File

@ -1,3 +1,4 @@
./attr_print0: send attr protocol = test
./attr_print0: send attr number = 4711
./attr_print0: send attr long_number = 1234
./attr_print0: send attr string = whoopee
@ -5,10 +6,15 @@
./attr_print0: send attr name foo-name value foo-value
./attr_print0: send attr name bar-name value bar-value
./attr_print0: send attr long_number = 4321
./attr_print0: send attr protocol = test
./attr_print0: send attr number = 4711
./attr_print0: send attr long_number = 1234
./attr_print0: send attr string = whoopee
./attr_print0: send attr data = [data 7 bytes]
./attr_print0: send attr protocol = not-test
./attr_scan0: unknown_stream: wanted attribute: protocol
./attr_scan0: input attribute name: protocol
./attr_scan0: input attribute value: test
./attr_scan0: unknown_stream: wanted attribute: number
./attr_scan0: input attribute name: number
./attr_scan0: input attribute value: 4711
@ -36,6 +42,9 @@
./attr_scan0: input attribute value: 4321
./attr_scan0: unknown_stream: wanted attribute: (list terminator)
./attr_scan0: input attribute name: (end)
./attr_scan0: unknown_stream: wanted attribute: protocol
./attr_scan0: input attribute name: protocol
./attr_scan0: input attribute value: test
./attr_scan0: unknown_stream: wanted attribute: number
./attr_scan0: input attribute name: number
./attr_scan0: input attribute value: 4711
@ -50,6 +59,10 @@
./attr_scan0: input attribute value: d2hvb3BlZQ==
./attr_scan0: unknown_stream: wanted attribute: (list terminator)
./attr_scan0: input attribute name: (end)
./attr_scan0: unknown_stream: wanted attribute: protocol
./attr_scan0: input attribute name: protocol
./attr_scan0: input attribute value: not-test
./attr_scan0: warning: unexpected protocol not-test from unknown_stream (expected: test)
number 4711
long_number 1234
string whoopee
@ -63,3 +76,4 @@ string whoopee
data whoopee
(hash) foo-name foo-value
(hash) bar-name bar-value
return: -1

View File

@ -102,6 +102,9 @@
/* This argument is followed by an attribute name and a long pointer.
/* .IP "RECV_ATTR_STR(const char *name, VSTRING *vp)"
/* This argument is followed by an attribute name and a VSTRING pointer.
/* .IP "RECV_ATTR_STREQ(const char *name, const char *value)"
/* The name and value must match what the client sends.
/* This attribute does not increment the result value.
/* .IP "RECV_ATTR_DATA(const char *name, VSTRING *vp)"
/* This argument is followed by an attribute name and a VSTRING pointer.
/* .IP "RECV_ATTR_FUNC(ATTR_SCAN_CUSTOM_FN, void *data)"
@ -281,6 +284,7 @@ int attr_vscan64(VSTREAM *fp, int flags, va_list ap)
int conversions;
ATTR_SCAN_CUSTOM_FN scan_fn;
void *scan_arg;
const char *expect_val;
/*
* Sanity check.
@ -470,6 +474,29 @@ int attr_vscan64(VSTREAM *fp, int flags, va_list ap)
if (scan_fn(attr_scan64, fp, flags | ATTR_FLAG_MORE, scan_arg) < 0)
return (-1);
break;
case ATTR_TYPE_STREQ:
if (ch != ':') {
msg_warn("missing value for string attribute %s from %s",
STR(name_buf), VSTREAM_PATH(fp));
return (-1);
}
expect_val = va_arg(ap, const char *);
if ((ch = attr_scan64_string(fp, str_buf,
"input attribute value")) < 0)
return (-1);
if (ch != '\n') {
msg_warn("multiple values for attribute %s from %s",
STR(name_buf), VSTREAM_PATH(fp));
return (-1);
}
if (strcmp(expect_val, STR(str_buf)) != 0) {
msg_warn("unexpected %s %s from %s (expected: %s)",
STR(name_buf), STR(str_buf), VSTREAM_PATH(fp),
expect_val);
return (-1);
}
conversions -= 1;
break;
case ATTR_TYPE_HASH:
case ATTR_TYPE_CLOSE:
if (ch != ':') {
@ -572,6 +599,7 @@ int main(int unused_argc, char **used_argv)
msg_vstream_init(used_argv[0], VSTREAM_ERR);
if ((ret = attr_scan64(VSTREAM_IN,
ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
RECV_ATTR_STR(ATTR_NAME_STR, str_val),
@ -593,6 +621,7 @@ int main(int unused_argc, char **used_argv)
}
if ((ret = attr_scan64(VSTREAM_IN,
ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
RECV_ATTR_STR(ATTR_NAME_STR, str_val),
@ -609,6 +638,11 @@ int main(int unused_argc, char **used_argv)
} else {
vstream_printf("return: %d\n", ret);
}
if ((ret = attr_scan64(VSTREAM_IN,
ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
ATTR_TYPE_END)) != 0)
vstream_printf("return: %d\n", ret);
if (vstream_fflush(VSTREAM_OUT) != 0)
msg_fatal("write error: %m");

View File

@ -1,3 +1,4 @@
./attr_print64: send attr protocol = test
./attr_print64: send attr number = 4711
./attr_print64: send attr long_number = 1234
./attr_print64: send attr string = whoopee
@ -5,10 +6,15 @@
./attr_print64: send attr name foo-name value foo-value
./attr_print64: send attr name bar-name value bar-value
./attr_print64: send attr long_number = 4321
./attr_print64: send attr protocol = test
./attr_print64: send attr number = 4711
./attr_print64: send attr long_number = 1234
./attr_print64: send attr string = whoopee
./attr_print64: send attr data = [data 7 bytes]
./attr_print64: send attr protocol = not-test
./attr_scan64: unknown_stream: wanted attribute: protocol
./attr_scan64: input attribute name: protocol
./attr_scan64: input attribute value: test
./attr_scan64: unknown_stream: wanted attribute: number
./attr_scan64: input attribute name: number
./attr_scan64: input attribute value: 4711
@ -36,6 +42,9 @@
./attr_scan64: input attribute value: 4321
./attr_scan64: unknown_stream: wanted attribute: (list terminator)
./attr_scan64: input attribute name: (end)
./attr_scan64: unknown_stream: wanted attribute: protocol
./attr_scan64: input attribute name: protocol
./attr_scan64: input attribute value: test
./attr_scan64: unknown_stream: wanted attribute: number
./attr_scan64: input attribute name: number
./attr_scan64: input attribute value: 4711
@ -50,6 +59,10 @@
./attr_scan64: input attribute value: whoopee
./attr_scan64: unknown_stream: wanted attribute: (list terminator)
./attr_scan64: input attribute name: (end)
./attr_scan64: unknown_stream: wanted attribute: protocol
./attr_scan64: input attribute name: protocol
./attr_scan64: input attribute value: not-test
./attr_scan64: warning: unexpected protocol not-test from unknown_stream (expected: test)
number 4711
long_number 1234
string whoopee
@ -63,3 +76,4 @@ string whoopee
data whoopee
(hash) foo-name foo-value
(hash) bar-name bar-value
return: -1

View File

@ -100,6 +100,9 @@
/* This argument is followed by an attribute name and a long pointer.
/* .IP "RECV_ATTR_STR(const char *name, VSTRING *vp)"
/* This argument is followed by an attribute name and a VSTRING pointer.
/* .IP "RECV_ATTR_STREQ(const char *name, const char *value)"
/* The name and value must match what the client sends.
/* This attribute does not increment the result value.
/* .IP "RECV_ATTR_DATA(const char *name, VSTRING *vp)"
/* This argument is followed by an attribute name and a VSTRING pointer.
/* .IP "RECV_ATTR_FUNC(ATTR_SCAN_CUSTOM_FN, void *data)"
@ -294,6 +297,7 @@ int attr_vscan_plain(VSTREAM *fp, int flags, va_list ap)
int conversions;
ATTR_SCAN_CUSTOM_FN scan_fn;
void *scan_arg;
const char *expect_val;
/*
* Sanity check.
@ -458,6 +462,24 @@ int attr_vscan_plain(VSTREAM *fp, int flags, va_list ap)
if (scan_fn(attr_scan_plain, fp, flags | ATTR_FLAG_MORE, scan_arg) < 0)
return (-1);
break;
case ATTR_TYPE_STREQ:
if (ch != '=') {
msg_warn("missing value for string attribute %s from %s",
STR(name_buf), VSTREAM_PATH(fp));
return (-1);
}
expect_val = va_arg(ap, const char *);
if ((ch = attr_scan_plain_string(fp, str_buf, 0,
"input attribute value")) < 0)
return (-1);
if (strcmp(expect_val, STR(str_buf)) != 0) {
msg_warn("unexpected %s %s from %s (expected: %s)",
STR(name_buf), STR(str_buf), VSTREAM_PATH(fp),
expect_val);
return (-1);
}
conversions -= 1;
break;
case ATTR_TYPE_HASH:
case ATTR_TYPE_CLOSE:
if (ch != '=') {
@ -555,6 +577,7 @@ int main(int unused_argc, char **used_argv)
msg_vstream_init(used_argv[0], VSTREAM_ERR);
if ((ret = attr_scan_plain(VSTREAM_IN,
ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
RECV_ATTR_STR(ATTR_NAME_STR, str_val),
@ -576,6 +599,7 @@ int main(int unused_argc, char **used_argv)
}
if ((ret = attr_scan_plain(VSTREAM_IN,
ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
RECV_ATTR_STR(ATTR_NAME_STR, str_val),
@ -592,6 +616,11 @@ int main(int unused_argc, char **used_argv)
} else {
vstream_printf("return: %d\n", ret);
}
if ((ret = attr_scan_plain(VSTREAM_IN,
ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
ATTR_TYPE_END)) != 0)
vstream_printf("return: %d\n", ret);
if (vstream_fflush(VSTREAM_OUT) != 0)
msg_fatal("write error: %m");

View File

@ -1,3 +1,4 @@
./attr_print_plain: send attr protocol = test
./attr_print_plain: send attr number = 4711
./attr_print_plain: send attr long_number = 1234
./attr_print_plain: send attr string = whoopee
@ -5,10 +6,15 @@
./attr_print_plain: send attr name foo-name value foo-value
./attr_print_plain: send attr name bar-name value bar-value
./attr_print_plain: send attr long_number = 4321
./attr_print_plain: send attr protocol = test
./attr_print_plain: send attr number = 4711
./attr_print_plain: send attr long_number = 1234
./attr_print_plain: send attr string = whoopee
./attr_print_plain: send attr data = [data 7 bytes]
./attr_print_plain: send attr protocol = not-test
./attr_scan_plain: unknown_stream: wanted attribute: protocol
./attr_scan_plain: input attribute name: protocol
./attr_scan_plain: input attribute value: test
./attr_scan_plain: unknown_stream: wanted attribute: number
./attr_scan_plain: input attribute name: number
./attr_scan_plain: input attribute value: 4711
@ -36,6 +42,9 @@
./attr_scan_plain: input attribute value: 4321
./attr_scan_plain: unknown_stream: wanted attribute: (list terminator)
./attr_scan_plain: input attribute name: (end)
./attr_scan_plain: unknown_stream: wanted attribute: protocol
./attr_scan_plain: input attribute name: protocol
./attr_scan_plain: input attribute value: test
./attr_scan_plain: unknown_stream: wanted attribute: number
./attr_scan_plain: input attribute name: number
./attr_scan_plain: input attribute value: 4711
@ -50,6 +59,10 @@
./attr_scan_plain: input attribute value: d2hvb3BlZQ==
./attr_scan_plain: unknown_stream: wanted attribute: (list terminator)
./attr_scan_plain: input attribute name: (end)
./attr_scan_plain: unknown_stream: wanted attribute: protocol
./attr_scan_plain: input attribute name: protocol
./attr_scan_plain: input attribute value: not-test
./attr_scan_plain: warning: unexpected protocol not-test from unknown_stream (expected: test)
number 4711
long_number 1234
string whoopee
@ -63,3 +76,4 @@ string whoopee
data whoopee
(hash) foo-name foo-value
(hash) bar-name bar-value
return: -1

View File

@ -6,6 +6,8 @@
/* SYNOPSIS
/* #include <auto_clnt.h>
/*
/* typedef void (*AUTO_CLNT_HANDSHAKE_FN)(VSTREAM *);
/*
/* AUTO_CLNT *auto_clnt_create(service, timeout, max_idle, max_ttl)
/* const char *service;
/* int timeout;
@ -23,6 +25,10 @@
/*
/* void auto_clnt_free(auto_clnt)
/* AUTO_CLNT *auto_clnt;
/*
/* void auto_clnt_control(auto_clnt, name, value, ... AUTO_CLNT_CTL_END)
/* AUTO_CLNT *auto_clnt;
/* int name;
/* DESCRIPTION
/* This module maintains IPC client endpoints that automatically
/* disconnect after a being idle for a configurable amount of time,
@ -47,6 +53,15 @@
/*
/* auto_clnt_free() destroys of the specified client endpoint.
/*
/* auto_clnt_control() allows the user to fine tune the behavior of
/* the specified client. The arguments are a list of (name, value)
/* terminated with AUTO_CLNT_CTL_END.
/* The following lists the names and the types of the corresponding
/* value arguments.
/* .IP "AUTO_CLNT_CTL_HANDSHAKE(VSTREAM *)"
/* A pointer to function that will be called at the start of a
/* new connection, and that returns 0 in case of success.
/* .PP
/* Arguments:
/* .IP service
/* The service argument specifies "transport:servername" where
@ -79,6 +94,10 @@
/* is expected to set the stream pathname to the server endpoint name.
/* .IP context
/* Application context that is passed to the open_action routine.
/* .IP handshake
/* A null pointer, or a pointer to function that will be called
/* at the start of a new connection and that returns 0 in case
/* of success.
/* DIAGNOSTICS
/* Warnings: communication failure. Fatal error: out of memory.
/* LICENSE
@ -90,6 +109,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -120,6 +144,7 @@ struct AUTO_CLNT {
int timeout; /* I/O time limit */
int max_idle; /* time before client disconnect */
int max_ttl; /* time before client disconnect */
AUTO_CLNT_HANDSHAKE_FN handshake; /* new connection only */
int (*connect) (const char *, int, int); /* unix, local, inet */
};
@ -250,6 +275,7 @@ void auto_clnt_recover(AUTO_CLNT *auto_clnt)
VSTREAM *auto_clnt_access(AUTO_CLNT *auto_clnt)
{
AUTO_CLNT_HANDSHAKE_FN handshake;
/*
* Open a stream or restart the idle timer.
@ -258,11 +284,15 @@ VSTREAM *auto_clnt_access(AUTO_CLNT *auto_clnt)
*/
if (auto_clnt->vstream == 0) {
auto_clnt_open(auto_clnt);
handshake = (auto_clnt->vstream ? auto_clnt->handshake : 0);
} else {
if (auto_clnt->max_idle > 0)
event_request_timer(auto_clnt_event, (void *) auto_clnt,
auto_clnt->max_idle);
handshake = 0;
}
if (handshake != 0 && handshake(auto_clnt->vstream) != 0)
return (0);
return (auto_clnt->vstream);
}
@ -290,6 +320,7 @@ AUTO_CLNT *auto_clnt_create(const char *service, int timeout,
auto_clnt->timeout = timeout;
auto_clnt->max_idle = max_idle;
auto_clnt->max_ttl = max_ttl;
auto_clnt->handshake = 0;
if (strcmp(transport, "inet") == 0) {
auto_clnt->connect = inet_connect;
} else if (strcmp(transport, "local") == 0) {
@ -320,3 +351,22 @@ void auto_clnt_free(AUTO_CLNT *auto_clnt)
myfree(auto_clnt->endpoint);
myfree((void *) auto_clnt);
}
/* auto_clnt_control - fine control */
void auto_clnt_control(AUTO_CLNT *client, int name,...)
{
const char *myname = "auto_clnt_control";
va_list ap;
for (va_start(ap, name); name != AUTO_CLNT_CTL_END; name = va_arg(ap, int)) {
switch (name) {
case AUTO_CLNT_CTL_HANDSHAKE:
client->handshake = va_arg(ap, AUTO_CLNT_HANDSHAKE_FN);
break;
default:
msg_panic("%s: bad name %d", myname, name);
}
}
va_end(ap);
}

View File

@ -20,12 +20,17 @@
* External interface.
*/
typedef struct AUTO_CLNT AUTO_CLNT;
typedef int (*AUTO_CLNT_HANDSHAKE_FN) (VSTREAM *);
extern AUTO_CLNT *auto_clnt_create(const char *, int, int, int);
extern VSTREAM *auto_clnt_access(AUTO_CLNT *);
extern void auto_clnt_recover(AUTO_CLNT *);
extern const char *auto_clnt_name(AUTO_CLNT *);
extern void auto_clnt_free(AUTO_CLNT *);
extern void auto_clnt_control(AUTO_CLNT *, int,...);
#define AUTO_CLNT_CTL_END 0
#define AUTO_CLNT_CTL_HANDSHAKE 1 /* handshake before first request */
/* LICENSE
/* .ad
@ -36,6 +41,11 @@ extern void auto_clnt_free(AUTO_CLNT *);
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
#endif

View File

@ -95,7 +95,6 @@
#include <vstream.h>
#include <msg_vstream.h>
#include <stringops.h>
#include <percentm.h>
#include <msg_output.h>
/*
@ -165,7 +164,7 @@ void msg_vprintf(int level, const char *format, va_list ap)
msg_vstream_init("unknown", VSTREAM_ERR);
vp = msg_buffers[msg_vprintf_level - 1];
/* OK if terminating signal handler hijacks control before next stmt. */
vstring_vsprintf(vp, percentm(format, errno), ap);
vstring_vsprintf(vp, format, ap);
printable(vstring_str(vp), '?');
for (i = 0; i < msg_output_fn_count; i++)
msg_output_fn[i] (level, vstring_str(vp));

View File

@ -1,84 +0,0 @@
/*++
/* NAME
/* percentm 3
/* SUMMARY
/* expand %m embedded in string to system error text
/* SYNOPSIS
/* #include <percentm.h>
/*
/* char *percentm(const char *src, int err)
/* DESCRIPTION
/* The percentm() routine makes a copy of the null-terminated string
/* given via the \fIsrc\fR argument, with %m sequences replaced by
/* the system error text corresponding to the \fIerr\fR argument.
/* The result is overwritten upon each successive call.
/*
/* Arguments:
/* .IP src
/* A null-terminated input string with zero or more %m sequences.
/* .IP err
/* A legal \fIerrno\fR value. The text corresponding to this error
/* value is used when expanding %m sequences.
/* SEE ALSO
/* syslog(3) system logger library
/* HISTORY
/* .ad
/* .fi
/* A percentm() routine appears in the TCP Wrapper software
/* by Wietse Venema.
/* 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 libraries. */
#include <sys_defs.h>
#include <string.h>
/* Utility library. */
#include "vstring.h"
#include "percentm.h"
/* percentm - replace %m by error message corresponding to value in err */
char *percentm(const char *str, int err)
{
static VSTRING *vp;
const unsigned char *ip = (const unsigned char *) str;
if (vp == 0)
vp = vstring_alloc(100); /* grows on demand */
VSTRING_RESET(vp);
while (*ip) {
switch (*ip) {
default:
VSTRING_ADDCH(vp, *ip++);
break;
case '%':
switch (ip[1]) {
default: /* leave %<any> alone */
VSTRING_ADDCH(vp, *ip++);
/* FALLTHROUGH */
case '\0': /* don't fall off end */
VSTRING_ADDCH(vp, *ip++);
break;
case 'm': /* replace %m */
vstring_strcat(vp, strerror(err));
ip += 2;
break;
}
}
}
VSTRING_TERMINATE(vp);
return (vstring_str(vp));
}

View File

@ -1,35 +0,0 @@
#ifndef _PERCENT_H_INCLUDED_
#define _PERCENT_H_INCLUDED_
/*++
/* NAME
/* percentm 3h
/* SUMMARY
/* expand %m embedded in string to system error text
/* SYNOPSIS
/* #include <percentm.h>
/* DESCRIPTION
/* .nf
/*
* External interface.
*/
extern char *percentm(const char *, int);
/* HISTORY
/* .ad
/* .fi
/* A percentm() routine appears in the TCP Wrapper software
/* by Wietse Venema.
/* 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

View File

@ -526,8 +526,8 @@ static void verify_query_service(VSTREAM *client_stream)
(addr_status != DEL_RCPT_STAT_OK && updated + var_verify_neg_try < now)
if (now - probed > PROBE_TTL
&& (POSITIVE_REFRESH_NEEDED(addr_status, updated)
|| NEGATIVE_REFRESH_NEEDED(addr_status, updated))) {
&& (POSITIVE_REFRESH_NEEDED(addr_status, updated)
|| NEGATIVE_REFRESH_NEEDED(addr_status, updated))) {
if (msg_verbose)
msg_info("PROBE %s status=%d probed=%ld updated=%ld",
STR(addr), addr_status, now, updated);
@ -723,6 +723,21 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
RESTORE_SAVED_EUGID();
}
/* post_accept_init - announce our protocol */
static void post_accept_init(VSTREAM *stream, char *unused_name,
char **unused_argv, HTABLE *unused_table)
{
/*
* Announce the protocol.
*/
attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_VERIFY),
ATTR_TYPE_END);
(void) vstream_fflush(stream);
}
MAIL_VERSION_STAMP_DECLARE;
/* main - pass control to the multi-threaded skeleton */
@ -754,6 +769,7 @@ int main(int argc, char **argv)
CA_MAIL_SERVER_TIME_TABLE(time_table),
CA_MAIL_SERVER_PRE_INIT(pre_jail_init),
CA_MAIL_SERVER_POST_INIT(post_jail_init),
CA_MAIL_SERVER_POST_ACCEPT(post_accept_init),
CA_MAIL_SERVER_SOLITARY,
CA_MAIL_SERVER_EXIT(verify_dump),
0);