2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-25 11:27:48 +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_MATCH_LIST
-TADDR_PATTERN -TADDR_PATTERN
-TALIAS_TOKEN -TALIAS_TOKEN

View File

@ -25057,6 +25057,8 @@ Apologies for any names omitted.
mantools/man2html, mantools/readme2html, proto/*_README.html, mantools/man2html, mantools/readme2html, proto/*_README.html,
proto/INSTALL.html, proto/postconf.html.prolog, html/index.html. proto/INSTALL.html, proto/postconf.html.prolog, html/index.html.
20200830
Refactor: moved the SASL mechanism filter code from the Refactor: moved the SASL mechanism filter code from the
Postfix SMTP client to a library module, so that it can be Postfix SMTP client to a library module, so that it can be
reused in the Postfix SMTP server. Files: smtp/smtp_sasl_proto.c, 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 wants to anounce EXTERNAL support for which Postfix support
does not exist. Files: smtpd/smtpd.[hc], smtpd_sasl_glue.[hc], does not exist. Files: smtpd/smtpd.[hc], smtpd_sasl_glue.[hc],
global/mail_params.h, proto/postconf.proto, mantools/postlink. 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 the software under the license of their choice. Those who are more
comfortable with the IPL can continue with that license. 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 Incompatible change with snapshot 20200705
========================================== ==========================================

View File

@ -1,5 +1,23 @@
Wish list: 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_tls_security_options = noanonymous, and make
smtp_sasl_security_options default dependent on the smtp_sasl_security_options default dependent on the
smtp_sasl_tls_security_options default (i.e. reverse 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. Postfix 2.6 the default protocol is 2.
<b><a href="postconf.5.html#milter_default_action">milter_default_action</a> (tempfail)</b> <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 The default action when a Milter (mail filter) response is
unavailable or mis-configured. 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> <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. 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> <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. tion, and for negotiating protocol options.
<b><a href="postconf.5.html#milter_command_timeout">milter_command_timeout</a> (30s)</b> <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. filter) application, and for receiving the response.
<b><a href="postconf.5.html#milter_content_timeout">milter_content_timeout</a> (300s)</b> <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. 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> <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. after completion of an SMTP connection.
<b><a href="postconf.5.html#milter_helo_macros">milter_helo_macros</a> (see 'postconf -d' output)</b> <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. 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> <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. after the SMTP MAIL FROM command.
<b><a href="postconf.5.html#milter_rcpt_macros">milter_rcpt_macros</a> (see 'postconf -d' output)</b> <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. after the SMTP RCPT TO command.
<b><a href="postconf.5.html#milter_data_macros">milter_data_macros</a> (see 'postconf -d' output)</b> <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. 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> <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. 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> <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. after the message end-of-data.
Available in Postfix version 2.5 and later: 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> <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. after the end of the message header.
Available in Postfix version 2.7 and later: Available in Postfix version 2.7 and later:
@ -227,8 +228,8 @@ CLEANUP(8) CLEANUP(8)
Available in Postfix version 3.1 and later: Available in Postfix version 3.1 and later:
<b><a href="postconf.5.html#milter_macro_defaults">milter_macro_defaults</a> (empty)</b> <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 Optional list of <i>name=value</i> pairs that specify default values
for arbitrary macros that Postfix may send to Milter applica- for arbitrary macros that Postfix may send to Milter applica-
tions. tions.
<b>MIME PROCESSING CONTROLS</b> <b>MIME PROCESSING CONTROLS</b>
@ -254,91 +255,91 @@ CLEANUP(8) CLEANUP(8)
ing information. ing information.
<b><a href="postconf.5.html#strict_mime_encoding_domain">strict_mime_encoding_domain</a> (no)</b> <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. for the message/* or multipart/* MIME content types.
Available in Postfix version 2.5 and later: 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> <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- Automatically detect 8BITMIME body content by looking at Con-
tent-Transfer-Encoding: message headers; historically, this tent-Transfer-Encoding: message headers; historically, this
behavior was hard-coded to be "always on". behavior was hard-coded to be "always on".
<b>AUTOMATIC BCC RECIPIENT CONTROLS</b> <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: the mail system:
<b><a href="postconf.5.html#always_bcc">always_bcc</a> (empty)</b> <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. message that is received by the Postfix mail system.
Available in Postfix version 2.1 and later: Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#sender_bcc_maps">sender_bcc_maps</a> (empty)</b> <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. by sender address.
<b><a href="postconf.5.html#recipient_bcc_maps">recipient_bcc_maps</a> (empty)</b> <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. by recipient address.
<b>ADDRESS TRANSFORMATION CONTROLS</b> <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. <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> <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. The recipient of mail addressed to the null address.
<b><a href="postconf.5.html#canonical_maps">canonical_maps</a> (empty)</b> <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. envelopes.
<b><a href="postconf.5.html#recipient_canonical_maps">recipient_canonical_maps</a> (empty)</b> <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. recipient addresses.
<b><a href="postconf.5.html#sender_canonical_maps">sender_canonical_maps</a> (empty)</b> <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. sender addresses.
<b><a href="postconf.5.html#masquerade_classes">masquerade_classes</a> (envelope_sender, header_sender, header_recipient)</b> <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. What addresses are subject to address masquerading.
<b><a href="postconf.5.html#masquerade_domains">masquerade_domains</a> (empty)</b> <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. stripped off in email addresses.
<b><a href="postconf.5.html#masquerade_exceptions">masquerade_exceptions</a> (empty)</b> <b><a href="postconf.5.html#masquerade_exceptions">masquerade_exceptions</a> (empty)</b>
Optional list of user names that are not subjected to address 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>- 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>. <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> <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. lookup key to the lookup result.
Available before Postfix version 2.0: Available before Postfix version 2.0:
<b><a href="postconf.5.html#virtual_maps">virtual_maps</a> (empty)</b> <b><a href="postconf.5.html#virtual_maps">virtual_maps</a> (empty)</b>
Optional lookup tables with a) names of domains for which all Optional lookup tables with a) names of domains for which all
addresses are aliased to addresses in other local or remote addresses are aliased to addresses in other local or remote
domains, and b) addresses that are aliased to addresses in other domains, and b) addresses that are aliased to addresses in other
local or remote domains. local or remote domains.
Available in Postfix version 2.0 and later: 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> <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. domains to other local or remote address.
Available in Postfix version 2.2 and later: 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> <b>header_recipient)</b>
What addresses are subject to <a href="postconf.5.html#canonical_maps">canonical_maps</a> address mapping. 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> <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. mapping.
<b><a href="postconf.5.html#sender_canonical_classes">sender_canonical_classes</a> (envelope_sender, header_sender)</b> <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. ping.
<b><a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> (empty)</b> <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 Don't rewrite message headers from remote clients at all when
this parameter is empty; otherwise, rewrite message headers and this parameter is empty; otherwise, rewrite message headers and
append the specified domain name to incomplete addresses. append the specified domain name to incomplete addresses.
<b>RESOURCE AND RATE CONTROLS</b> <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. <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> <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. header.
<b><a href="postconf.5.html#hopcount_limit">hopcount_limit</a> (50)</b> <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. in the primary message headers.
<b><a href="postconf.5.html#in_flow_delay">in_flow_delay</a> (1s)</b> <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. arrival rate exceeds the message delivery rate.
<b><a href="postconf.5.html#message_size_limit">message_size_limit</a> (10240000)</b> <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. information.
Available in Postfix version 2.0 and later: 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> <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. message header.
<b><a href="postconf.5.html#mime_boundary_length_limit">mime_boundary_length_limit</a> (2048)</b> <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: 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> <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. produces from each original recipient.
<b><a href="postconf.5.html#virtual_alias_recursion_limit">virtual_alias_recursion_limit</a> (1000)</b> <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: 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> <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. expansion.
<b>SMTPUTF8 CONTROLS</b> <b>SMTPUTF8 CONTROLS</b>
Preliminary SMTPUTF8 support is introduced with Postfix 3.0. Preliminary SMTPUTF8 support is introduced with Postfix 3.0.
<b><a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> (yes)</b> <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. 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> <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. fied mail origin classes.
Available in Postfix version 3.2 and later: Available in Postfix version 3.2 and later:
<b><a href="postconf.5.html#enable_idna2003_compatibility">enable_idna2003_compatibility</a> (no)</b> <b><a href="postconf.5.html#enable_idna2003_compatibility">enable_idna2003_compatibility</a> (no)</b>
Enable 'transitional' compatibility between IDNA2003 and Enable 'transitional' compatibility between IDNA2003 and
IDNA2008, when converting UTF-8 domain names to/from the ASCII IDNA2008, when converting UTF-8 domain names to/from the ASCII
form that is used for DNS lookups. form that is used for DNS lookups.
<b>MISCELLANEOUS CONTROLS</b> <b>MISCELLANEOUS CONTROLS</b>
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</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. figuration files.
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b> <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. 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> <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. ging sub-second delay values.
<b><a href="postconf.5.html#delay_warning_time">delay_warning_time</a> (0h)</b> <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. headers of mail that is still queued.
<b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b> <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. internal communication channel.
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b> <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. waits for an incoming connection before terminating voluntarily.
<b><a href="postconf.5.html#max_use">max_use</a> (100)</b> <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. 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> <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. and that locally posted mail is delivered to.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b> <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. The location of the Postfix top-level queue directory.
<b><a href="postconf.5.html#soft_bounce">soft_bounce</a> (no)</b> <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. to the sender.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b> <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging. The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b> <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". records, so that, for example, "smtpd" becomes "prefix/smtpd".
Available in Postfix version 2.1 and later: Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#enable_original_recipient">enable_original_recipient</a> (yes)</b> <b><a href="postconf.5.html#enable_original_recipient">enable_original_recipient</a> (yes)</b>
Enable support for the original recipient address after an Enable support for the original recipient address after an
address is rewritten to a different address (for example with address is rewritten to a different address (for example with
aliasing or with canonical mapping). aliasing or with canonical mapping).
Available in Postfix 3.3 and later: Available in Postfix 3.3 and later:
@ -492,7 +493,7 @@ CLEANUP(8) CLEANUP(8)
Available in Postfix 3.5 and later: Available in Postfix 3.5 and later:
<b>info_log_address_format (external)</b> <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.). (info, warning, etc.).
<b>FILES</b> <b>FILES</b>

View File

@ -169,8 +169,8 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8)
explicit ".example.com" pattern. explicit ".example.com" pattern.
<b><a href="postconf.5.html#relayhost">relayhost</a> (empty)</b> <b><a href="postconf.5.html#relayhost">relayhost</a> (empty)</b>
The next-hop destination of non-local mail; overrides non-local The next-hop destination(s) for non-local mail; overrides
domains in recipient addresses. 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> <b><a href="postconf.5.html#transport_maps">transport_maps</a> (empty)</b>
Optional lookup tables with mappings from recipient address to 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 for communication with a Milter application; prior to Postfix 2.6
the default protocol is 2. the default protocol is 2.
.IP "\fBmilter_default_action (tempfail)\fR" .IP "\fBmilter_default_action (tempfail)\fR"
The default action when a Milter (mail filter) application is The default action when a Milter (mail filter) response is
unavailable or mis\-configured. unavailable (for example, bad Postfix configuration or Milter
failure).
.IP "\fBmilter_macro_daemon_name ($myhostname)\fR" .IP "\fBmilter_macro_daemon_name ($myhostname)\fR"
The {daemon_name} macro value for Milter (mail filter) applications. The {daemon_name} macro value for Milter (mail filter) applications.
.IP "\fBmilter_macro_v ($mail_name $mail_version)\fR" .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, matches subdomains of example.com,
instead of requiring an explicit ".example.com" pattern. instead of requiring an explicit ".example.com" pattern.
.IP "\fBrelayhost (empty)\fR" .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. domains in recipient addresses.
.IP "\fBtransport_maps (empty)\fR" .IP "\fBtransport_maps (empty)\fR"
Optional lookup tables with mappings from recipient address to 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; 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 */ /* main - pass control to the multi-threaded skeleton */
int main(int argc, char **argv) int main(int argc, char **argv)
@ -1024,6 +1039,7 @@ int main(int argc, char **argv)
multi_server_main(argc, argv, anvil_service, multi_server_main(argc, argv, anvil_service,
CA_MAIL_SERVER_TIME_TABLE(time_table), CA_MAIL_SERVER_TIME_TABLE(time_table),
CA_MAIL_SERVER_POST_INIT(post_jail_init), CA_MAIL_SERVER_POST_INIT(post_jail_init),
CA_MAIL_SERVER_POST_ACCEPT(post_accept),
CA_MAIL_SERVER_SOLITARY, CA_MAIL_SERVER_SOLITARY,
CA_MAIL_SERVER_PRE_DISCONN(anvil_service_done), CA_MAIL_SERVER_PRE_DISCONN(anvil_service_done),
CA_MAIL_SERVER_EXIT(anvil_status_dump), 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) if (mail_queue_name_ok(service_name) == 0)
msg_fatal("malformed service name: %s", service_name); 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 * Read and validate the first parameter of the client request. Let the
* request-specific protocol routines take care of the remainder. * 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 /* for communication with a Milter application; prior to Postfix 2.6
/* the default protocol is 2. /* the default protocol is 2.
/* .IP "\fBmilter_default_action (tempfail)\fR" /* .IP "\fBmilter_default_action (tempfail)\fR"
/* The default action when a Milter (mail filter) application is /* The default action when a Milter (mail filter) response is
/* unavailable or mis-configured. /* unavailable (for example, bad Postfix configuration or Milter
/* failure).
/* .IP "\fBmilter_macro_daemon_name ($myhostname)\fR" /* .IP "\fBmilter_macro_daemon_name ($myhostname)\fR"
/* The {daemon_name} macro value for Milter (mail filter) applications. /* The {daemon_name} macro value for Milter (mail filter) applications.
/* .IP "\fBmilter_macro_v ($mail_name $mail_version)\fR" /* .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. * about the whole operation.
*/ */
attr_print(src, ATTR_FLAG_NONE, 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), SEND_ATTR_STR(MAIL_ATTR_QUEUEID, state->queue_id),
ATTR_TYPE_END); ATTR_TYPE_END);
if (attr_scan(src, ATTR_FLAG_STRICT, 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; 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. * Kluge: choose the protocol depending on the request size.
*/ */

View File

@ -169,6 +169,11 @@
/* IBM T.J. Watson Research /* IBM T.J. Watson Research
/* P.O. Box 704 /* P.O. Box 704
/* Yorktown Heights, NY 10598, USA /* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/ /*--*/
/* System library. */ /* System library. */
@ -202,10 +207,11 @@ typedef struct {
int command; /* bounce request type */ int command; /* bounce request type */
int flags; /* bounce options */ int flags; /* bounce options */
char *id; /* queue ID for logging */ char *id; /* queue ID for logging */
VSTRING *request; /* serialized request */
ABOUNCE_FN callback; /* application callback */ ABOUNCE_FN callback; /* application callback */
void *context; /* application context */ void *context; /* application context */
VSTREAM *fp; /* server I/O handle */ VSTREAM *fp; /* server I/O handle */
} ABOUNCE; } ABOUNCE_STATE;
/* /*
* Encapsulate common code. * Encapsulate common code.
@ -215,11 +221,6 @@ typedef struct {
event_request_timer((callback), (context), (timeout)); \ event_request_timer((callback), (context), (timeout)); \
} while (0) } 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 * 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 * increasing overload. With 1000s timeout mail will keep flowing, but there
@ -228,11 +229,30 @@ typedef struct {
*/ */
#define ABOUNCE_TIMEOUT 1000 #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 */ /* 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) if (status != 0 && (ap->flags & BOUNCE_FLAG_CLEAN) == 0)
msg_info("%s: status=deferred (%s failed)", ap->id, msg_info("%s: status=deferred (%s failed)", ap->id,
ap->command == BOUNCE_CMD_FLUSH ? "bounce" : ap->command == BOUNCE_CMD_FLUSH ? "bounce" :
@ -242,65 +262,125 @@ static void abounce_done(ABOUNCE *ap, int status)
"whatever"); "whatever");
ap->callback(status, ap->context); ap->callback(status, ap->context);
myfree(ap->id); myfree(ap->id);
vstring_free(ap->request);
myfree((void *) ap); 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; int status;
ABOUNCE_EVENT_DISABLE(vstream_fileno(ap->fp), abounce_event, context); if (event != EVENT_TIME)
abounce_done(ap, (event != EVENT_TIME event_cancel_timer(abounce_receive, context);
&& attr_scan(ap->fp, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &status), if (event == EVENT_READ
ATTR_TYPE_END) == 1) ? status : -1); && 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, static void abounce_send(int event, void *context)
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 *ap; ABOUNCE_STATE *ap = (ABOUNCE_STATE *) context;
/* /*
* Save pseudo thread state. Connect to the server. Send the request and * Receive the server's protocol name announcement. At this point the
* suspend the pseudo thread until the server replies (or dies). * 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->command = command;
ap->flags = flags; ap->flags = flags;
ap->id = mystrdup(id); ap->id = mystrdup(id);
ap->request = vstring_alloc(ABOUNCE_BUFSIZE);
ap->callback = callback; ap->callback = callback;
ap->context = context; 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), * Format the request now, so that we don't have to save a lot of
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags), * arguments now and format the request later.
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue), */
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id), if (ap->fp != 0) {
SEND_ATTR_STR(MAIL_ATTR_ENCODING, encoding), /* Note: all code paths must terminate or enable I/O events. */
SEND_ATTR_INT(MAIL_ATTR_SMTPUTF8, smtputf8), VSTREAM *mp = vstream_memopen(ap->request, O_WRONLY);
SEND_ATTR_STR(MAIL_ATTR_SENDER, sender),
SEND_ATTR_STR(MAIL_ATTR_DSN_ENVID, dsn_envid), if (attr_print(mp, ATTR_FLAG_MORE,
SEND_ATTR_INT(MAIL_ATTR_DSN_RET, dsn_ret), SEND_ATTR_INT(MAIL_ATTR_NREQ, command),
SEND_ATTR_STR(MAIL_ATTR_VERPDL, verp), SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
ATTR_TYPE_END) == 0 SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
&& vstream_fflush(ap->fp) == 0) { SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id),
ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_event, 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); (void *) ap, ABOUNCE_TIMEOUT);
} else { } else {
abounce_done(ap, -1); abounce_done(ap, -1);
@ -316,9 +396,9 @@ void abounce_flush_verp(int flags, const char *queue, const char *id,
ABOUNCE_FN callback, ABOUNCE_FN callback,
void *context) void *context)
{ {
abounce_request_verp(MAIL_CLASS_PRIVATE, var_bounce_service, abounce_connect(MAIL_CLASS_PRIVATE, var_bounce_service,
BOUNCE_CMD_VERP, flags, queue, id, encoding, smtputf8, BOUNCE_CMD_VERP, flags, queue, id, encoding, smtputf8,
sender, dsn_envid, dsn_ret, verp, callback, context); sender, dsn_envid, dsn_ret, verp, callback, context);
} }
/* adefer_flush_verp - asynchronous defer flush */ /* 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) ABOUNCE_FN callback, void *context)
{ {
flags |= BOUNCE_FLAG_DELRCPT; flags |= BOUNCE_FLAG_DELRCPT;
abounce_request_verp(MAIL_CLASS_PRIVATE, var_defer_service, abounce_connect(MAIL_CLASS_PRIVATE, var_defer_service,
BOUNCE_CMD_VERP, flags, queue, id, encoding, smtputf8, BOUNCE_CMD_VERP, flags, queue, id, encoding, smtputf8,
sender, dsn_envid, dsn_ret, verp, callback, context); 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_flush - asynchronous bounce flush */ /* 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, int dsn_ret, ABOUNCE_FN callback,
void *context) 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, flags, queue, id, encoding, smtputf8, sender, dsn_envid,
dsn_ret, callback, context); dsn_ret, ABOUNCE_NO_VERP, callback, context);
} }
/* adefer_flush - asynchronous defer flush */ /* 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) int dsn_ret, ABOUNCE_FN callback, void *context)
{ {
flags |= BOUNCE_FLAG_DELRCPT; 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, 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 */ /* 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, const char *sender, const char *dsn_envid,
int dsn_ret, ABOUNCE_FN callback, void *context) 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, flags, queue, id, encoding, smtputf8, sender, dsn_envid,
dsn_ret, callback, context); dsn_ret, ABOUNCE_NO_VERP, callback, context);
} }
/* atrace_flush - asynchronous trace flush */ /* 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, const char *sender, const char *dsn_envid,
int dsn_ret, ABOUNCE_FN callback, void *context) 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, 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) \ #define ANVIL_IDENT(service, addr) \
printable(concatenate(service, ":", addr, (char *) 0), '?') 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_create - instantiate connection rate service client */
ANVIL_CLNT *anvil_clnt_create(void) ANVIL_CLNT *anvil_clnt_create(void)
@ -186,6 +195,9 @@ ANVIL_CLNT *anvil_clnt_create(void)
#else #else
anvil_clnt = attr_clnt_create(var_anvil_service, var_ipc_timeout, 0, 0); anvil_clnt = attr_clnt_create(var_anvil_service, var_ipc_timeout, 0, 0);
#endif #endif
attr_clnt_control(anvil_clnt,
ATTR_CLNT_CTL_HANDSHAKE, anvil_clnt_handshake,
ATTR_CLNT_CTL_END);
return ((ANVIL_CLNT *) anvil_clnt); return ((ANVIL_CLNT *) anvil_clnt);
} }

View File

@ -186,6 +186,11 @@
/* IBM T.J. Watson Research /* IBM T.J. Watson Research
/* P.O. Box 704 /* P.O. Box 704
/* Yorktown Heights, NY 10598, USA /* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/ /*--*/
/* System library. */ /* 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 ? if (mail_command_client(MAIL_CLASS_PRIVATE, var_soft_bounce ?
var_defer_service : var_bounce_service, var_defer_service : var_bounce_service,
MAIL_ATTR_PROTO_BOUNCE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND), SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags), SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id), 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) if (var_soft_bounce)
return (-1); return (-1);
if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service, 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_NREQ, BOUNCE_CMD_FLUSH),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags), SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue), 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) if (var_soft_bounce)
return (-1); return (-1);
if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service, 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_NREQ, BOUNCE_CMD_VERP),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags), SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue), 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"; my_dsn.action = "failed";
if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service, 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_NREQ, BOUNCE_CMD_ONE),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags), SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue), SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),

View File

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

View File

@ -20,9 +20,12 @@
* External interface. * External interface.
*/ */
typedef struct CLNT_STREAM CLNT_STREAM; 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 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_recover(CLNT_STREAM *);
extern void clnt_stream_free(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 /* IBM T.J. Watson Research
/* P.O. Box 704 /* P.O. Box 704
/* Yorktown Heights, NY 10598, USA /* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/ /*--*/
#endif #endif

View File

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

View File

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

View File

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

View File

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

View File

@ -71,6 +71,11 @@
/* IBM T.J. Watson Research /* IBM T.J. Watson Research
/* P.O. Box 704 /* P.O. Box 704
/* Yorktown Heights, NY 10598, USA /* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/ /*--*/
/* System library. */ /* System library. */
@ -125,6 +130,7 @@ int flush_purge(void)
status = FLUSH_STAT_DENY; status = FLUSH_STAT_DENY;
else else
status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service, status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
MAIL_ATTR_PROTO_FLUSH,
SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_PURGE), SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_PURGE),
ATTR_TYPE_END); ATTR_TYPE_END);
@ -151,6 +157,7 @@ int flush_refresh(void)
status = FLUSH_STAT_DENY; status = FLUSH_STAT_DENY;
else else
status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service, status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
MAIL_ATTR_PROTO_FLUSH,
SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_REFRESH), SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_REFRESH),
ATTR_TYPE_END); ATTR_TYPE_END);
@ -182,6 +189,7 @@ int flush_send_site(const char *site)
VAR_RELAY_DOMAINS "=$mydestination to flush " VAR_RELAY_DOMAINS "=$mydestination to flush "
"mail for domain \"%s\"", site); "mail for domain \"%s\"", site);
status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service, 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_REQ, FLUSH_REQ_SEND_SITE),
SEND_ATTR_STR(MAIL_ATTR_SITE, site), SEND_ATTR_STR(MAIL_ATTR_SITE, site),
ATTR_TYPE_END); ATTR_TYPE_END);
@ -210,6 +218,7 @@ int flush_send_file(const char *queue_id)
* Require that the service is turned on. * Require that the service is turned on.
*/ */
status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service, 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_REQ, FLUSH_REQ_SEND_FILE),
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id), SEND_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id),
ATTR_TYPE_END); ATTR_TYPE_END);
@ -242,6 +251,7 @@ int flush_add(const char *site, const char *queue_id)
VAR_RELAY_DOMAINS "=$mydestination to update " VAR_RELAY_DOMAINS "=$mydestination to update "
"fast-flush logfile for domain \"%s\"", site); "fast-flush logfile for domain \"%s\"", site);
status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service, 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_REQ, FLUSH_REQ_ADD),
SEND_ATTR_STR(MAIL_ATTR_SITE, site), SEND_ATTR_STR(MAIL_ATTR_SITE, site),
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id), 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"); return ("unsupported network protocol");
} }
/* For now, skip and ignore TLVs. */ /* For now, skip and ignore TLVs. */
*non_proxy = 0;
*str_len = PP2_HEADER_LEN + ntohs(hdr_v2->len); *str_len = PP2_HEADER_LEN + ntohs(hdr_v2->len);
return (0); return (0);
@ -434,6 +433,8 @@ const char *haproxy_srvr_parse(const char *str, ssize_t *str_len,
if (proto_info == 0) if (proto_info == 0)
proto_info = inet_proto_info(); proto_info = inet_proto_info();
*non_proxy = 0;
/* /*
* XXX We don't accept connections with the "UNKNOWN" protocol type, * XXX We don't accept connections with the "UNKNOWN" protocol type,
* because those would sidestep address-based access control mechanisms. * 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); myfree(saved_str);
*non_proxy = 0;
return (err); return (err);
} }

View File

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

View File

@ -114,11 +114,32 @@
*/ */
extern VSTREAM *mail_connect(const char *, const char *, int); extern VSTREAM *mail_connect(const char *, const char *, int);
extern VSTREAM *mail_connect_wait(const char *, const char *); 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_command_server(VSTREAM *,...);
extern int mail_trigger(const char *, const char *, const char *, ssize_t); extern int mail_trigger(const char *, const char *, const char *, ssize_t);
extern char *mail_pathname(const char *, const char *); 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. * Attribute names.
*/ */

View File

@ -105,6 +105,11 @@
/* IBM T.J. Watson Research /* IBM T.J. Watson Research
/* P.O. Box 704 /* P.O. Box 704
/* Yorktown Heights, NY 10598, USA /* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/ /*--*/
/* System library. */ /* System library. */
@ -440,7 +445,8 @@ MAIL_STREAM *mail_stream_service(const char *class, const char *name)
id_buf = vstring_alloc(10); id_buf = vstring_alloc(10);
stream = mail_connect_wait(class, name); 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) { RECV_ATTR_STR(MAIL_ATTR_QUEUEID, id_buf), 0) != 1) {
vstream_fclose(stream); vstream_fclose(stream);
return (0); return (0);
@ -492,7 +498,8 @@ MAIL_STREAM *mail_stream_command(const char *command)
CA_VSTREAM_CTL_PATH(command), CA_VSTREAM_CTL_PATH(command),
CA_VSTREAM_CTL_END); 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) { RECV_ATTR_STR(MAIL_ATTR_QUEUEID, id_buf), 0) != 1) {
if ((status = vstream_pclose(stream)) != 0) if ((status = vstream_pclose(stream)) != 0)
msg_warn("command \"%s\" exited with status %d", command, status); 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 * Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only. * patchlevel; they change the release date only.
*/ */
#define MAIL_RELEASE_DATE "20200830" #define MAIL_RELEASE_DATE "20200920"
#define MAIL_VERSION_NUMBER "3.6" #define MAIL_VERSION_NUMBER "3.6"
#ifdef SNAPSHOT #ifdef SNAPSHOT

View File

@ -231,8 +231,18 @@ static void post_mail_init(VSTREAM *stream, const char *sender,
date = mail_date(now.tv_sec); date = mail_date(now.tv_sec);
/* /*
* XXX Don't flush buffers while sending the initial message records. * The comment in the next paragraph is likely obsolete. Fix 20030610
* That would cause deadlock between verify(8) and cleanup(8) servers. * 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_control(stream, VSTREAM_CTL_BUFSIZE, 2 * VSTREAM_BUFSIZE,
VSTREAM_CTL_END); 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. * Negotiate with the cleanup service. Give up if we can't agree.
*/ */
if (attr_scan(stream, ATTR_FLAG_STRICT, if (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP),
RECV_ATTR_STR(MAIL_ATTR_QUEUEID, id), RECV_ATTR_STR(MAIL_ATTR_QUEUEID, id),
ATTR_TYPE_END) != 1 ATTR_TYPE_END) != 1
|| attr_print(stream, ATTR_FLAG_NONE, || attr_print(stream, ATTR_FLAG_NONE,

View File

@ -152,6 +152,15 @@ void resolve_clnt_init(RESOLVE_REPLY *reply)
reply->flags = 0; 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) */ /* resolve_clnt - resolve address to (transport, next hop, recipient) */
void resolve_clnt(const char *class, const char *sender, 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, rewrite_clnt_stream = clnt_stream_create(MAIL_CLASS_PRIVATE,
var_rewrite_service, var_rewrite_service,
var_ipc_idle_limit, var_ipc_idle_limit,
var_ipc_ttl_limit); var_ipc_ttl_limit,
resolve_clnt_handshake);
for (;;) { for (;;) {
stream = clnt_stream_access(rewrite_clnt_stream); stream = clnt_stream_access(rewrite_clnt_stream);
errno = 0; errno = 0;
count += 1; count += 1;
if (attr_print(stream, ATTR_FLAG_NONE, if (stream == 0
SEND_ATTR_STR(MAIL_ATTR_REQ, class), || attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_SENDER, sender), SEND_ATTR_STR(MAIL_ATTR_REQ, class),
SEND_ATTR_STR(MAIL_ATTR_ADDR, addr), SEND_ATTR_STR(MAIL_ATTR_SENDER, sender),
ATTR_TYPE_END) != 0 SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),
ATTR_TYPE_END) != 0
|| vstream_fflush(stream) || vstream_fflush(stream)
|| attr_scan(stream, ATTR_FLAG_STRICT, || attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_FLAGS, &server_flags), RECV_ATTR_INT(MAIL_ATTR_FLAGS, &server_flags),

View File

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

View File

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

View File

@ -41,6 +41,11 @@
/* IBM T.J. Watson Research /* IBM T.J. Watson Research
/* P.O. Box 704 /* P.O. Box 704
/* Yorktown Heights, NY 10598, USA /* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/ /*--*/
/* System library. */ /* System library. */
@ -80,6 +85,15 @@ typedef struct {
#define SCACHE_MAX_TRIES 2 #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 */ /* scache_clnt_save_endp - save endpoint */
static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl, 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->size = scache_clnt_size;
sp->scache->free = scache_clnt_free; 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); 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); myfree(service);
#ifdef CANT_WRITE_BEFORE_SENDING_FD #ifdef CANT_WRITE_BEFORE_SENDING_FD

View File

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

View File

@ -56,6 +56,11 @@
/* IBM T.J. Watson Research /* IBM T.J. Watson Research
/* P.O. Box 704 /* P.O. Box 704
/* Yorktown Heights, NY 10598, USA /* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/ /*--*/
/* System library. */ /* System library. */
@ -80,6 +85,15 @@
CLNT_STREAM *vrfy_clnt; 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 */ /* verify_clnt_init - initialize */
static void verify_clnt_init(void) static void verify_clnt_init(void)
@ -87,7 +101,8 @@ static void verify_clnt_init(void)
if (vrfy_clnt != 0) if (vrfy_clnt != 0)
msg_panic("verify_clnt_init: multiple initialization"); msg_panic("verify_clnt_init: multiple initialization");
vrfy_clnt = clnt_stream_create(MAIL_CLASS_PRIVATE, var_verify_service, 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 */ /* 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); stream = clnt_stream_access(vrfy_clnt);
errno = 0; errno = 0;
count += 1; count += 1;
if (attr_print(stream, ATTR_FLAG_NONE, if (stream == 0
SEND_ATTR_STR(MAIL_ATTR_REQ, VRFY_REQ_QUERY), || attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_ADDR, addr), SEND_ATTR_STR(MAIL_ATTR_REQ, VRFY_REQ_QUERY),
ATTR_TYPE_END) != 0 SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),
ATTR_TYPE_END) != 0
|| vstream_fflush(stream) || vstream_fflush(stream)
|| attr_scan(stream, ATTR_FLAG_MISSING, || attr_scan(stream, ATTR_FLAG_MISSING,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &request_status), 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 (;;) { for (;;) {
stream = clnt_stream_access(vrfy_clnt); stream = clnt_stream_access(vrfy_clnt);
errno = 0; errno = 0;
if (attr_print(stream, ATTR_FLAG_NONE, if (stream == 0
SEND_ATTR_STR(MAIL_ATTR_REQ, VRFY_REQ_UPDATE), || attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_ADDR, addr), SEND_ATTR_STR(MAIL_ATTR_REQ, VRFY_REQ_UPDATE),
SEND_ATTR_INT(MAIL_ATTR_ADDR_STATUS, addr_status), SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),
SEND_ATTR_STR(MAIL_ATTR_WHY, why), SEND_ATTR_INT(MAIL_ATTR_ADDR_STATUS, addr_status),
ATTR_TYPE_END) != 0 SEND_ATTR_STR(MAIL_ATTR_WHY, why),
ATTR_TYPE_END) != 0
|| attr_scan(stream, ATTR_FLAG_MISSING, || attr_scan(stream, ATTR_FLAG_MISSING,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &request_status), RECV_ATTR_INT(MAIL_ATTR_STATUS, &request_status),
ATTR_TYPE_END) != 1) { 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); close_on_exec(vstream_fileno(cleanup), CLOSE_ON_EXEC);
if (attr_scan(cleanup, ATTR_FLAG_STRICT, if (attr_scan(cleanup, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP),
RECV_ATTR_STR(MAIL_ATTR_QUEUEID, buffer), RECV_ATTR_STR(MAIL_ATTR_QUEUEID, buffer),
ATTR_TYPE_END) != 1) { ATTR_TYPE_END) != 1) {
vstream_fclose(cleanup); 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_pre_disconn) (VSTREAM *, char *, char **);
static void (*event_server_slow_exit) (char *, char **); static void (*event_server_slow_exit) (char *, char **);
static int event_server_watchdog = 1000; static int event_server_watchdog = 1000;
static int event_server_saved_flags;
/* event_server_exit - normal termination */ /* event_server_exit - normal termination */
@ -373,8 +372,7 @@ void event_server_disconnect(VSTREAM *stream)
static void event_server_execute(int unused_event, void *context) static void event_server_execute(int unused_event, void *context)
{ {
VSTREAM *stream = (VSTREAM *) context; VSTREAM *stream = (VSTREAM *) context;
HTABLE *attr = (vstream_flags(stream) == event_server_saved_flags ? HTABLE *attr = (HTABLE *) vstream_context(stream);
(HTABLE *) vstream_context(stream) : 0);
if (event_server_lock != 0 if (event_server_lock != 0
&& myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK, && myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK,
@ -432,7 +430,6 @@ static void event_server_wakeup(int fd, HTABLE *attr)
CA_VSTREAM_CTL_END); CA_VSTREAM_CTL_END);
myfree(tmp); myfree(tmp);
timed_ipc_setup(stream); timed_ipc_setup(stream);
event_server_saved_flags = vstream_flags(stream);
if (event_server_in_flow_delay && mail_flow_get(1) < 0) if (event_server_in_flow_delay && mail_flow_get(1) < 0)
event_request_timer(event_server_execute, (void *) stream, event_request_timer(event_server_execute, (void *) stream,
var_in_flow_delay); var_in_flow_delay);

View File

@ -12,6 +12,7 @@
* Utility library. * Utility library.
*/ */
#include <vstream.h> #include <vstream.h>
#include <htable.h>
/* /*
* Global library. * Global library.
@ -45,11 +46,13 @@
#define MAIL_SERVER_SLOW_EXIT 21 #define MAIL_SERVER_SLOW_EXIT 21
#define MAIL_SERVER_BOUNCE_INIT 22 #define MAIL_SERVER_BOUNCE_INIT 22
#define MAIL_SERVER_RETIRE_ME 23 #define MAIL_SERVER_RETIRE_ME 23
#define MAIL_SERVER_POST_ACCEPT 24
typedef void (*MAIL_SERVER_INIT_FN) (char *, char **); typedef void (*MAIL_SERVER_INIT_FN) (char *, char **);
typedef int (*MAIL_SERVER_LOOP_FN) (char *, char **); typedef int (*MAIL_SERVER_LOOP_FN) (char *, char **);
typedef void (*MAIL_SERVER_EXIT_FN) (char *, char **); typedef void (*MAIL_SERVER_EXIT_FN) (char *, char **);
typedef void (*MAIL_SERVER_ACCEPT_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_DISCONN_FN) (VSTREAM *, char *, char **);
typedef void (*MAIL_SERVER_SLOW_EXIT_FN) (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_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_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_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_SOLITARY MAIL_SERVER_SOLITARY
#define CA_MAIL_SERVER_UNLIMITED MAIL_SERVER_UNLIMITED #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)) #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_EXIT_FN);
CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_DISCONN_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_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, int);
CHECK_PTR_HELPER_DCL(MAIL_SERVER, char); CHECK_PTR_HELPER_DCL(MAIL_SERVER, char);
CHECK_PPTR_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 /* function is run after the program has optionally dropped its
/* privileges. This function should not attempt to preserve state /* privileges. This function should not attempt to preserve state
/* across calls. The stream initial state is non-blocking mode. /* across calls. The stream initial state is non-blocking mode.
/* Optional connection attributes are provided as a hash that
/* is attached as stream context. NOTE: the attributes are
/* destroyed after this function is called.
/* The service name argument corresponds to the service name in the /* The service name argument corresponds to the service name in the
/* master.cf file. /* master.cf file.
/* The argv argument specifies command-line arguments left over /* The argv argument specifies command-line arguments left over
@ -114,6 +111,14 @@
/* Function to be executed prior to accepting a new connection. /* Function to be executed prior to accepting a new connection.
/* .sp /* .sp
/* Only the last instance of this parameter type is remembered. /* 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)" /* .IP "CA_MAIL_SERVER_PRE_DISCONN(VSTREAM *, char *service_name, char **argv)"
/* A pointer to a function that is called /* A pointer to a function that is called
/* by the multi_server_disconnect() function (see below). /* 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_accept) (int, void *);
static void (*multi_server_onexit) (char *, char **); static void (*multi_server_onexit) (char *, char **);
static void (*multi_server_pre_accept) (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 VSTREAM *multi_server_lock;
static int multi_server_in_flow_delay; static int multi_server_in_flow_delay;
static unsigned multi_server_generation; static unsigned multi_server_generation;
static void (*multi_server_pre_disconn) (VSTREAM *, char *, char **); static void (*multi_server_pre_disconn) (VSTREAM *, char *, char **);
static int multi_server_saved_flags;
/* multi_server_exit - normal termination */ /* multi_server_exit - normal termination */
@ -336,8 +341,6 @@ void multi_server_disconnect(VSTREAM *stream)
static void multi_server_execute(int unused_event, void *context) static void multi_server_execute(int unused_event, void *context)
{ {
VSTREAM *stream = (VSTREAM *) context; VSTREAM *stream = (VSTREAM *) context;
HTABLE *attr = (vstream_flags(stream) == multi_server_saved_flags ?
(HTABLE *) vstream_context(stream) : 0);
if (multi_server_lock != 0 if (multi_server_lock != 0
&& myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK, && myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
@ -358,8 +361,6 @@ static void multi_server_execute(int unused_event, void *context)
} else { } else {
multi_server_disconnect(stream); multi_server_disconnect(stream);
} }
if (attr)
htable_free(attr, myfree);
} }
/* multi_server_enable_read - enable read events */ /* multi_server_enable_read - enable read events */
@ -404,16 +405,20 @@ static void multi_server_wakeup(int fd, HTABLE *attr)
tmp = concatenate(multi_server_name, " socket", (char *) 0); tmp = concatenate(multi_server_name, " socket", (char *) 0);
vstream_control(stream, vstream_control(stream,
CA_VSTREAM_CTL_PATH(tmp), CA_VSTREAM_CTL_PATH(tmp),
CA_VSTREAM_CTL_CONTEXT((void *) attr),
CA_VSTREAM_CTL_END); CA_VSTREAM_CTL_END);
myfree(tmp); myfree(tmp);
timed_ipc_setup(stream); timed_ipc_setup(stream);
multi_server_saved_flags = vstream_flags(stream);
if (multi_server_in_flow_delay && mail_flow_get(1) < 0) if (multi_server_in_flow_delay && mail_flow_get(1) < 0)
event_request_timer(multi_server_enable_read, (void *) stream, event_request_timer(multi_server_enable_read, (void *) stream,
var_in_flow_delay); var_in_flow_delay);
else else
multi_server_enable_read(0, (void *) stream); 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 */ /* 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: case MAIL_SERVER_PRE_ACCEPT:
multi_server_pre_accept = va_arg(ap, MAIL_SERVER_ACCEPT_FN); multi_server_pre_accept = va_arg(ap, MAIL_SERVER_ACCEPT_FN);
break; break;
case MAIL_SERVER_POST_ACCEPT:
multi_server_post_accept = va_arg(ap, MAIL_SERVER_POST_ACCEPT_FN);
break;
case MAIL_SERVER_PRE_DISCONN: case MAIL_SERVER_PRE_DISCONN:
multi_server_pre_disconn = va_arg(ap, MAIL_SERVER_DISCONN_FN); multi_server_pre_disconn = va_arg(ap, MAIL_SERVER_DISCONN_FN);
break; break;

View File

@ -109,12 +109,12 @@ static int qmgr_deliver_initial_reply(VSTREAM *stream)
msg_warn("%s: premature disconnect", VSTREAM_PATH(stream)); msg_warn("%s: premature disconnect", VSTREAM_PATH(stream));
return (DELIVER_STAT_CRASH); return (DELIVER_STAT_CRASH);
} else if (attr_scan(stream, ATTR_FLAG_STRICT, } else if (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &stat), RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_DELIVER),
ATTR_TYPE_END) != 1) { ATTR_TYPE_END) != 0) {
msg_warn("%s: malformed response", VSTREAM_PATH(stream)); msg_warn("%s: malformed response", VSTREAM_PATH(stream));
return (DELIVER_STAT_CRASH); return (DELIVER_STAT_DEFER);
} else { } 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); cleanup = mail_connect_wait(MAIL_CLASS_PUBLIC, var_cleanup_service);
if (attr_scan(cleanup, ATTR_FLAG_STRICT, if (attr_scan(cleanup, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP),
RECV_ATTR_STR(MAIL_ATTR_QUEUEID, buf), RECV_ATTR_STR(MAIL_ATTR_QUEUEID, buf),
ATTR_TYPE_END) != 1 ATTR_TYPE_END) != 1
|| attr_print(cleanup, ATTR_FLAG_NONE, || 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 postconf_lookup.o postconf_match.o postconf_print.o
HDRS = postconf.h HDRS = postconf.h
TESTSRC = TESTSRC =
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE) DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE) -DLEGACY_DBMS_SUPPORT
CFLAGS = $(DEBUG) $(OPT) $(DEFS) -DLEGACY_DBMS_SUPPORT CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG= TESTPROG=
MAKES = bool_table.h bool_vars.h int_table.h int_vars.h str_table.h \ 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 \ 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, dst = mail_stream_file(MAIL_QUEUE_MAILDROP, MAIL_CLASS_PUBLIC,
var_pickup_service, 0444); var_pickup_service, 0444);
attr_print(VSTREAM_OUT, ATTR_FLAG_NONE, 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), SEND_ATTR_STR(MAIL_ATTR_QUEUEID, dst->id),
ATTR_TYPE_END); ATTR_TYPE_END);
vstream_fflush(VSTREAM_OUT); vstream_fflush(VSTREAM_OUT);

View File

@ -61,14 +61,19 @@ depend: $(MAKES)
# do not edit below this line - it is generated by 'make depend' # do not edit below this line - it is generated by 'make depend'
postlogd.o: ../../include/check_arg.h postlogd.o: ../../include/check_arg.h
postlogd.o: ../../include/htable.h
postlogd.o: ../../include/logwriter.h postlogd.o: ../../include/logwriter.h
postlogd.o: ../../include/mail_conf.h postlogd.o: ../../include/mail_conf.h
postlogd.o: ../../include/mail_params.h postlogd.o: ../../include/mail_params.h
postlogd.o: ../../include/mail_server.h postlogd.o: ../../include/mail_server.h
postlogd.o: ../../include/mail_task.h
postlogd.o: ../../include/mail_version.h postlogd.o: ../../include/mail_version.h
postlogd.o: ../../include/maillog_client.h
postlogd.o: ../../include/msg.h postlogd.o: ../../include/msg.h
postlogd.o: ../../include/msg_logger.h postlogd.o: ../../include/msg_logger.h
postlogd.o: ../../include/stringops.h
postlogd.o: ../../include/sys_defs.h postlogd.o: ../../include/sys_defs.h
postlogd.o: ../../include/vbuf.h postlogd.o: ../../include/vbuf.h
postlogd.o: ../../include/vstream.h postlogd.o: ../../include/vstream.h
postlogd.o: ../../include/vstring.h
postlogd.o: postlogd.c 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, 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 */ /* show_queue - show queue status */
static void show_queue(int mode) static void show_queue(int mode)
@ -361,16 +381,7 @@ static void show_queue(int mode)
* Connect to the show queue service. * Connect to the show queue service.
*/ */
if ((showq = mail_connect(MAIL_CLASS_PUBLIC, var_showq_service, BLOCKING)) != 0) { if ((showq = mail_connect(MAIL_CLASS_PUBLIC, var_showq_service, BLOCKING)) != 0) {
switch (mode) { showq_client(mode, showq);
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);
}
if (vstream_fclose(showq)) if (vstream_fclose(showq))
msg_warn("close: %m"); msg_warn("close: %m");
} }
@ -407,23 +418,14 @@ static void show_queue(int mode)
CA_VSTREAM_POPEN_END)) == 0) { CA_VSTREAM_POPEN_END)) == 0) {
stat = -1; stat = -1;
} else { } else {
switch (mode) { showq_client(mode, showq);
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);
}
stat = vstream_pclose(showq); stat = vstream_pclose(showq);
} }
argv_free(argv); argv_free(argv);
myfree(showq_path);
if (stat != 0) if (stat != 0)
msg_fatal_status(stat < 0 ? EX_OSERR : EX_SOFTWARE, msg_fatal_status(stat < 0 ? EX_OSERR : EX_SOFTWARE,
"Error running %s", showq_path); "Error running %s", showq_path);
myfree(showq_path);
} }
/* /*

View File

@ -88,6 +88,22 @@ typedef struct {
static char *psc_tlsp_service = 0; 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 */ /* psc_starttls_finish - complete negotiation with TLS proxy */
static void psc_starttls_finish(int event, void *context) 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 * The TLS proxy reports that the TLS engine is not available (due to
* configuration error, or other causes). * configuration error, or other causes).
*/ */
event_disable_readwrite(vstream_fileno(tlsproxy_stream)); msg_warn("%s receiving status from %s service",
vstream_fclose(tlsproxy_stream); event == EVENT_TIME ? "timeout" : "problem", psc_tlsp_service);
PSC_SEND_REPLY(smtp_state, PSC_SEND_REPLY(smtp_state,
"454 4.7.0 TLS not available due to local problem\r\n"); "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. * Some error: drop the TLS proxy stream.
*/ */
msg_warn("%s sending file handle to %s service", msg_warn("problem sending file handle to %s service", psc_tlsp_service);
event == EVENT_TIME ? "timeout" : "problem",
psc_tlsp_service);
event_disable_readwrite(vstream_fileno(tlsproxy_stream));
vstream_fclose(tlsproxy_stream);
PSC_SEND_REPLY(smtp_state, PSC_SEND_REPLY(smtp_state,
"454 4.7.0 TLS not available due to local problem\r\n"); "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"); 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 * Swap the SMTP client stream and the TLS proxy stream, and close
* TLS handshake is done, the TLS proxy will deliver plaintext SMTP * the direct connection to the SMTP client. The TLS proxy will talk
* commands to postscreen(8). * 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 * Swap the file descriptors from under the VSTREAM so that we don't
* have to worry about loss of user-configurable VSTREAM attributes. * 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, vstream_control(smtp_state->smtp_client_stream,
CA_VSTREAM_CTL_SWAP_FD(tlsproxy_stream), CA_VSTREAM_CTL_SWAP_FD(tlsproxy_stream),
CA_VSTREAM_CTL_END); CA_VSTREAM_CTL_END);
vstream_fclose(tlsproxy_stream); /* direct-to-client stream! */
smtp_state->flags |= PSC_STATE_FLAG_USING_TLS; 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); if (remote_endpt == 0)
myfree((void *) starttls_state); 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 */ /* 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; PSC_STARTTLS *starttls_state;
VSTREAM *tlsproxy_stream; VSTREAM *tlsproxy_stream;
int fd; int fd;
static VSTRING *remote_endpt = 0;
if (psc_tlsp_service == 0) { if (psc_tlsp_service == 0) {
psc_tlsp_service = concatenate(MAIL_CLASS_PRIVATE "/", psc_tlsp_service = concatenate(MAIL_CLASS_PRIVATE "/",
var_tlsproxy_service, (char *) 0); 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; return;
} }
if (msg_verbose) 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", " for smtp socket %d from [%s]:%s flags=%s",
myname, fd, vstream_fileno(smtp_state->smtp_client_stream), myname, fd, vstream_fileno(smtp_state->smtp_client_stream),
smtp_state->smtp_client_addr, smtp_state->smtp_client_port, smtp_state->smtp_client_addr, smtp_state->smtp_client_port,
psc_print_state_flags(smtp_state->flags, myname)); 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); tlsproxy_stream = vstream_fdopen(fd, O_RDWR);
vstring_sprintf(remote_endpt, "[%s]:%s", smtp_state->smtp_client_addr, vstream_control(tlsproxy_stream,
smtp_state->smtp_client_port); VSTREAM_CTL_PATH, psc_tlsp_service,
attr_print(tlsproxy_stream, ATTR_FLAG_NONE, VSTREAM_CTL_END);
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;
}
/* /*
* Set up a read event for the next phase of the TLS proxy handshake. * 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->tlsproxy_stream = tlsproxy_stream;
starttls_state->resume_event = resume_event; starttls_state->resume_event = resume_event;
starttls_state->smtp_state = smtp_state; 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); (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; MAIL_VERSION_STAMP_DECLARE;
/* main - pass control to the multi-threaded skeleton */ /* 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_STR_TABLE(str_table),
CA_MAIL_SERVER_POST_INIT(post_jail_init), CA_MAIL_SERVER_POST_INIT(post_jail_init),
CA_MAIL_SERVER_PRE_ACCEPT(pre_accept), CA_MAIL_SERVER_PRE_ACCEPT(pre_accept),
CA_MAIL_SERVER_POST_ACCEPT(post_accept),
/* XXX CA_MAIL_SERVER_SOLITARY if proxywrite */ /* XXX CA_MAIL_SERVER_SOLITARY if proxywrite */
0); 0);
} }

View File

@ -108,18 +108,16 @@ int qmgr_deliver_concurrency;
static int qmgr_deliver_initial_reply(VSTREAM *stream) static int qmgr_deliver_initial_reply(VSTREAM *stream)
{ {
int stat;
if (peekfd(vstream_fileno(stream)) < 0) { if (peekfd(vstream_fileno(stream)) < 0) {
msg_warn("%s: premature disconnect", VSTREAM_PATH(stream)); msg_warn("%s: premature disconnect", VSTREAM_PATH(stream));
return (DELIVER_STAT_CRASH); return (DELIVER_STAT_CRASH);
} else if (attr_scan(stream, ATTR_FLAG_STRICT, } else if (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &stat), RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_DELIVER),
ATTR_TYPE_END) != 1) { ATTR_TYPE_END) != 0) {
msg_warn("%s: malformed response", VSTREAM_PATH(stream)); msg_warn("%s: malformed response", VSTREAM_PATH(stream));
return (DELIVER_STAT_CRASH); return (DELIVER_STAT_DEFER);
} else { } 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_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; MAIL_VERSION_STAMP_DECLARE;
/* main - pass control to the multi-threaded skeleton */ /* 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, multi_server_main(argc, argv, scache_service,
CA_MAIL_SERVER_TIME_TABLE(time_table), CA_MAIL_SERVER_TIME_TABLE(time_table),
CA_MAIL_SERVER_POST_INIT(post_jail_init), 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_EXIT(scache_status_dump),
CA_MAIL_SERVER_SOLITARY, CA_MAIL_SERVER_SOLITARY,
0); 0);

View File

@ -360,6 +360,13 @@ static void showq_service(VSTREAM *client, char *unused_service, char **argv)
if (argv[0]) if (argv[0])
msg_fatal("unexpected command-line argument: %s", 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 * 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 * 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_proto.h
smtpd_chat.o: ../../include/mail_stream.h smtpd_chat.o: ../../include/mail_stream.h
smtpd_chat.o: ../../include/maps.h smtpd_chat.o: ../../include/maps.h
smtpd_chat.o: ../../include/match_list.h
smtpd_chat.o: ../../include/milter.h smtpd_chat.o: ../../include/milter.h
smtpd_chat.o: ../../include/msg.h smtpd_chat.o: ../../include/msg.h
smtpd_chat.o: ../../include/myaddrinfo.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/smtp_stream.h
smtpd_chat.o: ../../include/smtputf8.h smtpd_chat.o: ../../include/smtputf8.h
smtpd_chat.o: ../../include/sock_addr.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/stringops.h
smtpd_chat.o: ../../include/sys_defs.h smtpd_chat.o: ../../include/sys_defs.h
smtpd_chat.o: ../../include/tls.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_params.h
smtpd_expand.o: ../../include/mail_proto.h smtpd_expand.o: ../../include/mail_proto.h
smtpd_expand.o: ../../include/mail_stream.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/milter.h
smtpd_expand.o: ../../include/msg.h smtpd_expand.o: ../../include/msg.h
smtpd_expand.o: ../../include/myaddrinfo.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/name_mask.h
smtpd_expand.o: ../../include/nvtable.h smtpd_expand.o: ../../include/nvtable.h
smtpd_expand.o: ../../include/sock_addr.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/stringops.h
smtpd_expand.o: ../../include/sys_defs.h smtpd_expand.o: ../../include/sys_defs.h
smtpd_expand.o: ../../include/tls.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/iostuff.h
smtpd_haproxy.o: ../../include/mail_params.h smtpd_haproxy.o: ../../include/mail_params.h
smtpd_haproxy.o: ../../include/mail_stream.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/milter.h
smtpd_haproxy.o: ../../include/msg.h smtpd_haproxy.o: ../../include/msg.h
smtpd_haproxy.o: ../../include/myaddrinfo.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/nvtable.h
smtpd_haproxy.o: ../../include/smtp_stream.h smtpd_haproxy.o: ../../include/smtp_stream.h
smtpd_haproxy.o: ../../include/sock_addr.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/stringops.h
smtpd_haproxy.o: ../../include/sys_defs.h smtpd_haproxy.o: ../../include/sys_defs.h
smtpd_haproxy.o: ../../include/tls.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/htable.h
smtpd_milter.o: ../../include/mail_params.h smtpd_milter.o: ../../include/mail_params.h
smtpd_milter.o: ../../include/mail_stream.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/milter.h
smtpd_milter.o: ../../include/myaddrinfo.h smtpd_milter.o: ../../include/myaddrinfo.h
smtpd_milter.o: ../../include/mymalloc.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/resolve_clnt.h
smtpd_milter.o: ../../include/sock_addr.h smtpd_milter.o: ../../include/sock_addr.h
smtpd_milter.o: ../../include/split_at.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/stringops.h
smtpd_milter.o: ../../include/sys_defs.h smtpd_milter.o: ../../include/sys_defs.h
smtpd_milter.o: ../../include/tls.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_params.h
smtpd_peer.o: ../../include/mail_proto.h smtpd_peer.o: ../../include/mail_proto.h
smtpd_peer.o: ../../include/mail_stream.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/milter.h
smtpd_peer.o: ../../include/msg.h smtpd_peer.o: ../../include/msg.h
smtpd_peer.o: ../../include/myaddrinfo.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/nvtable.h
smtpd_peer.o: ../../include/sock_addr.h smtpd_peer.o: ../../include/sock_addr.h
smtpd_peer.o: ../../include/split_at.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/stringops.h
smtpd_peer.o: ../../include/sys_defs.h smtpd_peer.o: ../../include/sys_defs.h
smtpd_peer.o: ../../include/tls.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_proto.h
smtpd_proxy.o: ../../include/mail_queue.h smtpd_proxy.o: ../../include/mail_queue.h
smtpd_proxy.o: ../../include/mail_stream.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/milter.h
smtpd_proxy.o: ../../include/msg.h smtpd_proxy.o: ../../include/msg.h
smtpd_proxy.o: ../../include/myaddrinfo.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/record.h
smtpd_proxy.o: ../../include/smtp_stream.h smtpd_proxy.o: ../../include/smtp_stream.h
smtpd_proxy.o: ../../include/sock_addr.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/stringops.h
smtpd_proxy.o: ../../include/sys_defs.h smtpd_proxy.o: ../../include/sys_defs.h
smtpd_proxy.o: ../../include/tls.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_params.h
smtpd_sasl_proto.o: ../../include/mail_proto.h smtpd_sasl_proto.o: ../../include/mail_proto.h
smtpd_sasl_proto.o: ../../include/mail_stream.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/milter.h
smtpd_sasl_proto.o: ../../include/msg.h smtpd_sasl_proto.o: ../../include/msg.h
smtpd_sasl_proto.o: ../../include/myaddrinfo.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/name_mask.h
smtpd_sasl_proto.o: ../../include/nvtable.h smtpd_sasl_proto.o: ../../include/nvtable.h
smtpd_sasl_proto.o: ../../include/sock_addr.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/stringops.h
smtpd_sasl_proto.o: ../../include/sys_defs.h smtpd_sasl_proto.o: ../../include/sys_defs.h
smtpd_sasl_proto.o: ../../include/tls.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_params.h
smtpd_state.o: ../../include/mail_proto.h smtpd_state.o: ../../include/mail_proto.h
smtpd_state.o: ../../include/mail_stream.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/milter.h
smtpd_state.o: ../../include/msg.h smtpd_state.o: ../../include/msg.h
smtpd_state.o: ../../include/myaddrinfo.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/name_mask.h
smtpd_state.o: ../../include/nvtable.h smtpd_state.o: ../../include/nvtable.h
smtpd_state.o: ../../include/sock_addr.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/sys_defs.h
smtpd_state.o: ../../include/tls.h smtpd_state.o: ../../include/tls.h
smtpd_state.o: ../../include/vbuf.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/iostuff.h
smtpd_xforward.o: ../../include/mail_proto.h smtpd_xforward.o: ../../include/mail_proto.h
smtpd_xforward.o: ../../include/mail_stream.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/milter.h
smtpd_xforward.o: ../../include/msg.h smtpd_xforward.o: ../../include/msg.h
smtpd_xforward.o: ../../include/myaddrinfo.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/name_mask.h
smtpd_xforward.o: ../../include/nvtable.h smtpd_xforward.o: ../../include/nvtable.h
smtpd_xforward.o: ../../include/sock_addr.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/sys_defs.h
smtpd_xforward.o: ../../include/tls.h smtpd_xforward.o: ../../include/tls.h
smtpd_xforward.o: ../../include/vbuf.h smtpd_xforward.o: ../../include/vbuf.h

View File

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

View File

@ -107,6 +107,11 @@
/* IBM T.J. Watson Research /* IBM T.J. Watson Research
/* P.O. Box 704 /* P.O. Box 704
/* Yorktown Heights, NY 10598, USA /* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/ /*--*/
/* System library. */ /* System library. */
@ -144,6 +149,15 @@
static ATTR_CLNT *tls_mgr; 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 */ /* tls_mgr_open - create client handle */
static void tls_mgr_open(void) static void tls_mgr_open(void)
@ -168,6 +182,7 @@ static void tls_mgr_open(void)
attr_clnt_control(tls_mgr, attr_clnt_control(tls_mgr,
ATTR_CLNT_CTL_PROTO, attr_vprint, attr_vscan, ATTR_CLNT_CTL_PROTO, attr_vprint, attr_vscan,
ATTR_CLNT_CTL_HANDSHAKE, tls_mgr_handshake,
ATTR_CLNT_CTL_END); 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. * remote peer file descriptor in a later transaction.
*/ */
tlsproxy_stream = vstream_fdopen(fd, O_RDWR); 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); vstring_sprintf(remote_endpt, "[%s]:%s", peer_addr, peer_port);
attr_print(tlsproxy_stream, ATTR_FLAG_NONE, attr_print(tlsproxy_stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(TLS_ATTR_REMOTE_ENDPT, STR(remote_endpt)), 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_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 */ /* tlsmgr_before_exit - save PRNG state before exit */
static void tlsmgr_before_exit(char *unused_service_name, char **unused_argv) 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_STR_TABLE(str_table),
CA_MAIL_SERVER_PRE_INIT(tlsmgr_pre_init), CA_MAIL_SERVER_PRE_INIT(tlsmgr_pre_init),
CA_MAIL_SERVER_POST_INIT(tlsmgr_post_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_EXIT(tlsmgr_before_exit),
CA_MAIL_SERVER_LOOP(tlsmgr_loop), CA_MAIL_SERVER_LOOP(tlsmgr_loop),
CA_MAIL_SERVER_SOLITARY, 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_TIMEOUT(5),
CA_VSTREAM_CTL_END); 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. * Receive postscreen's remote SMTP client address/port and socket.
*/ */

View File

@ -153,7 +153,7 @@
/* matches subdomains of example.com, /* matches subdomains of example.com,
/* instead of requiring an explicit ".example.com" pattern. /* instead of requiring an explicit ".example.com" pattern.
/* .IP "\fBrelayhost (empty)\fR" /* .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. /* domains in recipient addresses.
/* .IP "\fBtransport_maps (empty)\fR" /* .IP "\fBtransport_maps (empty)\fR"
/* Optional lookup tables with mappings from recipient address to /* Optional lookup tables with mappings from recipient address to
@ -522,6 +522,21 @@ static void pre_accept(char *unused_name, char **unused_argv)
#endif #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) static void check_table_stats(int unused_event, void *unused_context)
{ {
const char *table; const char *table;
@ -648,5 +663,6 @@ int main(int argc, char **argv)
#ifdef CHECK_TABLE_STATS_BEFORE_ACCEPT #ifdef CHECK_TABLE_STATS_BEFORE_ACCEPT
CA_MAIL_SERVER_PRE_ACCEPT(pre_accept), CA_MAIL_SERVER_PRE_ACCEPT(pre_accept),
#endif #endif
CA_MAIL_SERVER_POST_ACCEPT(post_accept),
0); 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 \ 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 \ 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 \ 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 \ readlline.c ring.c safe_getenv.c safe_open.c \
sane_accept.c sane_connect.c sane_link.c sane_rename.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 \ 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 \ 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 \ 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 \ 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 \ readlline.o ring.o safe_getenv.o safe_open.o \
sane_accept.o sane_connect.o sane_link.o sane_rename.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 \ 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 \ 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 \ 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 \ 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 \ safe.h safe_open.h sane_accept.h sane_connect.h sane_fsops.h \
load_lib.h \ load_lib.h \
sane_socketpair.h sane_time.h scan_dir.h set_eugid.h set_ugid.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: vstream.h
load_file.o: warn_stat.h load_file.o: warn_stat.h
load_lib.o: load_lib.c load_lib.o: load_lib.c
load_lib.o: load_lib.h
load_lib.o: msg.h
load_lib.o: sys_defs.h load_lib.o: sys_defs.h
logwriter.o: check_arg.h logwriter.o: check_arg.h
logwriter.o: iostuff.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_output.h
msg_output.o: msg_vstream.h msg_output.o: msg_vstream.h
msg_output.o: mymalloc.h msg_output.o: mymalloc.h
msg_output.o: percentm.h
msg_output.o: stringops.h msg_output.o: stringops.h
msg_output.o: sys_defs.h msg_output.o: sys_defs.h
msg_output.o: vbuf.h msg_output.o: vbuf.h
@ -2220,12 +2221,6 @@ pass_trigger.o: trigger.h
peekfd.o: iostuff.h peekfd.o: iostuff.h
peekfd.o: peekfd.c peekfd.o: peekfd.c
peekfd.o: sys_defs.h peekfd.o: sys_defs.h
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: iostuff.h
poll_fd.o: msg.h poll_fd.o: msg.h
poll_fd.o: poll_fd.c 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_LONG 4 /* Unsigned long */
#define ATTR_TYPE_DATA 5 /* Binary data */ #define ATTR_TYPE_DATA 5 /* Binary data */
#define ATTR_TYPE_FUNC 6 /* Function pointer */ #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. * 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_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_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_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_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)) #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_PRINT_FN) (VSTREAM *, int, va_list);
/* typedef int (*ATTR_CLNT_SCAN_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) /* ATTR_CLNT *attr_clnt_create(server, timeout, max_idle, max_ttl)
/* const char *server; /* const char *server;
@ -65,6 +66,9 @@
/* .IP "ATTR_CLNT_CTL_TRY_DELAY(int)" /* .IP "ATTR_CLNT_CTL_TRY_DELAY(int)"
/* The time in seconds between attempts to send a request /* The time in seconds between attempts to send a request
/* (default: 1). Specify a value greater than zero. /* (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 /* DIAGNOSTICS
/* Warnings: communication failure. /* Warnings: communication failure.
/* SEE ALSO /* SEE ALSO
@ -80,6 +84,11 @@
/* IBM T.J. Watson Research /* IBM T.J. Watson Research
/* P.O. Box 704 /* P.O. Box 704
/* Yorktown Heights, NY 10598, USA /* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/ /*--*/
/* System library. */ /* 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->print = va_arg(ap, ATTR_CLNT_PRINT_FN);
client->scan = va_arg(ap, ATTR_CLNT_SCAN_FN); client->scan = va_arg(ap, ATTR_CLNT_SCAN_FN);
break; 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: case ATTR_CLNT_CTL_REQ_LIMIT:
client->req_limit = va_arg(ap, int); client->req_limit = va_arg(ap, int);
if (client->req_limit < 0) if (client->req_limit < 0)

View File

@ -27,6 +27,7 @@
typedef struct ATTR_CLNT ATTR_CLNT; typedef struct ATTR_CLNT ATTR_CLNT;
typedef int (*ATTR_CLNT_PRINT_FN) (VSTREAM *, int, va_list); typedef int (*ATTR_CLNT_PRINT_FN) (VSTREAM *, int, va_list);
typedef int (*ATTR_CLNT_SCAN_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 ATTR_CLNT *attr_clnt_create(const char *, int, int, int);
extern int attr_clnt_request(ATTR_CLNT *, 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_REQ_LIMIT 2 /* requests per connection */
#define ATTR_CLNT_CTL_TRY_LIMIT 3 /* attempts per request */ #define ATTR_CLNT_CTL_TRY_LIMIT 3 /* attempts per request */
#define ATTR_CLNT_CTL_TRY_DELAY 4 /* pause between requests */ #define ATTR_CLNT_CTL_TRY_DELAY 4 /* pause between requests */
#define ATTR_CLNT_CTL_HANDSHAKE 5 /* handshake before first request */
/* LICENSE /* LICENSE
/* .ad /* .ad
@ -48,6 +50,11 @@ extern void attr_clnt_control(ATTR_CLNT *, int,...);
/* IBM T.J. Watson Research /* IBM T.J. Watson Research
/* P.O. Box 704 /* P.O. Box 704
/* Yorktown Heights, NY 10598, USA /* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/ /*--*/
#endif #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, "foo-name", mystrdup("foo-value"));
htable_enter(table, "bar-name", mystrdup("bar-value")); htable_enter(table, "bar-name", mystrdup("bar-value"));
attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE, attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "test"),
SEND_ATTR_INT(ATTR_NAME_INT, 4711), SEND_ATTR_INT(ATTR_NAME_INT, 4711),
SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L), SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"), 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), SEND_ATTR_LONG(ATTR_NAME_LONG, 4321L),
ATTR_TYPE_END); ATTR_TYPE_END);
attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE, attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "test"),
SEND_ATTR_INT(ATTR_NAME_INT, 4711), SEND_ATTR_INT(ATTR_NAME_INT, 4711),
SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L), SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"), SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
SEND_ATTR_DATA(ATTR_NAME_DATA, strlen("whoopee"), "whoopee"), SEND_ATTR_DATA(ATTR_NAME_DATA, strlen("whoopee"), "whoopee"),
ATTR_TYPE_END); 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) if (vstream_fflush(VSTREAM_OUT) != 0)
msg_fatal("write error: %m"); 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, "foo-name", mystrdup("foo-value"));
htable_enter(table, "bar-name", mystrdup("bar-value")); htable_enter(table, "bar-name", mystrdup("bar-value"));
attr_print64(VSTREAM_OUT, ATTR_FLAG_NONE, attr_print64(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "test"),
SEND_ATTR_INT(ATTR_NAME_INT, 4711), SEND_ATTR_INT(ATTR_NAME_INT, 4711),
SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L), SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"), 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), SEND_ATTR_LONG(ATTR_NAME_LONG, 4321L),
ATTR_TYPE_END); ATTR_TYPE_END);
attr_print64(VSTREAM_OUT, ATTR_FLAG_NONE, attr_print64(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "test"),
SEND_ATTR_INT(ATTR_NAME_INT, 4711), SEND_ATTR_INT(ATTR_NAME_INT, 4711),
SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L), SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"), SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
SEND_ATTR_DATA(ATTR_NAME_DATA, strlen("whoopee"), "whoopee"), SEND_ATTR_DATA(ATTR_NAME_DATA, strlen("whoopee"), "whoopee"),
ATTR_TYPE_END); 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) if (vstream_fflush(VSTREAM_OUT) != 0)
msg_fatal("write error: %m"); 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, "foo-name", mystrdup("foo-value"));
htable_enter(table, "bar-name", mystrdup("bar-value")); htable_enter(table, "bar-name", mystrdup("bar-value"));
attr_print_plain(VSTREAM_OUT, ATTR_FLAG_NONE, attr_print_plain(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "test"),
SEND_ATTR_INT(ATTR_NAME_INT, 4711), SEND_ATTR_INT(ATTR_NAME_INT, 4711),
SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L), SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"), 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), SEND_ATTR_LONG(ATTR_NAME_LONG, 4321L),
ATTR_TYPE_END); ATTR_TYPE_END);
attr_print_plain(VSTREAM_OUT, ATTR_FLAG_NONE, attr_print_plain(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "test"),
SEND_ATTR_INT(ATTR_NAME_INT, 4711), SEND_ATTR_INT(ATTR_NAME_INT, 4711),
SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L), SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"), SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
SEND_ATTR_DATA(ATTR_NAME_DATA, strlen("whoopee"), "whoopee"), SEND_ATTR_DATA(ATTR_NAME_DATA, strlen("whoopee"), "whoopee"),
ATTR_TYPE_END); 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) if (vstream_fflush(VSTREAM_OUT) != 0)
msg_fatal("write error: %m"); msg_fatal("write error: %m");

View File

@ -100,6 +100,9 @@
/* This argument is followed by an attribute name and a long pointer. /* This argument is followed by an attribute name and a long pointer.
/* .IP "RECV_ATTR_STR(const char *name, VSTRING *vp)" /* .IP "RECV_ATTR_STR(const char *name, VSTRING *vp)"
/* This argument is followed by an attribute name and a VSTRING pointer. /* 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)" /* .IP "RECV_ATTR_DATA(const char *name, VSTRING *vp)"
/* This argument is followed by an attribute name and a VSTRING pointer. /* This argument is followed by an attribute name and a VSTRING pointer.
/* .IP "RECV_ATTR_FUNC(ATTR_SCAN_CUSTOM_FN, void *data)" /* .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; int conversions;
ATTR_SCAN_CUSTOM_FN scan_fn; ATTR_SCAN_CUSTOM_FN scan_fn;
void *scan_arg; void *scan_arg;
const char *expect_val;
/* /*
* Sanity check. * 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) if (scan_fn(attr_scan0, fp, flags | ATTR_FLAG_MORE, scan_arg) < 0)
return (-1); return (-1);
break; 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_HASH:
case ATTR_TYPE_CLOSE: case ATTR_TYPE_CLOSE:
if ((ch = attr_scan0_string(fp, str_buf, 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); msg_vstream_init(used_argv[0], VSTREAM_ERR);
if ((ret = attr_scan0(VSTREAM_IN, if ((ret = attr_scan0(VSTREAM_IN,
ATTR_FLAG_STRICT, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
RECV_ATTR_INT(ATTR_NAME_INT, &int_val), RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val), RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
RECV_ATTR_STR(ATTR_NAME_STR, str_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, if ((ret = attr_scan0(VSTREAM_IN,
ATTR_FLAG_STRICT, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
RECV_ATTR_INT(ATTR_NAME_INT, &int_val), RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val), RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
RECV_ATTR_STR(ATTR_NAME_STR, str_val), RECV_ATTR_STR(ATTR_NAME_STR, str_val),
@ -550,6 +569,11 @@ int main(int unused_argc, char **used_argv)
} else { } else {
vstream_printf("return: %d\n", ret); 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) if (vstream_fflush(VSTREAM_OUT) != 0)
msg_fatal("write error: %m"); 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 number = 4711
./attr_print0: send attr long_number = 1234 ./attr_print0: send attr long_number = 1234
./attr_print0: send attr string = whoopee ./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 foo-name value foo-value
./attr_print0: send attr name bar-name value bar-value ./attr_print0: send attr name bar-name value bar-value
./attr_print0: send attr long_number = 4321 ./attr_print0: send attr long_number = 4321
./attr_print0: send attr protocol = test
./attr_print0: send attr number = 4711 ./attr_print0: send attr number = 4711
./attr_print0: send attr long_number = 1234 ./attr_print0: send attr long_number = 1234
./attr_print0: send attr string = whoopee ./attr_print0: send attr string = whoopee
./attr_print0: send attr data = [data 7 bytes] ./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: unknown_stream: wanted attribute: number
./attr_scan0: input attribute name: number ./attr_scan0: input attribute name: number
./attr_scan0: input attribute value: 4711 ./attr_scan0: input attribute value: 4711
@ -36,6 +42,9 @@
./attr_scan0: input attribute value: 4321 ./attr_scan0: input attribute value: 4321
./attr_scan0: unknown_stream: wanted attribute: (list terminator) ./attr_scan0: unknown_stream: wanted attribute: (list terminator)
./attr_scan0: input attribute name: (end) ./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: unknown_stream: wanted attribute: number
./attr_scan0: input attribute name: number ./attr_scan0: input attribute name: number
./attr_scan0: input attribute value: 4711 ./attr_scan0: input attribute value: 4711
@ -50,6 +59,10 @@
./attr_scan0: input attribute value: d2hvb3BlZQ== ./attr_scan0: input attribute value: d2hvb3BlZQ==
./attr_scan0: unknown_stream: wanted attribute: (list terminator) ./attr_scan0: unknown_stream: wanted attribute: (list terminator)
./attr_scan0: input attribute name: (end) ./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 number 4711
long_number 1234 long_number 1234
string whoopee string whoopee
@ -63,3 +76,4 @@ string whoopee
data whoopee data whoopee
(hash) foo-name foo-value (hash) foo-name foo-value
(hash) bar-name bar-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. /* This argument is followed by an attribute name and a long pointer.
/* .IP "RECV_ATTR_STR(const char *name, VSTRING *vp)" /* .IP "RECV_ATTR_STR(const char *name, VSTRING *vp)"
/* This argument is followed by an attribute name and a VSTRING pointer. /* 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)" /* .IP "RECV_ATTR_DATA(const char *name, VSTRING *vp)"
/* This argument is followed by an attribute name and a VSTRING pointer. /* This argument is followed by an attribute name and a VSTRING pointer.
/* .IP "RECV_ATTR_FUNC(ATTR_SCAN_CUSTOM_FN, void *data)" /* .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; int conversions;
ATTR_SCAN_CUSTOM_FN scan_fn; ATTR_SCAN_CUSTOM_FN scan_fn;
void *scan_arg; void *scan_arg;
const char *expect_val;
/* /*
* Sanity check. * 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) if (scan_fn(attr_scan64, fp, flags | ATTR_FLAG_MORE, scan_arg) < 0)
return (-1); return (-1);
break; 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_HASH:
case ATTR_TYPE_CLOSE: case ATTR_TYPE_CLOSE:
if (ch != ':') { if (ch != ':') {
@ -572,6 +599,7 @@ int main(int unused_argc, char **used_argv)
msg_vstream_init(used_argv[0], VSTREAM_ERR); msg_vstream_init(used_argv[0], VSTREAM_ERR);
if ((ret = attr_scan64(VSTREAM_IN, if ((ret = attr_scan64(VSTREAM_IN,
ATTR_FLAG_STRICT, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
RECV_ATTR_INT(ATTR_NAME_INT, &int_val), RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val), RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
RECV_ATTR_STR(ATTR_NAME_STR, str_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, if ((ret = attr_scan64(VSTREAM_IN,
ATTR_FLAG_STRICT, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
RECV_ATTR_INT(ATTR_NAME_INT, &int_val), RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val), RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
RECV_ATTR_STR(ATTR_NAME_STR, str_val), RECV_ATTR_STR(ATTR_NAME_STR, str_val),
@ -609,6 +638,11 @@ int main(int unused_argc, char **used_argv)
} else { } else {
vstream_printf("return: %d\n", ret); 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) if (vstream_fflush(VSTREAM_OUT) != 0)
msg_fatal("write error: %m"); 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 number = 4711
./attr_print64: send attr long_number = 1234 ./attr_print64: send attr long_number = 1234
./attr_print64: send attr string = whoopee ./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 foo-name value foo-value
./attr_print64: send attr name bar-name value bar-value ./attr_print64: send attr name bar-name value bar-value
./attr_print64: send attr long_number = 4321 ./attr_print64: send attr long_number = 4321
./attr_print64: send attr protocol = test
./attr_print64: send attr number = 4711 ./attr_print64: send attr number = 4711
./attr_print64: send attr long_number = 1234 ./attr_print64: send attr long_number = 1234
./attr_print64: send attr string = whoopee ./attr_print64: send attr string = whoopee
./attr_print64: send attr data = [data 7 bytes] ./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: unknown_stream: wanted attribute: number
./attr_scan64: input attribute name: number ./attr_scan64: input attribute name: number
./attr_scan64: input attribute value: 4711 ./attr_scan64: input attribute value: 4711
@ -36,6 +42,9 @@
./attr_scan64: input attribute value: 4321 ./attr_scan64: input attribute value: 4321
./attr_scan64: unknown_stream: wanted attribute: (list terminator) ./attr_scan64: unknown_stream: wanted attribute: (list terminator)
./attr_scan64: input attribute name: (end) ./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: unknown_stream: wanted attribute: number
./attr_scan64: input attribute name: number ./attr_scan64: input attribute name: number
./attr_scan64: input attribute value: 4711 ./attr_scan64: input attribute value: 4711
@ -50,6 +59,10 @@
./attr_scan64: input attribute value: whoopee ./attr_scan64: input attribute value: whoopee
./attr_scan64: unknown_stream: wanted attribute: (list terminator) ./attr_scan64: unknown_stream: wanted attribute: (list terminator)
./attr_scan64: input attribute name: (end) ./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 number 4711
long_number 1234 long_number 1234
string whoopee string whoopee
@ -63,3 +76,4 @@ string whoopee
data whoopee data whoopee
(hash) foo-name foo-value (hash) foo-name foo-value
(hash) bar-name bar-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. /* This argument is followed by an attribute name and a long pointer.
/* .IP "RECV_ATTR_STR(const char *name, VSTRING *vp)" /* .IP "RECV_ATTR_STR(const char *name, VSTRING *vp)"
/* This argument is followed by an attribute name and a VSTRING pointer. /* 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)" /* .IP "RECV_ATTR_DATA(const char *name, VSTRING *vp)"
/* This argument is followed by an attribute name and a VSTRING pointer. /* This argument is followed by an attribute name and a VSTRING pointer.
/* .IP "RECV_ATTR_FUNC(ATTR_SCAN_CUSTOM_FN, void *data)" /* .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; int conversions;
ATTR_SCAN_CUSTOM_FN scan_fn; ATTR_SCAN_CUSTOM_FN scan_fn;
void *scan_arg; void *scan_arg;
const char *expect_val;
/* /*
* Sanity check. * 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) if (scan_fn(attr_scan_plain, fp, flags | ATTR_FLAG_MORE, scan_arg) < 0)
return (-1); return (-1);
break; 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_HASH:
case ATTR_TYPE_CLOSE: case ATTR_TYPE_CLOSE:
if (ch != '=') { if (ch != '=') {
@ -555,6 +577,7 @@ int main(int unused_argc, char **used_argv)
msg_vstream_init(used_argv[0], VSTREAM_ERR); msg_vstream_init(used_argv[0], VSTREAM_ERR);
if ((ret = attr_scan_plain(VSTREAM_IN, if ((ret = attr_scan_plain(VSTREAM_IN,
ATTR_FLAG_STRICT, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
RECV_ATTR_INT(ATTR_NAME_INT, &int_val), RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val), RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
RECV_ATTR_STR(ATTR_NAME_STR, str_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, if ((ret = attr_scan_plain(VSTREAM_IN,
ATTR_FLAG_STRICT, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
RECV_ATTR_INT(ATTR_NAME_INT, &int_val), RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val), RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
RECV_ATTR_STR(ATTR_NAME_STR, str_val), RECV_ATTR_STR(ATTR_NAME_STR, str_val),
@ -592,6 +616,11 @@ int main(int unused_argc, char **used_argv)
} else { } else {
vstream_printf("return: %d\n", ret); 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) if (vstream_fflush(VSTREAM_OUT) != 0)
msg_fatal("write error: %m"); 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 number = 4711
./attr_print_plain: send attr long_number = 1234 ./attr_print_plain: send attr long_number = 1234
./attr_print_plain: send attr string = whoopee ./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 foo-name value foo-value
./attr_print_plain: send attr name bar-name value bar-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 long_number = 4321
./attr_print_plain: send attr protocol = test
./attr_print_plain: send attr number = 4711 ./attr_print_plain: send attr number = 4711
./attr_print_plain: send attr long_number = 1234 ./attr_print_plain: send attr long_number = 1234
./attr_print_plain: send attr string = whoopee ./attr_print_plain: send attr string = whoopee
./attr_print_plain: send attr data = [data 7 bytes] ./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: unknown_stream: wanted attribute: number
./attr_scan_plain: input attribute name: number ./attr_scan_plain: input attribute name: number
./attr_scan_plain: input attribute value: 4711 ./attr_scan_plain: input attribute value: 4711
@ -36,6 +42,9 @@
./attr_scan_plain: input attribute value: 4321 ./attr_scan_plain: input attribute value: 4321
./attr_scan_plain: unknown_stream: wanted attribute: (list terminator) ./attr_scan_plain: unknown_stream: wanted attribute: (list terminator)
./attr_scan_plain: input attribute name: (end) ./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: unknown_stream: wanted attribute: number
./attr_scan_plain: input attribute name: number ./attr_scan_plain: input attribute name: number
./attr_scan_plain: input attribute value: 4711 ./attr_scan_plain: input attribute value: 4711
@ -50,6 +59,10 @@
./attr_scan_plain: input attribute value: d2hvb3BlZQ== ./attr_scan_plain: input attribute value: d2hvb3BlZQ==
./attr_scan_plain: unknown_stream: wanted attribute: (list terminator) ./attr_scan_plain: unknown_stream: wanted attribute: (list terminator)
./attr_scan_plain: input attribute name: (end) ./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 number 4711
long_number 1234 long_number 1234
string whoopee string whoopee
@ -63,3 +76,4 @@ string whoopee
data whoopee data whoopee
(hash) foo-name foo-value (hash) foo-name foo-value
(hash) bar-name bar-value (hash) bar-name bar-value
return: -1

View File

@ -6,6 +6,8 @@
/* SYNOPSIS /* SYNOPSIS
/* #include <auto_clnt.h> /* #include <auto_clnt.h>
/* /*
/* typedef void (*AUTO_CLNT_HANDSHAKE_FN)(VSTREAM *);
/*
/* AUTO_CLNT *auto_clnt_create(service, timeout, max_idle, max_ttl) /* AUTO_CLNT *auto_clnt_create(service, timeout, max_idle, max_ttl)
/* const char *service; /* const char *service;
/* int timeout; /* int timeout;
@ -23,6 +25,10 @@
/* /*
/* void auto_clnt_free(auto_clnt) /* void auto_clnt_free(auto_clnt)
/* AUTO_CLNT *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 /* DESCRIPTION
/* This module maintains IPC client endpoints that automatically /* This module maintains IPC client endpoints that automatically
/* disconnect after a being idle for a configurable amount of time, /* 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_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: /* Arguments:
/* .IP service /* .IP service
/* The service argument specifies "transport:servername" where /* The service argument specifies "transport:servername" where
@ -79,6 +94,10 @@
/* is expected to set the stream pathname to the server endpoint name. /* is expected to set the stream pathname to the server endpoint name.
/* .IP context /* .IP context
/* Application context that is passed to the open_action routine. /* 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 /* DIAGNOSTICS
/* Warnings: communication failure. Fatal error: out of memory. /* Warnings: communication failure. Fatal error: out of memory.
/* LICENSE /* LICENSE
@ -90,6 +109,11 @@
/* IBM T.J. Watson Research /* IBM T.J. Watson Research
/* P.O. Box 704 /* P.O. Box 704
/* Yorktown Heights, NY 10598, USA /* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/ /*--*/
/* System library. */ /* System library. */
@ -120,6 +144,7 @@ struct AUTO_CLNT {
int timeout; /* I/O time limit */ int timeout; /* I/O time limit */
int max_idle; /* time before client disconnect */ int max_idle; /* time before client disconnect */
int max_ttl; /* 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 */ 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) VSTREAM *auto_clnt_access(AUTO_CLNT *auto_clnt)
{ {
AUTO_CLNT_HANDSHAKE_FN handshake;
/* /*
* Open a stream or restart the idle timer. * 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) { if (auto_clnt->vstream == 0) {
auto_clnt_open(auto_clnt); auto_clnt_open(auto_clnt);
handshake = (auto_clnt->vstream ? auto_clnt->handshake : 0);
} else { } else {
if (auto_clnt->max_idle > 0) if (auto_clnt->max_idle > 0)
event_request_timer(auto_clnt_event, (void *) auto_clnt, event_request_timer(auto_clnt_event, (void *) auto_clnt,
auto_clnt->max_idle); auto_clnt->max_idle);
handshake = 0;
} }
if (handshake != 0 && handshake(auto_clnt->vstream) != 0)
return (0);
return (auto_clnt->vstream); return (auto_clnt->vstream);
} }
@ -290,6 +320,7 @@ AUTO_CLNT *auto_clnt_create(const char *service, int timeout,
auto_clnt->timeout = timeout; auto_clnt->timeout = timeout;
auto_clnt->max_idle = max_idle; auto_clnt->max_idle = max_idle;
auto_clnt->max_ttl = max_ttl; auto_clnt->max_ttl = max_ttl;
auto_clnt->handshake = 0;
if (strcmp(transport, "inet") == 0) { if (strcmp(transport, "inet") == 0) {
auto_clnt->connect = inet_connect; auto_clnt->connect = inet_connect;
} else if (strcmp(transport, "local") == 0) { } else if (strcmp(transport, "local") == 0) {
@ -320,3 +351,22 @@ void auto_clnt_free(AUTO_CLNT *auto_clnt)
myfree(auto_clnt->endpoint); myfree(auto_clnt->endpoint);
myfree((void *) auto_clnt); 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. * External interface.
*/ */
typedef struct AUTO_CLNT AUTO_CLNT; 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 AUTO_CLNT *auto_clnt_create(const char *, int, int, int);
extern VSTREAM *auto_clnt_access(AUTO_CLNT *); extern VSTREAM *auto_clnt_access(AUTO_CLNT *);
extern void auto_clnt_recover(AUTO_CLNT *); extern void auto_clnt_recover(AUTO_CLNT *);
extern const char *auto_clnt_name(AUTO_CLNT *); extern const char *auto_clnt_name(AUTO_CLNT *);
extern void auto_clnt_free(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 /* LICENSE
/* .ad /* .ad
@ -36,6 +41,11 @@ extern void auto_clnt_free(AUTO_CLNT *);
/* IBM T.J. Watson Research /* IBM T.J. Watson Research
/* P.O. Box 704 /* P.O. Box 704
/* Yorktown Heights, NY 10598, USA /* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/ /*--*/
#endif #endif

View File

@ -95,7 +95,6 @@
#include <vstream.h> #include <vstream.h>
#include <msg_vstream.h> #include <msg_vstream.h>
#include <stringops.h> #include <stringops.h>
#include <percentm.h>
#include <msg_output.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); msg_vstream_init("unknown", VSTREAM_ERR);
vp = msg_buffers[msg_vprintf_level - 1]; vp = msg_buffers[msg_vprintf_level - 1];
/* OK if terminating signal handler hijacks control before next stmt. */ /* 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), '?'); printable(vstring_str(vp), '?');
for (i = 0; i < msg_output_fn_count; i++) for (i = 0; i < msg_output_fn_count; i++)
msg_output_fn[i] (level, vstring_str(vp)); 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) (addr_status != DEL_RCPT_STAT_OK && updated + var_verify_neg_try < now)
if (now - probed > PROBE_TTL if (now - probed > PROBE_TTL
&& (POSITIVE_REFRESH_NEEDED(addr_status, updated) && (POSITIVE_REFRESH_NEEDED(addr_status, updated)
|| NEGATIVE_REFRESH_NEEDED(addr_status, updated))) { || NEGATIVE_REFRESH_NEEDED(addr_status, updated))) {
if (msg_verbose) if (msg_verbose)
msg_info("PROBE %s status=%d probed=%ld updated=%ld", msg_info("PROBE %s status=%d probed=%ld updated=%ld",
STR(addr), addr_status, now, updated); STR(addr), addr_status, now, updated);
@ -723,6 +723,21 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
RESTORE_SAVED_EUGID(); 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; MAIL_VERSION_STAMP_DECLARE;
/* main - pass control to the multi-threaded skeleton */ /* 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_TIME_TABLE(time_table),
CA_MAIL_SERVER_PRE_INIT(pre_jail_init), CA_MAIL_SERVER_PRE_INIT(pre_jail_init),
CA_MAIL_SERVER_POST_INIT(post_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_SOLITARY,
CA_MAIL_SERVER_EXIT(verify_dump), CA_MAIL_SERVER_EXIT(verify_dump),
0); 0);