]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.6-20200920
authorWietse Venema <wietse@porcupine.org>
Sun, 20 Sep 2020 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Mon, 12 Oct 2020 01:32:15 +0000 (23:32 -0200)
76 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/WISHLIST
postfix/html/cleanup.8.html
postfix/html/trivial-rewrite.8.html
postfix/man/man8/cleanup.8
postfix/man/man8/trivial-rewrite.8
postfix/src/anvil/anvil.c
postfix/src/bounce/bounce.c
postfix/src/cleanup/cleanup.c
postfix/src/flush/flush.c
postfix/src/global/abounce.c
postfix/src/global/anvil_clnt.c
postfix/src/global/bounce.c
postfix/src/global/clnt_stream.c
postfix/src/global/clnt_stream.h
postfix/src/global/defer.c
postfix/src/global/deliver_pass.c
postfix/src/global/deliver_request.c
postfix/src/global/dict_proxy.c
postfix/src/global/flush_clnt.c
postfix/src/global/haproxy_srvr.c
postfix/src/global/mail_command_client.c
postfix/src/global/mail_proto.h
postfix/src/global/mail_stream.c
postfix/src/global/mail_version.h
postfix/src/global/post_mail.c
postfix/src/global/resolve_clnt.c
postfix/src/global/rewrite_clnt.c
postfix/src/global/sasl_mech_filter.c
postfix/src/global/scache_clnt.c
postfix/src/global/trace.c
postfix/src/global/verify_clnt.c
postfix/src/local/forward.c
postfix/src/master/event_server.c
postfix/src/master/mail_server.h
postfix/src/master/multi_server.c
postfix/src/oqmgr/qmgr_deliver.c
postfix/src/pickup/pickup.c
postfix/src/postconf/Makefile.in
postfix/src/postdrop/postdrop.c
postfix/src/postlogd/Makefile.in
postfix/src/postqueue/.indent.pro [new symlink]
postfix/src/postqueue/postqueue.c
postfix/src/postscreen/postscreen_starttls.c
postfix/src/proxymap/proxymap.c
postfix/src/qmgr/qmgr_deliver.c
postfix/src/scache/scache.c
postfix/src/showq/showq.c
postfix/src/smtpd/Makefile.in
postfix/src/spawn/Makefile.in
postfix/src/tls/tls_mgr.c
postfix/src/tls/tls_proxy_clnt.c
postfix/src/tlsmgr/tlsmgr.c
postfix/src/tlsproxy/tlsproxy.c
postfix/src/trivial-rewrite/trivial-rewrite.c
postfix/src/util/Makefile.in
postfix/src/util/attr.h
postfix/src/util/attr_clnt.c
postfix/src/util/attr_clnt.h
postfix/src/util/attr_print0.c
postfix/src/util/attr_print64.c
postfix/src/util/attr_print_plain.c
postfix/src/util/attr_scan0.c
postfix/src/util/attr_scan0.ref
postfix/src/util/attr_scan64.c
postfix/src/util/attr_scan64.ref
postfix/src/util/attr_scan_plain.c
postfix/src/util/attr_scan_plain.ref
postfix/src/util/auto_clnt.c
postfix/src/util/auto_clnt.h
postfix/src/util/msg_output.c
postfix/src/util/percentm.c [deleted file]
postfix/src/util/percentm.h [deleted file]
postfix/src/verify/verify.c

index 3f054f2ed17e735b3698c8e6905a67e5455e746e..736227a07e1d7ea3b23eda515ba66984504b075d 100644 (file)
@@ -1,4 +1,4 @@
--TABOUNCE
+-TABOUNCE_STATE
 -TADDR_MATCH_LIST
 -TADDR_PATTERN
 -TALIAS_TOKEN
index edede8a0436267f5a3329aad111df918c8e92589..408c9ce3872bfbd4b778f77428f7cdba63ac1010 100644 (file)
@@ -25057,6 +25057,8 @@ Apologies for any names omitted.
        mantools/man2html, mantools/readme2html, proto/*_README.html,
        proto/INSTALL.html, proto/postconf.html.prolog, html/index.html.
 
+20200830
+
        Refactor: moved the SASL mechanism filter code from the
        Postfix SMTP client to a library module, so that it can be
        reused in the Postfix SMTP server. Files: smtp/smtp_sasl_proto.c,
@@ -25071,3 +25073,83 @@ Apologies for any names omitted.
        wants to anounce EXTERNAL support for which Postfix support
        does not exist. Files: smtpd/smtpd.[hc], smtpd_sasl_glue.[hc],
        global/mail_params.h, proto/postconf.proto, mantools/postlink.
+
+20200906
+
+       Cleanup: missing file. File: src/postqueue/.indent.pro.
+
+       Cleanup: uninitialized value in unit test code. File:
+       global/haproxy_srvr.c.
+
+       Cleanup: duplicate 'const' in argument declaration. File:
+       src/global/sasl_mech_filter.c.
+
+20200906-18
+
+       Baseline is postfix-3.6-20200906.
+
+       Other debt: internal protocol identification. Each server
+       sends the name of the internal protocol that it implements,
+       and each client logs a warning if it receives the wrong
+       protocol name. With this, a client-server mismatch results
+       in a better error message. It is a good idea to "postfix
+       stop" before updating, or before backing out to an earlier
+       relase. To make this work consistently, a few internal
+       protocols were converted from "client speaks first" to
+       "server speaks first". Files: anvil/anvil.c, bounce/bounce.c,
+       cleanup/cleanup.c, flush/flush.c, global/abounce.c,
+       global/anvil_clnt.c, global/bounce.c, global/clnt_stream.c,
+       global/clnt_stream.h, global/defer.c, global/deliver_pass.c,
+       global/deliver_request.c, global/dict_proxy.c, global/flush_clnt.c,
+       global/mail_command_client.c, global/mail_proto.h,
+       global/mail_stream.c, global/mail_version.h, global/post_mail.c,
+       global/resolve_clnt.c, global/rewrite_clnt.c, global/scache_clnt.c,
+       global/trace.c, global/verify_clnt.c, local/forward.c,
+       master/event_server.c, master/mail_server.h, master/multi_server.c,
+       oqmgr/qmgr_deliver.c, pickup/pickup.c, postdrop/postdrop.c,
+       postqueue/postqueue.c, postscreen/postscreen_starttls.c,
+       proxymap/proxymap.c, qmgr/qmgr_deliver.c, scache/scache.c,
+       showq/showq.c, tls/tls_mgr.c, tls/tls_proxy_clnt.c,
+       tlsmgr/tlsmgr.c, tlsproxy/tlsproxy.c,
+       trivial-rewrite/trivial-rewrite.c, util/attr.h, util/attr_clnt.c,
+       util/attr_clnt.h, util/attr_print0.c, util/attr_print64.c,
+       util/attr_print_plain.c, util/attr_scan0.c, util/attr_scan64.c,
+       util/attr_scan_plain.c, util/auto_clnt.c, util/auto_clnt.h,
+       verify/verify.c.
+
+       Debt: during the conversion of some internal protocols to
+       "server speaks first", took the opportunity to improve how
+       event-driven client implementations handle a server that
+       is locked up.  Files: global/abounce.c,
+       postscreen/postscreen_starttls.c.
+
+20200919
+
+       Cleanup: eliminated a silly optimization for lazy clients
+       that read the "server speaks first" protocol announcement
+       after sending a client request. Files: src/anvil/anvil.c,
+       src/bounce/bounce.c, src/flush/flush.c, src/global/abounce.c,
+       src/global/anvil_clnt.c, src/global/deliver_pass.c,
+       src/global/deliver_request.c, src/global/dict_proxy.c,
+       src/global/mail_command_client.c, src/global/mail_stream.c,
+       src/global/resolve_clnt.c, src/global/rewrite_clnt.c,
+       src/global/scache_clnt.c, src/global/verify_clnt.c,
+       src/local/forward.c, src/oqmgr/qmgr_deliver.c, src/pickup/pickup.c,
+       src/postqueue/postqueue.c, src/postscreen/postscreen_starttls.c,
+       src/proxymap/proxymap.c, src/qmgr/qmgr_deliver.c,
+       src/scache/scache.c, src/showq/showq.c, src/tlsmgr/tlsmgr.c,
+       src/tlsproxy/tlsproxy.c, src/tls/tls_mgr.c,
+       src/tls/tls_proxy_clnt.c, src/trivial-rewrite/trivial-rewrite.c,
+       src/verify/verify.c.
+
+       Cleanup: factored out some duplicate showq client code.
+       File: postqueue/postqueue.c.
+
+20200920
+
+       Cleanup: deleted the percentm module. It was obsoleted in
+       19971027 by the vbuf_print() string formatter for VSTREAM
+       and VSTRING objects. Files: util/percentm.[hc].
+
+       Cleanup: replaced hard-coded 'private' with named constant.
+       File: global/scache_clnt.c.
index a6576c3b92a6c6643a6b47010ccd7a6fb6e5dcb3..f9ce0ef5ca2ad73c6737e202c56c7ceec2e7f3f0 100644 (file)
@@ -25,6 +25,22 @@ more recent Eclipse Public License 2.0. Recipients can choose to take
 the software under the license of their choice. Those who are more
 comfortable with the IPL can continue with that license.
 
+Incompatible change with snapshot 20200920
+==========================================
+
+Internal protocols have changed. You need to "postfix stop" before
+updating, or before backing out to an earlier release, otherwise
+long-running daemons (pickup, qmgr, verify, tlsproxy, postscreen)
+may fail to communicate with the rest of Postfix (warnings, timeouts).
+
+The purpose of this change is to produce better error messages, for
+example, when someone configures the discard daemon as a bounce
+service in master.cf, or vice versa.
+
+This change will break third-party code that implements a
+Postfix-internal protocol such as qpsmtpd. Programs that depend on
+Postfix internal details are not supported.
+
 Incompatible change with snapshot 20200705
 ==========================================
 
index 8707e5e293db7b949f66c0615d6d05bc207d9230..b2eff8711362a877ae6fa39873ec62696c8a8b59 100644 (file)
@@ -1,5 +1,23 @@
 Wish list:
 
+       Does tlsproxy terminate to soon after 'postfix reload'?
+
+       The documented order of relay/recipient restrictions differs
+       from the implementation. This may need a new compatibility
+       parameter. For example:
+       http://postfix.1071664.n5.nabble.com/Relay-attempt-questions-td103646.html
+
+       Hardening the half-dane behavior: some sites may rely on
+       current behavior which allows original MX domain name for
+       certificate matches. Requires a new (compatibility) parameter
+       setting?
+
+       multi_server applications could be migrated to event_server;
+       after accept(), they would have to set up their own read
+       event callback for handling requests.
+
+       Maybe expand %m to "application error" when errno == 0.
+
        smtp_sasl_tls_security_options = noanonymous, and make
        smtp_sasl_security_options default dependent on the
        smtp_sasl_tls_security_options default (i.e. reverse the
index f7f2efdc907bb1aacfa38098050044a6c04448a5..3d0039413370fd7e39427e2ad440bf9fc5fed6d7 100644 (file)
@@ -162,11 +162,12 @@ CLEANUP(8)                                                          CLEANUP(8)
               Postfix 2.6 the default protocol is 2.
 
        <b><a href="postconf.5.html#milter_default_action">milter_default_action</a> (tempfail)</b>
-              The  default  action  when a Milter (mail filter) application is
-              unavailable or mis-configured.
+              The  default  action  when  a  Milter  (mail filter) response is
+              unavailable (for example, bad Postfix  configuration  or  Milter
+              failure).
 
        <b><a href="postconf.5.html#milter_macro_daemon_name">milter_macro_daemon_name</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
-              The {daemon_name} macro value for Milter (mail filter)  applica-
+              The  {daemon_name} macro value for Milter (mail filter) applica-
               tions.
 
        <b><a href="postconf.5.html#milter_macro_v">milter_macro_v</a> ($<a href="postconf.5.html#mail_name">mail_name</a> $<a href="postconf.5.html#mail_version">mail_version</a>)</b>
@@ -177,45 +178,45 @@ CLEANUP(8)                                                          CLEANUP(8)
               tion, and for negotiating protocol options.
 
        <b><a href="postconf.5.html#milter_command_timeout">milter_command_timeout</a> (30s)</b>
-              The time limit for sending an SMTP command  to  a  Milter  (mail
+              The  time  limit  for  sending an SMTP command to a Milter (mail
               filter) application, and for receiving the response.
 
        <b><a href="postconf.5.html#milter_content_timeout">milter_content_timeout</a> (300s)</b>
-              The  time  limit  for  sending message content to a Milter (mail
+              The time limit for sending message content  to  a  Milter  (mail
               filter) application, and for receiving the response.
 
        <b><a href="postconf.5.html#milter_connect_macros">milter_connect_macros</a> (see 'postconf -d' output)</b>
-              The macros that are sent to Milter  (mail  filter)  applications
+              The  macros  that  are sent to Milter (mail filter) applications
               after completion of an SMTP connection.
 
        <b><a href="postconf.5.html#milter_helo_macros">milter_helo_macros</a> (see 'postconf -d' output)</b>
-              The  macros  that  are sent to Milter (mail filter) applications
+              The macros that are sent to Milter  (mail  filter)  applications
               after the SMTP HELO or EHLO command.
 
        <b><a href="postconf.5.html#milter_mail_macros">milter_mail_macros</a> (see 'postconf -d' output)</b>
-              The macros that are sent to Milter  (mail  filter)  applications
+              The  macros  that  are sent to Milter (mail filter) applications
               after the SMTP MAIL FROM command.
 
        <b><a href="postconf.5.html#milter_rcpt_macros">milter_rcpt_macros</a> (see 'postconf -d' output)</b>
-              The  macros  that  are sent to Milter (mail filter) applications
+              The macros that are sent to Milter  (mail  filter)  applications
               after the SMTP RCPT TO command.
 
        <b><a href="postconf.5.html#milter_data_macros">milter_data_macros</a> (see 'postconf -d' output)</b>
-              The macros that are sent to version 4  or  higher  Milter  (mail
+              The  macros  that  are  sent to version 4 or higher Milter (mail
               filter) applications after the SMTP DATA command.
 
        <b><a href="postconf.5.html#milter_unknown_command_macros">milter_unknown_command_macros</a> (see 'postconf -d' output)</b>
-              The  macros  that  are  sent to version 3 or higher Milter (mail
+              The macros that are sent to version 3  or  higher  Milter  (mail
               filter) applications after an unknown SMTP command.
 
        <b><a href="postconf.5.html#milter_end_of_data_macros">milter_end_of_data_macros</a> (see 'postconf -d' output)</b>
-              The macros that are sent to Milter  (mail  filter)  applications
+              The  macros  that  are sent to Milter (mail filter) applications
               after the message end-of-data.
 
        Available in Postfix version 2.5 and later:
 
        <b><a href="postconf.5.html#milter_end_of_header_macros">milter_end_of_header_macros</a> (see 'postconf -d' output)</b>
-              The  macros  that  are sent to Milter (mail filter) applications
+              The macros that are sent to Milter  (mail  filter)  applications
               after the end of the message header.
 
        Available in Postfix version 2.7 and later:
@@ -227,8 +228,8 @@ CLEANUP(8)                                                          CLEANUP(8)
        Available in Postfix version 3.1 and later:
 
        <b><a href="postconf.5.html#milter_macro_defaults">milter_macro_defaults</a> (empty)</b>
-              Optional  list  of  <i>name=value</i> pairs that specify default values
-              for arbitrary macros that Postfix may send  to  Milter  applica-
+              Optional list of <i>name=value</i> pairs that  specify  default  values
+              for  arbitrary  macros  that Postfix may send to Milter applica-
               tions.
 
 <b>MIME PROCESSING CONTROLS</b>
@@ -254,91 +255,91 @@ CLEANUP(8)                                                          CLEANUP(8)
               ing information.
 
        <b><a href="postconf.5.html#strict_mime_encoding_domain">strict_mime_encoding_domain</a> (no)</b>
-              Reject  mail with invalid Content-Transfer-Encoding: information
+              Reject mail with invalid Content-Transfer-Encoding:  information
               for the message/* or multipart/* MIME content types.
 
        Available in Postfix version 2.5 and later:
 
        <b><a href="postconf.5.html#detect_8bit_encoding_header">detect_8bit_encoding_header</a> (yes)</b>
-              Automatically detect 8BITMIME body content by  looking  at  Con-
-              tent-Transfer-Encoding:   message  headers;  historically,  this
+              Automatically  detect  8BITMIME  body content by looking at Con-
+              tent-Transfer-Encoding:  message  headers;  historically,   this
               behavior was hard-coded to be "always on".
 
 <b>AUTOMATIC BCC RECIPIENT CONTROLS</b>
-       Postfix can automatically add BCC (blind carbon copy) when mail  enters
+       Postfix  can automatically add BCC (blind carbon copy) when mail enters
        the mail system:
 
        <b><a href="postconf.5.html#always_bcc">always_bcc</a> (empty)</b>
-              Optional  address  that  receives  a "blind carbon copy" of each
+              Optional address that receives a "blind  carbon  copy"  of  each
               message that is received by the Postfix mail system.
 
        Available in Postfix version 2.1 and later:
 
        <b><a href="postconf.5.html#sender_bcc_maps">sender_bcc_maps</a> (empty)</b>
-              Optional BCC (blind carbon-copy) address lookup tables,  indexed
+              Optional  BCC (blind carbon-copy) address lookup tables, indexed
               by sender address.
 
        <b><a href="postconf.5.html#recipient_bcc_maps">recipient_bcc_maps</a> (empty)</b>
-              Optional  BCC (blind carbon-copy) address lookup tables, indexed
+              Optional BCC (blind carbon-copy) address lookup tables,  indexed
               by recipient address.
 
 <b>ADDRESS TRANSFORMATION CONTROLS</b>
-       Address rewriting is delegated to the <a href="trivial-rewrite.8.html"><b>trivial-rewrite</b>(8)</a>  daemon.   The
+       Address  rewriting  is delegated to the <a href="trivial-rewrite.8.html"><b>trivial-rewrite</b>(8)</a> daemon.  The
        <a href="cleanup.8.html"><b>cleanup</b>(8)</a> server implements table driven address mapping.
 
        <b><a href="postconf.5.html#empty_address_recipient">empty_address_recipient</a> (MAILER-DAEMON)</b>
               The recipient of mail addressed to the null address.
 
        <b><a href="postconf.5.html#canonical_maps">canonical_maps</a> (empty)</b>
-              Optional  address  mapping lookup tables for message headers and
+              Optional address mapping lookup tables for message  headers  and
               envelopes.
 
        <b><a href="postconf.5.html#recipient_canonical_maps">recipient_canonical_maps</a> (empty)</b>
-              Optional address mapping lookup tables for envelope  and  header
+              Optional  address  mapping lookup tables for envelope and header
               recipient addresses.
 
        <b><a href="postconf.5.html#sender_canonical_maps">sender_canonical_maps</a> (empty)</b>
-              Optional  address  mapping lookup tables for envelope and header
+              Optional address mapping lookup tables for envelope  and  header
               sender addresses.
 
        <b><a href="postconf.5.html#masquerade_classes">masquerade_classes</a> (envelope_sender, header_sender, header_recipient)</b>
               What addresses are subject to address masquerading.
 
        <b><a href="postconf.5.html#masquerade_domains">masquerade_domains</a> (empty)</b>
-              Optional list of  domains  whose  subdomain  structure  will  be
+              Optional  list  of  domains  whose  subdomain  structure will be
               stripped off in email addresses.
 
        <b><a href="postconf.5.html#masquerade_exceptions">masquerade_exceptions</a> (empty)</b>
-              Optional  list  of  user names that are not subjected to address
-              masquerading,  even  when  their   addresses   match   $<a href="postconf.5.html#masquerade_domains">masquer</a>-
+              Optional list of user names that are not  subjected  to  address
+              masquerading,   even   when   their  addresses  match  $<a href="postconf.5.html#masquerade_domains">masquer</a>-
               <a href="postconf.5.html#masquerade_domains">ade_domains</a>.
 
        <b><a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a> (canonical, virtual)</b>
-              What  address  lookup  tables copy an address extension from the
+              What address lookup tables copy an address  extension  from  the
               lookup key to the lookup result.
 
        Available before Postfix version 2.0:
 
        <b><a href="postconf.5.html#virtual_maps">virtual_maps</a> (empty)</b>
-              Optional lookup tables with a) names of domains  for  which  all
-              addresses  are  aliased  to  addresses  in other local or remote
+              Optional  lookup  tables  with a) names of domains for which all
+              addresses are aliased to addresses  in  other  local  or  remote
               domains, and b) addresses that are aliased to addresses in other
               local or remote domains.
 
        Available in Postfix version 2.0 and later:
 
        <b><a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> ($<a href="postconf.5.html#virtual_maps">virtual_maps</a>)</b>
-              Optional  lookup  tables  that  alias specific mail addresses or
+              Optional lookup tables that alias  specific  mail  addresses  or
               domains to other local or remote address.
 
        Available in Postfix version 2.2 and later:
 
-       <b><a href="postconf.5.html#canonical_classes">canonical_classes</a> (envelope_sender, envelope_recipient,  header_sender,</b>
+       <b><a href="postconf.5.html#canonical_classes">canonical_classes</a>  (envelope_sender, envelope_recipient, header_sender,</b>
        <b>header_recipient)</b>
               What addresses are subject to <a href="postconf.5.html#canonical_maps">canonical_maps</a> address mapping.
 
        <b><a href="postconf.5.html#recipient_canonical_classes">recipient_canonical_classes</a> (envelope_recipient, header_recipient)</b>
-              What addresses are subject to  <a href="postconf.5.html#recipient_canonical_maps">recipient_canonical_maps</a>  address
+              What  addresses  are subject to <a href="postconf.5.html#recipient_canonical_maps">recipient_canonical_maps</a> address
               mapping.
 
        <b><a href="postconf.5.html#sender_canonical_classes">sender_canonical_classes</a> (envelope_sender, header_sender)</b>
@@ -346,8 +347,8 @@ CLEANUP(8)                                                          CLEANUP(8)
               ping.
 
        <b><a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> (empty)</b>
-              Don't rewrite message headers from remote clients  at  all  when
-              this  parameter is empty; otherwise, rewrite message headers and
+              Don't  rewrite  message  headers from remote clients at all when
+              this parameter is empty; otherwise, rewrite message headers  and
               append the specified domain name to incomplete addresses.
 
 <b>RESOURCE AND RATE CONTROLS</b>
@@ -357,7 +358,7 @@ CLEANUP(8)                                                          CLEANUP(8)
               <a href="showq.8.html"><b>showq</b>(8)</a> queue displays.
 
        <b><a href="postconf.5.html#header_size_limit">header_size_limit</a> (102400)</b>
-              The maximal amount of memory in  bytes  for  storing  a  message
+              The  maximal  amount  of  memory  in bytes for storing a message
               header.
 
        <b><a href="postconf.5.html#hopcount_limit">hopcount_limit</a> (50)</b>
@@ -365,17 +366,17 @@ CLEANUP(8)                                                          CLEANUP(8)
               in the primary message headers.
 
        <b><a href="postconf.5.html#in_flow_delay">in_flow_delay</a> (1s)</b>
-              Time to pause before accepting a new message, when  the  message
+              Time  to  pause before accepting a new message, when the message
               arrival rate exceeds the message delivery rate.
 
        <b><a href="postconf.5.html#message_size_limit">message_size_limit</a> (10240000)</b>
-              The  maximal  size  in  bytes  of  a message, including envelope
+              The maximal size in  bytes  of  a  message,  including  envelope
               information.
 
        Available in Postfix version 2.0 and later:
 
        <b><a href="postconf.5.html#header_address_token_limit">header_address_token_limit</a> (10240)</b>
-              The maximal number of address tokens are allowed in  an  address
+              The  maximal  number of address tokens are allowed in an address
               message header.
 
        <b><a href="postconf.5.html#mime_boundary_length_limit">mime_boundary_length_limit</a> (2048)</b>
@@ -391,7 +392,7 @@ CLEANUP(8)                                                          CLEANUP(8)
        Available in Postfix version 2.1 and later:
 
        <b><a href="postconf.5.html#virtual_alias_expansion_limit">virtual_alias_expansion_limit</a> (1000)</b>
-              The  maximal  number  of  addresses that virtual alias expansion
+              The maximal number of addresses  that  virtual  alias  expansion
               produces from each original recipient.
 
        <b><a href="postconf.5.html#virtual_alias_recursion_limit">virtual_alias_recursion_limit</a> (1000)</b>
@@ -400,50 +401,50 @@ CLEANUP(8)                                                          CLEANUP(8)
        Available in Postfix version 3.0 and later:
 
        <b><a href="postconf.5.html#virtual_alias_address_length_limit">virtual_alias_address_length_limit</a> (1000)</b>
-              The maximal length of  an  email  address  after  virtual  alias
+              The  maximal  length  of  an  email  address after virtual alias
               expansion.
 
 <b>SMTPUTF8 CONTROLS</b>
        Preliminary SMTPUTF8 support is introduced with Postfix 3.0.
 
        <b><a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> (yes)</b>
-              Enable  preliminary SMTPUTF8 support for the protocols described
+              Enable preliminary SMTPUTF8 support for the protocols  described
               in <a href="http://tools.ietf.org/html/rfc6531">RFC 6531</a>..6533.
 
        <b><a href="postconf.5.html#smtputf8_autodetect_classes">smtputf8_autodetect_classes</a> (sendmail, verify)</b>
-              Detect that a message requires SMTPUTF8 support for  the  speci-
+              Detect  that  a message requires SMTPUTF8 support for the speci-
               fied mail origin classes.
 
        Available in Postfix version 3.2 and later:
 
        <b><a href="postconf.5.html#enable_idna2003_compatibility">enable_idna2003_compatibility</a> (no)</b>
-              Enable   'transitional'   compatibility   between  IDNA2003  and
-              IDNA2008, when converting UTF-8 domain names to/from  the  ASCII
+              Enable  'transitional'  compatibility   between   IDNA2003   and
+              IDNA2008,  when  converting UTF-8 domain names to/from the ASCII
               form that is used for DNS lookups.
 
 <b>MISCELLANEOUS CONTROLS</b>
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The  default  location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
+              The default location of the Postfix <a href="postconf.5.html">main.cf</a> and  <a href="master.5.html">master.cf</a>  con-
               figuration files.
 
        <b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
-              How much time a Postfix daemon process  may  take  to  handle  a
+              How  much  time  a  Postfix  daemon process may take to handle a
               request before it is terminated by a built-in watchdog timer.
 
        <b><a href="postconf.5.html#delay_logging_resolution_limit">delay_logging_resolution_limit</a> (2)</b>
-              The  maximal  number of digits after the decimal point when log-
+              The maximal number of digits after the decimal point  when  log-
               ging sub-second delay values.
 
        <b><a href="postconf.5.html#delay_warning_time">delay_warning_time</a> (0h)</b>
-              The time after which the sender receives a copy of  the  message
+              The  time  after which the sender receives a copy of the message
               headers of mail that is still queued.
 
        <b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
-              The  time  limit  for  sending  or receiving information over an
+              The time limit for sending  or  receiving  information  over  an
               internal communication channel.
 
        <b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
-              The maximum amount of time that an idle Postfix  daemon  process
+              The  maximum  amount of time that an idle Postfix daemon process
               waits for an incoming connection before terminating voluntarily.
 
        <b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
@@ -454,7 +455,7 @@ CLEANUP(8)                                                          CLEANUP(8)
               The internet hostname of this mail system.
 
        <b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
-              The  domain  name that locally-posted mail appears to come from,
+              The domain name that locally-posted mail appears to  come  from,
               and that locally posted mail is delivered to.
 
        <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
@@ -467,21 +468,21 @@ CLEANUP(8)                                                          CLEANUP(8)
               The location of the Postfix top-level queue directory.
 
        <b><a href="postconf.5.html#soft_bounce">soft_bounce</a> (no)</b>
-              Safety net to keep mail queued that would otherwise be  returned
+              Safety  net to keep mail queued that would otherwise be returned
               to the sender.
 
        <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
               The syslog facility of Postfix logging.
 
        <b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
-              A  prefix  that  is  prepended  to  the  process  name in syslog
+              A prefix that  is  prepended  to  the  process  name  in  syslog
               records, so that, for example, "smtpd" becomes "prefix/smtpd".
 
        Available in Postfix version 2.1 and later:
 
        <b><a href="postconf.5.html#enable_original_recipient">enable_original_recipient</a> (yes)</b>
-              Enable support for  the  original  recipient  address  after  an
-              address  is  rewritten  to a different address (for example with
+              Enable  support  for  the  original  recipient  address after an
+              address is rewritten to a different address  (for  example  with
               aliasing or with canonical mapping).
 
        Available in Postfix 3.3 and later:
@@ -492,7 +493,7 @@ CLEANUP(8)                                                          CLEANUP(8)
        Available in Postfix 3.5 and later:
 
        <b>info_log_address_format (external)</b>
-              The email address form that will be used  in  non-debug  logging
+              The  email  address  form that will be used in non-debug logging
               (info, warning, etc.).
 
 <b>FILES</b>
index b6b0441552aa1a72086f5c9578ae4a6176fa3b00..bf166d3f1f8dcad05860bb9b0d92345450506fa0 100644 (file)
@@ -169,8 +169,8 @@ TRIVIAL-REWRITE(8)                                          TRIVIAL-REWRITE(8)
               explicit ".example.com" pattern.
 
        <b><a href="postconf.5.html#relayhost">relayhost</a> (empty)</b>
-              The  next-hop destination of non-local mail; overrides non-local
-              domains in recipient addresses.
+              The   next-hop  destination(s)  for  non-local  mail;  overrides
+              non-<a href="ADDRESS_CLASS_README.html#local_domain_class">local domains</a> in recipient addresses.
 
        <b><a href="postconf.5.html#transport_maps">transport_maps</a> (empty)</b>
               Optional lookup tables with mappings from recipient  address  to
index ed4e22bad3f2fe024d9c2fd90832a7ee3d4c36a3..69a2940d60a9bcc099229251edf93e70fcefb0eb 100644 (file)
@@ -164,8 +164,9 @@ The mail filter protocol version and optional protocol extensions
 for communication with a Milter application; prior to Postfix 2.6
 the default protocol is 2.
 .IP "\fBmilter_default_action (tempfail)\fR"
-The default action when a Milter (mail filter) application is
-unavailable or mis\-configured.
+The default action when a Milter (mail filter) response is
+unavailable (for example, bad Postfix configuration or Milter
+failure).
 .IP "\fBmilter_macro_daemon_name ($myhostname)\fR"
 The {daemon_name} macro value for Milter (mail filter) applications.
 .IP "\fBmilter_macro_v ($mail_name $mail_version)\fR"
index 523c44c4ec1a94abfce25dbdaa089918846e6e3e..6bbf7de1fe920a34f8978131dcecc39d15efc9c1 100644 (file)
@@ -175,7 +175,7 @@ A list of Postfix features where the pattern "example.com" also
 matches subdomains of example.com,
 instead of requiring an explicit ".example.com" pattern.
 .IP "\fBrelayhost (empty)\fR"
-The next\-hop destination of non\-local mail; overrides non\-local
+The next\-hop destination(s) for non\-local mail; overrides non\-local
 domains in recipient addresses.
 .IP "\fBtransport_maps (empty)\fR"
 Optional lookup tables with mappings from recipient address to
index d0a5b2a188da0f3fbda750a6436642d3d00f2593..884be28b950b4293ae5175f35e8962c5e263c6ae 100644 (file)
@@ -1006,6 +1006,21 @@ static void post_jail_init(char *unused_name, char **unused_argv)
 
 MAIL_VERSION_STAMP_DECLARE;
 
+/* post_accept - announce our protocol */
+
+static void post_accept(VSTREAM *stream, char *unused_name,
+                               char **unused_argv, HTABLE *unused_table)
+{
+
+    /*
+     * Announce the protocol.
+     */
+    attr_print_plain(stream, ATTR_FLAG_NONE,
+                    SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_ANVIL),
+                    ATTR_TYPE_END);
+    (void) vstream_fflush(stream);
+}
+
 /* main - pass control to the multi-threaded skeleton */
 
 int     main(int argc, char **argv)
@@ -1024,6 +1039,7 @@ int     main(int argc, char **argv)
     multi_server_main(argc, argv, anvil_service,
                      CA_MAIL_SERVER_TIME_TABLE(time_table),
                      CA_MAIL_SERVER_POST_INIT(post_jail_init),
+                     CA_MAIL_SERVER_POST_ACCEPT(post_accept),
                      CA_MAIL_SERVER_SOLITARY,
                      CA_MAIL_SERVER_PRE_DISCONN(anvil_service_done),
                      CA_MAIL_SERVER_EXIT(anvil_status_dump),
index afbeb63045ef727ce16c541aeed4a12f17fc93b8..c6c9790333efc596a2069d6093d4a3eb09736737 100644 (file)
@@ -527,6 +527,14 @@ static void bounce_service(VSTREAM *client, char *service_name, char **argv)
     if (mail_queue_name_ok(service_name) == 0)
        msg_fatal("malformed service name: %s", service_name);
 
+    /*
+     * Announce the protocol.
+     */
+    attr_print(client, ATTR_FLAG_NONE,
+              SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_BOUNCE),
+              ATTR_TYPE_END);
+    (void) vstream_fflush(client);
+
     /*
      * Read and validate the first parameter of the client request. Let the
      * request-specific protocol routines take care of the remainder.
index a3e86936df09d61859e9ebf62b64433ea58af443..e47fae6e7aedc053ad7d750c00652ba362d9d12b 100644 (file)
 /*     for communication with a Milter application; prior to Postfix 2.6
 /*     the default protocol is 2.
 /* .IP "\fBmilter_default_action (tempfail)\fR"
-/*     The default action when a Milter (mail filter) application is
-/*     unavailable or mis-configured.
+/*     The default action when a Milter (mail filter) response is
+/*     unavailable (for example, bad Postfix configuration or Milter
+/*     failure).
 /* .IP "\fBmilter_macro_daemon_name ($myhostname)\fR"
 /*     The {daemon_name} macro value for Milter (mail filter) applications.
 /* .IP "\fBmilter_macro_v ($mail_name $mail_version)\fR"
@@ -503,6 +504,7 @@ static void cleanup_service(VSTREAM *src, char *unused_service, char **argv)
      * about the whole operation.
      */
     attr_print(src, ATTR_FLAG_NONE,
+              SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP),
               SEND_ATTR_STR(MAIL_ATTR_QUEUEID, state->queue_id),
               ATTR_TYPE_END);
     if (attr_scan(src, ATTR_FLAG_STRICT,
index 2e261bc32da97584775b20b03d528c727b14e551..30e5d2b2a6d5522e278244f8caebf45f78e566ae 100644 (file)
@@ -699,6 +699,14 @@ static int flush_request_receive(VSTREAM *client_stream, VSTRING *request)
 {
     int     count;
 
+    /*
+     * Announce the protocol.
+     */
+    attr_print(client_stream, ATTR_FLAG_NONE,
+              SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_FLUSH),
+              ATTR_TYPE_END);
+    (void) vstream_fflush(client_stream);
+
     /*
      * Kluge: choose the protocol depending on the request size.
      */
index efbf1050f1cd203a9678210896927075babf4d49..5522f602edddc3c9c3016a441f434249190d8f79 100644 (file)
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
@@ -202,10 +207,11 @@ typedef struct {
     int     command;                   /* bounce request type */
     int     flags;                     /* bounce options */
     char   *id;                                /* queue ID for logging */
+    VSTRING *request;                  /* serialized request */
     ABOUNCE_FN callback;               /* application callback */
     void   *context;                   /* application context */
     VSTREAM *fp;                       /* server I/O handle */
-} ABOUNCE;
+} ABOUNCE_STATE;
 
  /*
   * Encapsulate common code.
@@ -215,11 +221,6 @@ typedef struct {
        event_request_timer((callback), (context), (timeout)); \
     } while (0)
 
-#define ABOUNCE_EVENT_DISABLE(fd, callback, context) do { \
-       event_cancel_timer((callback), (context)); \
-       event_disable_readwrite(fd); \
-    } while (0)
-
  /*
   * If we set the reply timeout too short, then we make the problem worse by
   * increasing overload. With 1000s timeout mail will keep flowing, but there
@@ -228,11 +229,30 @@ typedef struct {
   */
 #define ABOUNCE_TIMEOUT        1000
 
+ /*
+  * The initial buffer size for a serialized request.
+  */
+#define ABOUNCE_BUFSIZE        VSTREAM_BUFSIZE
+
+ /*
+  * We share most of the verp and non-verp code paths.
+  */
+#define ABOUNCE_NO_VERP        ((char *) 0)
+
+ /*
+  * SLMs.
+  */
+#define STR(x) vstring_str(x)
+#define LEN(x) VSTRING_LEN(x)
+
 /* abounce_done - deliver status to application and clean up pseudo thread */
 
-static void abounce_done(ABOUNCE *ap, int status)
+static void abounce_done(ABOUNCE_STATE *ap, int status)
 {
-    (void) vstream_fclose(ap->fp);
+    if (ap->fp) {
+       event_disable_readwrite(vstream_fileno(ap->fp));
+       (void) vstream_fclose(ap->fp);
+    }
     if (status != 0 && (ap->flags & BOUNCE_FLAG_CLEAN) == 0)
        msg_info("%s: status=deferred (%s failed)", ap->id,
                 ap->command == BOUNCE_CMD_FLUSH ? "bounce" :
@@ -242,65 +262,125 @@ static void abounce_done(ABOUNCE *ap, int status)
                 "whatever");
     ap->callback(status, ap->context);
     myfree(ap->id);
+    vstring_free(ap->request);
     myfree((void *) ap);
 }
 
-/* abounce_event - resume pseudo thread after server reply event */
+/* abounce_receive - receive server reply */
 
-static void abounce_event(int event, void *context)
+static void abounce_receive(int event, void *context)
 {
-    ABOUNCE *ap = (ABOUNCE *) context;
+    ABOUNCE_STATE *ap = (ABOUNCE_STATE *) context;
     int     status;
 
-    ABOUNCE_EVENT_DISABLE(vstream_fileno(ap->fp), abounce_event, context);
-    abounce_done(ap, (event != EVENT_TIME
-                     && attr_scan(ap->fp, ATTR_FLAG_STRICT,
-                                  RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
-                                  ATTR_TYPE_END) == 1) ? status : -1);
+    if (event != EVENT_TIME)
+       event_cancel_timer(abounce_receive, context);
+
+    if (event == EVENT_READ
+       && attr_scan(ap->fp, ATTR_FLAG_STRICT,
+                    RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
+                    ATTR_TYPE_END) == 1) {
+       abounce_done(ap, status);
+    } else {
+       abounce_done(ap, -1);
+    }
 }
 
-/* abounce_request_verp - suspend pseudo thread until server reply event */
-
-static void abounce_request_verp(const char *class, const char *service,
-                                        int command, int flags,
-                                        const char *queue, const char *id,
-                                        const char *encoding,
-                                        int smtputf8,
-                                        const char *sender,
-                                        const char *dsn_envid,
-                                        int dsn_ret,
-                                        const char *verp,
-                                        ABOUNCE_FN callback,
-                                        void *context)
+/* abounce_send - send the request and suspend until the server replies */
+
+static void abounce_send(int event, void *context)
+{
+    ABOUNCE_STATE *ap = (ABOUNCE_STATE *) context;
+
+    /*
+     * Receive the server's protocol name announcement. At this point the
+     * server is ready to receive a request without blocking the sender. Send
+     * the request and suspend until the server replies (or dies).
+     */
+    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 *ap;
+    ABOUNCE_STATE *ap;
 
     /*
-     * Save pseudo thread state. Connect to the server. Send the request and
-     * suspend the pseudo thread until the server replies (or dies).
+     * 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 *) mymalloc(sizeof(*ap));
+    ap = (ABOUNCE_STATE *) mymalloc(sizeof(*ap));
     ap->command = command;
     ap->flags = flags;
     ap->id = mystrdup(id);
+    ap->request = vstring_alloc(ABOUNCE_BUFSIZE);
     ap->callback = callback;
     ap->context = context;
-    ap->fp = mail_connect_wait(class, service);
-
-    if (attr_print(ap->fp, ATTR_FLAG_NONE,
-                  SEND_ATTR_INT(MAIL_ATTR_NREQ, command),
-                  SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
-                  SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
-                  SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id),
-                  SEND_ATTR_STR(MAIL_ATTR_ENCODING, encoding),
-                  SEND_ATTR_INT(MAIL_ATTR_SMTPUTF8, smtputf8),
-                  SEND_ATTR_STR(MAIL_ATTR_SENDER, sender),
-                  SEND_ATTR_STR(MAIL_ATTR_DSN_ENVID, dsn_envid),
-                  SEND_ATTR_INT(MAIL_ATTR_DSN_RET, dsn_ret),
-                  SEND_ATTR_STR(MAIL_ATTR_VERPDL, verp),
-                  ATTR_TYPE_END) == 0
-       && vstream_fflush(ap->fp) == 0) {
-       ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_event,
+    ap->fp = mail_connect(class, service, NON_BLOCKING);
+
+    /*
+     * Format the request now, so that we don't have to save a lot of
+     * arguments now and format the request later.
+     */
+    if (ap->fp != 0) {
+       /* Note: all code paths must terminate or enable I/O events. */
+       VSTREAM *mp = vstream_memopen(ap->request, O_WRONLY);
+
+       if (attr_print(mp, ATTR_FLAG_MORE,
+                      SEND_ATTR_INT(MAIL_ATTR_NREQ, command),
+                      SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
+                      SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
+                      SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id),
+                      SEND_ATTR_STR(MAIL_ATTR_ENCODING, encoding),
+                      SEND_ATTR_INT(MAIL_ATTR_SMTPUTF8, smtputf8),
+                      SEND_ATTR_STR(MAIL_ATTR_SENDER, sender),
+                      SEND_ATTR_STR(MAIL_ATTR_DSN_ENVID, dsn_envid),
+                      SEND_ATTR_INT(MAIL_ATTR_DSN_RET, dsn_ret),
+                      ATTR_TYPE_END) != 0
+           || (verp != 0
+               && attr_print(mp, ATTR_FLAG_MORE,
+                             SEND_ATTR_STR(MAIL_ATTR_VERPDL, verp),
+                             ATTR_TYPE_END) != 0)
+           || attr_print(mp, ATTR_FLAG_NONE,
+                         ATTR_TYPE_END) != 0
+           || vstream_fclose(mp) != 0)
+           msg_panic("abounce_connect: write request to memory stream: %m");
+
+       /*
+        * Suspend until the server replies (or dies).
+        */
+       ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_send,
                             (void *) ap, ABOUNCE_TIMEOUT);
     } else {
        abounce_done(ap, -1);
@@ -316,9 +396,9 @@ void    abounce_flush_verp(int flags, const char *queue, const char *id,
                                   ABOUNCE_FN callback,
                                   void *context)
 {
-    abounce_request_verp(MAIL_CLASS_PRIVATE, var_bounce_service,
-                     BOUNCE_CMD_VERP, flags, queue, id, encoding, smtputf8,
-                      sender, dsn_envid, dsn_ret, verp, callback, context);
+    abounce_connect(MAIL_CLASS_PRIVATE, var_bounce_service,
+                   BOUNCE_CMD_VERP, flags, queue, id, encoding, smtputf8,
+                   sender, dsn_envid, dsn_ret, verp, callback, context);
 }
 
 /* adefer_flush_verp - asynchronous defer flush */
@@ -330,52 +410,9 @@ void    adefer_flush_verp(int flags, const char *queue, const char *id,
                                  ABOUNCE_FN callback, void *context)
 {
     flags |= BOUNCE_FLAG_DELRCPT;
-    abounce_request_verp(MAIL_CLASS_PRIVATE, var_defer_service,
-                     BOUNCE_CMD_VERP, flags, queue, id, encoding, smtputf8,
-                      sender, dsn_envid, dsn_ret, verp, callback, context);
-}
-
-/* abounce_request - suspend pseudo thread until server reply event */
-
-static void abounce_request(const char *class, const char *service,
-                                   int command, int flags,
-                                   const char *queue, const char *id,
-                                   const char *encoding, int smtputf8,
-                                   const char *sender,
-                                   const char *dsn_envid, int dsn_ret,
-                                   ABOUNCE_FN callback, void *context)
-{
-    ABOUNCE *ap;
-
-    /*
-     * Save pseudo thread state. Connect to the server. Send the request and
-     * suspend the pseudo thread until the server replies (or dies).
-     */
-    ap = (ABOUNCE *) mymalloc(sizeof(*ap));
-    ap->command = command;
-    ap->flags = flags;
-    ap->id = mystrdup(id);
-    ap->callback = callback;
-    ap->context = context;
-    ap->fp = mail_connect_wait(class, service);
-
-    if (attr_print(ap->fp, ATTR_FLAG_NONE,
-                  SEND_ATTR_INT(MAIL_ATTR_NREQ, command),
-                  SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
-                  SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
-                  SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id),
-                  SEND_ATTR_STR(MAIL_ATTR_ENCODING, encoding),
-                  SEND_ATTR_INT(MAIL_ATTR_SMTPUTF8, smtputf8),
-                  SEND_ATTR_STR(MAIL_ATTR_SENDER, sender),
-                  SEND_ATTR_STR(MAIL_ATTR_DSN_ENVID, dsn_envid),
-                  SEND_ATTR_INT(MAIL_ATTR_DSN_RET, dsn_ret),
-                  ATTR_TYPE_END) == 0
-       && vstream_fflush(ap->fp) == 0) {
-       ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_event,
-                            (void *) ap, ABOUNCE_TIMEOUT);
-    } else {
-       abounce_done(ap, -1);
-    }
+    abounce_connect(MAIL_CLASS_PRIVATE, var_defer_service,
+                   BOUNCE_CMD_VERP, flags, queue, id, encoding, smtputf8,
+                   sender, dsn_envid, dsn_ret, verp, callback, context);
 }
 
 /* abounce_flush - asynchronous bounce flush */
@@ -386,9 +423,9 @@ void    abounce_flush(int flags, const char *queue, const char *id,
                              int dsn_ret, ABOUNCE_FN callback,
                              void *context)
 {
-    abounce_request(MAIL_CLASS_PRIVATE, var_bounce_service, BOUNCE_CMD_FLUSH,
+    abounce_connect(MAIL_CLASS_PRIVATE, var_bounce_service, BOUNCE_CMD_FLUSH,
                    flags, queue, id, encoding, smtputf8, sender, dsn_envid,
-                   dsn_ret, callback, context);
+                   dsn_ret, ABOUNCE_NO_VERP, callback, context);
 }
 
 /* adefer_flush - asynchronous defer flush */
@@ -399,9 +436,9 @@ void    adefer_flush(int flags, const char *queue, const char *id,
                             int dsn_ret, ABOUNCE_FN callback, void *context)
 {
     flags |= BOUNCE_FLAG_DELRCPT;
-    abounce_request(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_FLUSH,
+    abounce_connect(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_FLUSH,
                    flags, queue, id, encoding, smtputf8, sender, dsn_envid,
-                   dsn_ret, callback, context);
+                   dsn_ret, ABOUNCE_NO_VERP, callback, context);
 }
 
 /* adefer_warn - send copy of defer log to sender as warning bounce */
@@ -411,9 +448,9 @@ void    adefer_warn(int flags, const char *queue, const char *id,
                            const char *sender, const char *dsn_envid,
                            int dsn_ret, ABOUNCE_FN callback, void *context)
 {
-    abounce_request(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_WARN,
+    abounce_connect(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_WARN,
                    flags, queue, id, encoding, smtputf8, sender, dsn_envid,
-                   dsn_ret, callback, context);
+                   dsn_ret, ABOUNCE_NO_VERP, callback, context);
 }
 
 /* atrace_flush - asynchronous trace flush */
@@ -423,7 +460,7 @@ void    atrace_flush(int flags, const char *queue, const char *id,
                             const char *sender, const char *dsn_envid,
                             int dsn_ret, ABOUNCE_FN callback, void *context)
 {
-    abounce_request(MAIL_CLASS_PRIVATE, var_trace_service, BOUNCE_CMD_TRACE,
+    abounce_connect(MAIL_CLASS_PRIVATE, var_trace_service, BOUNCE_CMD_TRACE,
                    flags, queue, id, encoding, smtputf8, sender, dsn_envid,
-                   dsn_ret, callback, context);
+                   dsn_ret, ABOUNCE_NO_VERP, callback, context);
 }
index 60bcda3ef25d17c45f4943e375f64fa5372a26df..fff9ec7f44b5a8abb9b883957dd74d5c33180fac 100644 (file)
 #define ANVIL_IDENT(service, addr) \
     printable(concatenate(service, ":", addr, (char *) 0), '?')
 
+/* anvil_clnt_handshake - receive server protocol announcement */
+
+static int anvil_clnt_handshake(VSTREAM *stream)
+{
+    return (attr_scan_plain(stream, ATTR_FLAG_STRICT,
+                   RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_ANVIL),
+                           ATTR_TYPE_END));
+}
+
 /* anvil_clnt_create - instantiate connection rate service client */
 
 ANVIL_CLNT *anvil_clnt_create(void)
@@ -186,6 +195,9 @@ ANVIL_CLNT *anvil_clnt_create(void)
 #else
     anvil_clnt = attr_clnt_create(var_anvil_service, var_ipc_timeout, 0, 0);
 #endif
+    attr_clnt_control(anvil_clnt,
+                     ATTR_CLNT_CTL_HANDSHAKE, anvil_clnt_handshake,
+                     ATTR_CLNT_CTL_END);
     return ((ANVIL_CLNT *) anvil_clnt);
 }
 
index 3d782165092bbb0fe0af5e0e793de2e5054b6fd4..b0353075020cd2cbf47ed44537be3427e9e5eaec 100644 (file)
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
@@ -310,6 +315,7 @@ int     bounce_append_intern(int flags, const char *id, MSG_STATS *stats,
 
        if (mail_command_client(MAIL_CLASS_PRIVATE, var_soft_bounce ?
                                var_defer_service : var_bounce_service,
+                               MAIL_ATTR_PROTO_BOUNCE,
                           SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND),
                                SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
                                SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id),
@@ -353,6 +359,7 @@ int     bounce_flush(int flags, const char *queue, const char *id,
     if (var_soft_bounce)
        return (-1);
     if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service,
+                           MAIL_ATTR_PROTO_BOUNCE,
                            SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_FLUSH),
                            SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
                            SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
@@ -387,6 +394,7 @@ int     bounce_flush_verp(int flags, const char *queue, const char *id,
     if (var_soft_bounce)
        return (-1);
     if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service,
+                           MAIL_ATTR_PROTO_BOUNCE,
                            SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_VERP),
                            SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
                            SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
@@ -494,6 +502,7 @@ int     bounce_one_intern(int flags, const char *queue, const char *id,
        my_dsn.action = "failed";
 
        if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service,
+                               MAIL_ATTR_PROTO_BOUNCE,
                              SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_ONE),
                                SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
                                SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
index 2eec1fc8b277911772456b761edad823a2751ed1..ca3ce4f3dc1b35c9b001686ad9f55c1302210fe6 100644 (file)
@@ -6,11 +6,15 @@
 /* SYNOPSIS
 /*     #include <clnt_stream.h>
 /*
-/*     CLNT_STREAM *clnt_stream_create(class, service, timeout, ttl)
+/*     typedef void (*CLNT_STREAM_HANDSHAKE_FN)(VSTREAM *)
+/*
+/*     CLNT_STREAM *clnt_stream_create(class, service, timeout, ttl,
+/*                                             handshake)
 /*     const char *class;
 /*     const char *service;
 /*     int     timeout;
 /*     int     ttl;
+/*     CLNT_STREAM_HANDSHAKE_FN *handshake;
 /*
 /*     VSTREAM *clnt_stream_access(clnt_stream)
 /*     CLNT_STREAM *clnt_stream;
@@ -33,6 +37,8 @@
 /*
 /*     clnt_stream_access() returns an open stream to the service specified
 /*     to clnt_stream_create(). The stream instance may change between calls.
+/*     This function returns null when the handshake function returned an
+/*     error.
 /*
 /*     clnt_stream_recover() recovers from a server-initiated disconnect
 /*     that happened in the middle of an I/O operation.
 /*     Idle time after which the client disconnects.
 /* .IP ttl
 /*     Upper bound on the time that a connection is allowed to persist.
+/* .IP handshake
+/*     Null pointer, or pointer to function that will be called
+/*     at the start of a new connection and that returns 0 in case
+/*     of success.
 /* DIAGNOSTICS
 /*     Warnings: communication failure. Fatal error: mail system is down,
 /*     out of memory.
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
@@ -93,6 +108,7 @@ struct CLNT_STREAM {
     VSTREAM *vstream;                  /* buffered I/O */
     int     timeout;                   /* time before client disconnect */
     int     ttl;                       /* time before client disconnect */
+    CLNT_STREAM_HANDSHAKE_FN handshake;
     char   *class;                     /* server class */
     char   *service;                   /* server name */
 };
@@ -205,6 +221,7 @@ void    clnt_stream_recover(CLNT_STREAM *clnt_stream)
 
 VSTREAM *clnt_stream_access(CLNT_STREAM *clnt_stream)
 {
+    CLNT_STREAM_HANDSHAKE_FN handshake;
 
     /*
      * Open a stream or restart the idle timer.
@@ -213,20 +230,26 @@ VSTREAM *clnt_stream_access(CLNT_STREAM *clnt_stream)
      */
     if (clnt_stream->vstream == 0) {
        clnt_stream_open(clnt_stream);
+       handshake = clnt_stream->handshake;
     } else if (readable(vstream_fileno(clnt_stream->vstream))) {
        clnt_stream_close(clnt_stream);
        clnt_stream_open(clnt_stream);
+       handshake = clnt_stream->handshake;
     } else {
        event_request_timer(clnt_stream_event, (void *) clnt_stream,
                            clnt_stream->timeout);
+       handshake = 0;
     }
+    if (handshake != 0 && handshake(clnt_stream->vstream) != 0)
+       return (0);
     return (clnt_stream->vstream);
 }
 
 /* clnt_stream_create - create client stream connection */
 
 CLNT_STREAM *clnt_stream_create(const char *class, const char *service,
-                                       int timeout, int ttl)
+                                       int timeout, int ttl,
+                                       CLNT_STREAM_HANDSHAKE_FN handshake)
 {
     CLNT_STREAM *clnt_stream;
 
@@ -237,6 +260,7 @@ CLNT_STREAM *clnt_stream_create(const char *class, const char *service,
     clnt_stream->vstream = 0;
     clnt_stream->timeout = timeout;
     clnt_stream->ttl = ttl;
+    clnt_stream->handshake = handshake;
     clnt_stream->class = mystrdup(class);
     clnt_stream->service = mystrdup(service);
     return (clnt_stream);
index 0d3ee4775882a0833e664ea4322798e927af53c2..bb92e2fcc73927f36fe12bc15798982f3119d661 100644 (file)
   * External interface.
   */
 typedef struct CLNT_STREAM CLNT_STREAM;
+typedef int (*CLNT_STREAM_HANDSHAKE_FN)(VSTREAM *);
 
-extern CLNT_STREAM *clnt_stream_create(const char *, const char *, int, int);
+extern CLNT_STREAM *clnt_stream_create(const char *, const char *, int, int,
+                                              CLNT_STREAM_HANDSHAKE_FN);
 extern VSTREAM *clnt_stream_access(CLNT_STREAM *);
+extern const char *clnt_stream_path(CLNT_STREAM *);
 extern void clnt_stream_recover(CLNT_STREAM *);
 extern void clnt_stream_free(CLNT_STREAM *);
 
@@ -35,6 +38,11 @@ extern void clnt_stream_free(CLNT_STREAM *);
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 #endif
index 83e8d14916dee803fda59cd6dbcdadbe4b0133f1..f904ec67731604bbef27206f9f3424f99227d826 100644 (file)
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
@@ -257,6 +262,7 @@ int     defer_append_intern(int flags, const char *id, MSG_STATS *stats,
        my_dsn.action = "delayed";
 
        if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service,
+                               MAIL_ATTR_PROTO_BOUNCE,
                           SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND),
                                SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
                                SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id),
@@ -301,6 +307,7 @@ int     defer_flush(int flags, const char *queue, const char *id,
     flags |= BOUNCE_FLAG_DELRCPT;
 
     if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service,
+                           MAIL_ATTR_PROTO_BOUNCE,
                            SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_FLUSH),
                            SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
                            SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
@@ -325,6 +332,7 @@ int     defer_warn(int flags, const char *queue, const char *id,
                         const char *sender, const char *envid, int dsn_ret)
 {
     if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service,
+                           MAIL_ATTR_PROTO_BOUNCE,
                            SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_WARN),
                            SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
                            SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
index d7945fcd4529a0f92a35c4501c69c550888a2fbd..f744ad533ec2073871871f2eba1b23bdf38a11ea 100644 (file)
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
 
 static int deliver_pass_initial_reply(VSTREAM *stream)
 {
-    int     stat;
-
     if (attr_scan(stream, ATTR_FLAG_STRICT,
-                 RECV_ATTR_INT(MAIL_ATTR_STATUS, &stat),
-                 ATTR_TYPE_END) != 1) {
+                 RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_DELIVER),
+                 ATTR_TYPE_END) != 0) {
        msg_warn("%s: malformed response", VSTREAM_PATH(stream));
-       stat = -1;
+       return (-1);
     }
-    return (stat);
+    return (0);
 }
 
 /* deliver_pass_send_request - send delivery request to delivery process */
index f5c775ab2a26a77dd92952bb83fc486ab4c24401..d5add7873f5116a40679e43e34dcaedaf0c83b86 100644 (file)
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
@@ -135,13 +140,13 @@ static int deliver_request_initial(VSTREAM *stream)
      * delivery request; otherwise the queue manager could block in write().
      */
     if (msg_verbose)
-       msg_info("deliver_request_initial: send initial status");
+       msg_info("deliver_request_initial: send initial response");
     attr_print(stream, ATTR_FLAG_NONE,
-              SEND_ATTR_INT(MAIL_ATTR_STATUS, 0),
+              SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_DELIVER),
               ATTR_TYPE_END);
     if ((err = vstream_fflush(stream)) != 0)
        if (msg_verbose)
-           msg_warn("send initial status: %m");
+           msg_warn("send initial response: %m");
     return (err);
 }
 
index 924c62dcd6b0ecbb2e7114e405c53e9e4caa4a83..5aa915309049cc100f18b364cfd2062a2ead6625 100644 (file)
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
@@ -89,6 +94,15 @@ typedef struct {
 static CLNT_STREAM *proxymap_stream;   /* read-only maps */
 static CLNT_STREAM *proxywrite_stream; /* read-write maps */
 
+/* dict_proxy_handshake - receive server protocol announcement */
+
+static int dict_proxy_handshake(VSTREAM *stream)
+{
+    return (attr_scan(stream, ATTR_FLAG_STRICT,
+                RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_PROXYMAP),
+                     ATTR_TYPE_END));
+}
+
 /* dict_proxy_sequence - find first/next entry */
 
 static int dict_proxy_sequence(DICT *dict, int function,
@@ -118,12 +132,13 @@ static int dict_proxy_sequence(DICT *dict, int function,
        stream = clnt_stream_access(dict_proxy->clnt);
        errno = 0;
        count += 1;
-       if (attr_print(stream, ATTR_FLAG_NONE,
-                      SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_SEQUENCE),
-                      SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
-                      SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
-                      SEND_ATTR_INT(MAIL_ATTR_FUNC, function),
-                      ATTR_TYPE_END) != 0
+       if (stream == 0
+           || attr_print(stream, ATTR_FLAG_NONE,
+                         SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_SEQUENCE),
+                         SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
+                         SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
+                         SEND_ATTR_INT(MAIL_ATTR_FUNC, function),
+                         ATTR_TYPE_END) != 0
            || vstream_fflush(stream)
            || attr_scan(stream, ATTR_FLAG_STRICT,
                         RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
@@ -131,7 +146,7 @@ static int dict_proxy_sequence(DICT *dict, int function,
                         RECV_ATTR_STR(MAIL_ATTR_VALUE, dict_proxy->result),
                         ATTR_TYPE_END) != 3) {
            if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT))
-               msg_warn("%s: service %s: %m", myname, VSTREAM_PATH(stream));
+               msg_warn("%s: service %s: %m", myname, dict_proxy->service);
        } else {
            if (msg_verbose)
                msg_info("%s: table=%s flags=%s func=%d -> status=%d key=%s val=%s",
@@ -196,19 +211,20 @@ static const char *dict_proxy_lookup(DICT *dict, const char *key)
        stream = clnt_stream_access(dict_proxy->clnt);
        errno = 0;
        count += 1;
-       if (attr_print(stream, ATTR_FLAG_NONE,
-                      SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_LOOKUP),
-                      SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
-                      SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
-                      SEND_ATTR_STR(MAIL_ATTR_KEY, key),
-                      ATTR_TYPE_END) != 0
+       if (stream == 0
+           || attr_print(stream, ATTR_FLAG_NONE,
+                         SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_LOOKUP),
+                         SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
+                         SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
+                         SEND_ATTR_STR(MAIL_ATTR_KEY, key),
+                         ATTR_TYPE_END) != 0
            || vstream_fflush(stream)
            || attr_scan(stream, ATTR_FLAG_STRICT,
                         RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
                         RECV_ATTR_STR(MAIL_ATTR_VALUE, dict_proxy->result),
                         ATTR_TYPE_END) != 2) {
            if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT))
-               msg_warn("%s: service %s: %m", myname, VSTREAM_PATH(stream));
+               msg_warn("%s: service %s: %m", myname, dict_proxy->service);
        } else {
            if (msg_verbose)
                msg_info("%s: table=%s flags=%s key=%s -> status=%d result=%s",
@@ -266,19 +282,20 @@ static int dict_proxy_update(DICT *dict, const char *key, const char *value)
        stream = clnt_stream_access(dict_proxy->clnt);
        errno = 0;
        count += 1;
-       if (attr_print(stream, ATTR_FLAG_NONE,
-                      SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_UPDATE),
-                      SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
-                      SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
-                      SEND_ATTR_STR(MAIL_ATTR_KEY, key),
-                      SEND_ATTR_STR(MAIL_ATTR_VALUE, value),
-                      ATTR_TYPE_END) != 0
+       if (stream == 0
+           || attr_print(stream, ATTR_FLAG_NONE,
+                         SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_UPDATE),
+                         SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
+                         SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
+                         SEND_ATTR_STR(MAIL_ATTR_KEY, key),
+                         SEND_ATTR_STR(MAIL_ATTR_VALUE, value),
+                         ATTR_TYPE_END) != 0
            || vstream_fflush(stream)
            || attr_scan(stream, ATTR_FLAG_STRICT,
                         RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
                         ATTR_TYPE_END) != 1) {
            if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT))
-               msg_warn("%s: service %s: %m", myname, VSTREAM_PATH(stream));
+               msg_warn("%s: service %s: %m", myname, dict_proxy->service);
        } else {
            if (msg_verbose)
                msg_info("%s: table=%s flags=%s key=%s value=%s -> status=%d",
@@ -335,19 +352,20 @@ static int dict_proxy_delete(DICT *dict, const char *key)
        stream = clnt_stream_access(dict_proxy->clnt);
        errno = 0;
        count += 1;
-       if (attr_print(stream, ATTR_FLAG_NONE,
-                      SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_DELETE),
-                      SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
-                      SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
-                      SEND_ATTR_STR(MAIL_ATTR_KEY, key),
-                      ATTR_TYPE_END) != 0
+       if (stream == 0
+           || attr_print(stream, ATTR_FLAG_NONE,
+                         SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_DELETE),
+                         SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
+                         SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
+                         SEND_ATTR_STR(MAIL_ATTR_KEY, key),
+                         ATTR_TYPE_END) != 0
            || vstream_fflush(stream)
            || attr_scan(stream, ATTR_FLAG_STRICT,
                         RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
                         ATTR_TYPE_END) != 1) {
            if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno !=
                                             ENOENT))
-               msg_warn("%s: service %s: %m", myname, VSTREAM_PATH(stream));
+               msg_warn("%s: service %s: %m", myname, dict_proxy->service);
        } else {
            if (msg_verbose)
                msg_info("%s: table=%s flags=%s key=%s -> status=%d",
@@ -443,7 +461,8 @@ DICT   *dict_proxy_open(const char *map, int open_flags, int dict_flags)
            prefix = kludge = concatenate(var_queue_dir, "/",
                                          MAIL_CLASS_PRIVATE, (char *) 0);
        *pstream = clnt_stream_create(prefix, service, var_ipc_idle_limit,
-                                     var_ipc_ttl_limit);
+                                     var_ipc_ttl_limit,
+                                     dict_proxy_handshake);
        if (kludge)
            myfree(kludge);
        myfree(relative_path);
@@ -473,18 +492,19 @@ DICT   *dict_proxy_open(const char *map, int open_flags, int dict_flags)
     for (;;) {
        stream = clnt_stream_access(dict_proxy->clnt);
        errno = 0;
-       if (attr_print(stream, ATTR_FLAG_NONE,
-                      SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_OPEN),
-                      SEND_ATTR_STR(MAIL_ATTR_TABLE, dict_proxy->dict.name),
+       if (stream == 0
+           || attr_print(stream, ATTR_FLAG_NONE,
+                         SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_OPEN),
+                     SEND_ATTR_STR(MAIL_ATTR_TABLE, dict_proxy->dict.name),
                     SEND_ATTR_INT(MAIL_ATTR_FLAGS, dict_proxy->inst_flags),
-                      ATTR_TYPE_END) != 0
+                         ATTR_TYPE_END) != 0
            || vstream_fflush(stream)
            || attr_scan(stream, ATTR_FLAG_STRICT,
                         RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
                         RECV_ATTR_INT(MAIL_ATTR_FLAGS, &server_flags),
                         ATTR_TYPE_END) != 2) {
            if (msg_verbose || (errno != EPIPE && errno != ENOENT))
-               msg_warn("%s: service %s: %m", VSTREAM_PATH(stream), myname);
+               msg_warn("%s: service %s: %m", myname, dict_proxy->service);
        } else {
            if (msg_verbose)
                msg_info("%s: connect to map=%s status=%d server_flags=%s",
index 7accaa98abadde8b11bfe7e283351310db492ec6..8084bf5d809a014db5f4db11f4cc9182fe943958 100644 (file)
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
@@ -125,6 +130,7 @@ int     flush_purge(void)
        status = FLUSH_STAT_DENY;
     else
        status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
+                                    MAIL_ATTR_PROTO_FLUSH,
                              SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_PURGE),
                                     ATTR_TYPE_END);
 
@@ -151,6 +157,7 @@ int     flush_refresh(void)
        status = FLUSH_STAT_DENY;
     else
        status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
+                                    MAIL_ATTR_PROTO_FLUSH,
                            SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_REFRESH),
                                     ATTR_TYPE_END);
 
@@ -182,6 +189,7 @@ int     flush_send_site(const char *site)
                     VAR_RELAY_DOMAINS "=$mydestination to flush "
                     "mail for domain \"%s\"", site);
        status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
+                                    MAIL_ATTR_PROTO_FLUSH,
                          SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_SEND_SITE),
                                     SEND_ATTR_STR(MAIL_ATTR_SITE, site),
                                     ATTR_TYPE_END);
@@ -210,6 +218,7 @@ int     flush_send_file(const char *queue_id)
      * Require that the service is turned on.
      */
     status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
+                                MAIL_ATTR_PROTO_FLUSH,
                          SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_SEND_FILE),
                                 SEND_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id),
                                 ATTR_TYPE_END);
@@ -242,6 +251,7 @@ int     flush_add(const char *site, const char *queue_id)
                     VAR_RELAY_DOMAINS "=$mydestination to update "
                     "fast-flush logfile for domain \"%s\"", site);
        status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
+                                    MAIL_ATTR_PROTO_FLUSH,
                                SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_ADD),
                                     SEND_ATTR_STR(MAIL_ATTR_SITE, site),
                                 SEND_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id),
index 2c849d76c4b86a440491cf61178d4accda7e7946..0b40e0268fc11c784746e664ed30b70fdf191226 100644 (file)
@@ -403,7 +403,6 @@ static const char *haproxy_srvr_parse_v2_hdr(const char *str, ssize_t *str_len,
            return ("unsupported network protocol");
        }
        /* For now, skip and ignore TLVs. */
-       *non_proxy = 0;
        *str_len = PP2_HEADER_LEN + ntohs(hdr_v2->len);
        return (0);
 
@@ -434,6 +433,8 @@ const char *haproxy_srvr_parse(const char *str, ssize_t *str_len,
     if (proto_info == 0)
        proto_info = inet_proto_info();
 
+    *non_proxy = 0;
+
     /*
      * XXX We don't accept connections with the "UNKNOWN" protocol type,
      * because those would sidestep address-based access control mechanisms.
@@ -471,7 +472,6 @@ const char *haproxy_srvr_parse(const char *str, ssize_t *str_len,
        }
        myfree(saved_str);
 
-       *non_proxy = 0;
        return (err);
     }
 
index 1817b0329f5627e064c531f148df08a658ac953b..3de116948b5bf486db0f2ea7834938fb79c68bf6 100644 (file)
@@ -6,9 +6,10 @@
 /* SYNOPSIS
 /*     #include <mail_proto.h>
 /*
-/*     int     mail_command_client(class, name, type, attr, ...)
+/*     int     mail_command_client(class, name, proto, type, attr, ...)
 /*     const char *class;
 /*     const char *name;
+/*     const char *proto;
 /*     int     type;
 /*     const char *attr;
 /* DESCRIPTION
@@ -21,6 +22,8 @@
 /*     Service type: MAIL_CLASS_PUBLIC or MAIL_CLASS_PRIVATE
 /* .IP name
 /*     Service name (master.cf).
+/* .IP proto
+/*     The expected protocol name in the server announcement.
 /* .IP "type, attr, ..."
 /*     Attribute information as defined in attr_print(3).
 /* DIAGNOSTICS
@@ -65,7 +68,8 @@
 
 /* mail_command_client - single-command transaction with completion status */
 
-int     mail_command_client(const char *class, const char *name,...)
+int     mail_command_client(const char *class, const char *name,
+                                   const char *proto,...)
 {
     va_list ap;
     VSTREAM *stream;
@@ -82,14 +86,20 @@ int     mail_command_client(const char *class, const char *name,...)
        msg_warn("connect to %s/%s: %m", class, name);
        return (-1);
     }
-    va_start(ap, name);
-    status = attr_vprint(stream, ATTR_FLAG_NONE, ap);
-    va_end(ap);
-    if (status != 0) {
+    if (attr_scan(stream, ATTR_FLAG_STRICT,
+                 RECV_ATTR_STREQ(MAIL_ATTR_PROTO, proto),
+                 ATTR_TYPE_END) != 0) {
+       msg_warn("read %s: %m", VSTREAM_PATH(stream));
+       status = -1;
+    } else if (va_start(ap, proto),
+              (status = attr_vprint(stream, ATTR_FLAG_NONE, ap)),
+              va_end(ap),
+              (status != 0)) {
        msg_warn("write %s: %m", VSTREAM_PATH(stream));
        status = -1;
     } else if (attr_scan(stream, ATTR_FLAG_STRICT,
-                        RECV_ATTR_INT(MAIL_ATTR_STATUS, &status), 0) != 1) {
+                        RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
+                        ATTR_TYPE_END) != 1) {
        msg_warn("write/read %s: %m", VSTREAM_PATH(stream));
        status = -1;
     }
index a45466213c43a43004c2f37d836d1c14128f868a..3ffe1fcbd58ae7f0c4951fd11bacf373617499a9 100644 (file)
   */
 extern VSTREAM *mail_connect(const char *, const char *, int);
 extern VSTREAM *mail_connect_wait(const char *, const char *);
-extern int mail_command_client(const char *, const char *,...);
+extern int mail_command_client(const char *, const char *, const char *,...);
 extern int mail_command_server(VSTREAM *,...);
 extern int mail_trigger(const char *, const char *, const char *, ssize_t);
 extern char *mail_pathname(const char *, const char *);
 
+ /*
+  * Each Postfix internal service identifies the protocol that it intends to
+  * use. On the receiver end, this information does not contribute to the
+  * reported number of received attributes (it is a constant).
+  */
+#define MAIL_ATTR_PROTO                "protocol"
+
+#define MAIL_ATTR_PROTO_ANVIL  "anvil_protocol"
+#define MAIL_ATTR_PROTO_BOUNCE "delivery_status_protocol"
+#define MAIL_ATTR_PROTO_CLEANUP        "cleanup_protocol"
+#define MAIL_ATTR_PROTO_DELIVER        "delivery_request_protocol"
+#define MAIL_ATTR_PROTO_FLUSH  "queue_flush_protocol"
+#define MAIL_ATTR_PROTO_POSTDROP "postdrop_protocol"
+#define MAIL_ATTR_PROTO_PROXYMAP "proxymap_protocol"
+#define MAIL_ATTR_PROTO_SCACHE "connection_cache_protocol"
+#define MAIL_ATTR_PROTO_SHOWQ  "mail_queue_list_protocol"
+#define MAIL_ATTR_PROTO_TLSMGR "tlsmgr_protocol"
+#define MAIL_ATTR_PROTO_TLSPROXY "tlsproxy_protocol"
+#define MAIL_ATTR_PROTO_TRIVIAL        "trivial_rewrite_protocol"
+#define MAIL_ATTR_PROTO_VERIFY "address_verification_prrotocol"
+
  /*
   * Attribute names.
   */
index a98d3ad81e3f835b33e9fe24cdbb28b98c90cae7..90a1ee0845d71b732646ce9df5ed7b905883926e 100644 (file)
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
@@ -440,7 +445,8 @@ MAIL_STREAM *mail_stream_service(const char *class, const char *name)
        id_buf = vstring_alloc(10);
 
     stream = mail_connect_wait(class, name);
-    if (attr_scan(stream, ATTR_FLAG_MISSING,
+    if (attr_scan(stream, ATTR_FLAG_STRICT,
+                 RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP),
                  RECV_ATTR_STR(MAIL_ATTR_QUEUEID, id_buf), 0) != 1) {
        vstream_fclose(stream);
        return (0);
@@ -492,7 +498,8 @@ MAIL_STREAM *mail_stream_command(const char *command)
                    CA_VSTREAM_CTL_PATH(command),
                    CA_VSTREAM_CTL_END);
 
-    if (attr_scan(stream, ATTR_FLAG_MISSING,
+    if (attr_scan(stream, ATTR_FLAG_STRICT,
+                 RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_POSTDROP),
                  RECV_ATTR_STR(MAIL_ATTR_QUEUEID, id_buf), 0) != 1) {
        if ((status = vstream_pclose(stream)) != 0)
            msg_warn("command \"%s\" exited with status %d", command, status);
index 6605b50433af7fffed2a6609506c1387399455bc..f6ce1d215f637c910ed31fa1006ff02e193470c2 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20200830"
+#define MAIL_RELEASE_DATE      "20200920"
 #define MAIL_VERSION_NUMBER    "3.6"
 
 #ifdef SNAPSHOT
index 1fecf3f64d796077d463b14d28d13120dd5da780..e7a9a674681ec22002c1be15b29184f9dd57b564 100644 (file)
@@ -231,8 +231,18 @@ static void post_mail_init(VSTREAM *stream, const char *sender,
     date = mail_date(now.tv_sec);
 
     /*
-     * XXX Don't flush buffers while sending the initial message records.
-     * That would cause deadlock between verify(8) and cleanup(8) servers.
+     * The comment in the next paragraph is likely obsolete. Fix 20030610
+     * changed the verify server to use asynchronous submission of mail
+     * probes, to avoid blocking the post_mail client for in_flow_delay
+     * seconds when the cleanup service receives email messages faster than
+     * they are delivered. Instead, the post_mail client waits until the
+     * cleanup server announces its availability to receive input. A similar
+     * change was made at the end of submission, to avoid blocking the
+     * post_mail client for up to trigger_timeout seconds when the cleanup
+     * server attempts to notify a queue manager that is overwhelmed.
+     * 
+     * XXX Don't flush buffers while sending the initial message records. That
+     * would cause deadlock between verify(8) and cleanup(8) servers.
      */
     vstream_control(stream, VSTREAM_CTL_BUFSIZE, 2 * VSTREAM_BUFSIZE,
                    VSTREAM_CTL_END);
@@ -241,6 +251,7 @@ static void post_mail_init(VSTREAM *stream, const char *sender,
      * Negotiate with the cleanup service. Give up if we can't agree.
      */
     if (attr_scan(stream, ATTR_FLAG_STRICT,
+                 RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP),
                  RECV_ATTR_STR(MAIL_ATTR_QUEUEID, id),
                  ATTR_TYPE_END) != 1
        || attr_print(stream, ATTR_FLAG_NONE,
index 859469394ba33d94f6c60da8930928be2512ffda..ccd67b2397c85e9d6c42cb2b1e9459305f420f63 100644 (file)
@@ -152,6 +152,15 @@ void    resolve_clnt_init(RESOLVE_REPLY *reply)
     reply->flags = 0;
 }
 
+/* resolve_clnt_handshake - receive server protocol announcement */
+
+static int resolve_clnt_handshake(VSTREAM *stream)
+{
+    return (attr_scan(stream, ATTR_FLAG_STRICT,
+                 RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TRIVIAL),
+                     ATTR_TYPE_END));
+}
+
 /* resolve_clnt - resolve address to (transport, next hop, recipient) */
 
 void    resolve_clnt(const char *class, const char *sender,
@@ -219,17 +228,19 @@ void    resolve_clnt(const char *class, const char *sender,
        rewrite_clnt_stream = clnt_stream_create(MAIL_CLASS_PRIVATE,
                                                 var_rewrite_service,
                                                 var_ipc_idle_limit,
-                                                var_ipc_ttl_limit);
+                                                var_ipc_ttl_limit,
+                                                resolve_clnt_handshake);
 
     for (;;) {
        stream = clnt_stream_access(rewrite_clnt_stream);
        errno = 0;
        count += 1;
-       if (attr_print(stream, ATTR_FLAG_NONE,
-                      SEND_ATTR_STR(MAIL_ATTR_REQ, class),
-                      SEND_ATTR_STR(MAIL_ATTR_SENDER, sender),
-                      SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),
-                      ATTR_TYPE_END) != 0
+       if (stream == 0
+           || attr_print(stream, ATTR_FLAG_NONE,
+                         SEND_ATTR_STR(MAIL_ATTR_REQ, class),
+                         SEND_ATTR_STR(MAIL_ATTR_SENDER, sender),
+                         SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),
+                         ATTR_TYPE_END) != 0
            || vstream_fflush(stream)
            || attr_scan(stream, ATTR_FLAG_STRICT,
                         RECV_ATTR_INT(MAIL_ATTR_FLAGS, &server_flags),
index e11f81a4ab51bacdf91cc5c0e9ec4340e930aea7..420c778d29449fe6580267b52db081e1b8c84e4b 100644 (file)
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
@@ -77,6 +82,15 @@ static VSTRING *last_rule;
 static VSTRING *last_addr;
 static VSTRING *last_result;
 
+/* rewrite_clnt_handshake - receive server protocol announcement */
+
+static int rewrite_clnt_handshake(VSTREAM *stream)
+{
+    return (attr_scan(stream, ATTR_FLAG_STRICT,
+                 RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TRIVIAL),
+                     ATTR_TYPE_END));
+}
+
 /* rewrite_clnt - rewrite address to (transport, next hop, recipient) */
 
 VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result)
@@ -127,17 +141,19 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result)
        rewrite_clnt_stream = clnt_stream_create(MAIL_CLASS_PRIVATE,
                                                 var_rewrite_service,
                                                 var_ipc_idle_limit,
-                                                var_ipc_ttl_limit);
+                                                var_ipc_ttl_limit,
+                                                rewrite_clnt_handshake);
 
     for (;;) {
        stream = clnt_stream_access(rewrite_clnt_stream);
        errno = 0;
        count += 1;
-       if (attr_print(stream, ATTR_FLAG_NONE,
-                      SEND_ATTR_STR(MAIL_ATTR_REQ, REWRITE_ADDR),
-                      SEND_ATTR_STR(MAIL_ATTR_RULE, rule),
-                      SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),
-                      ATTR_TYPE_END) != 0
+       if (stream == 0
+           || attr_print(stream, ATTR_FLAG_NONE,
+                         SEND_ATTR_STR(MAIL_ATTR_REQ, REWRITE_ADDR),
+                         SEND_ATTR_STR(MAIL_ATTR_RULE, rule),
+                         SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),
+                         ATTR_TYPE_END) != 0
            || vstream_fflush(stream)
            || attr_scan(stream, ATTR_FLAG_STRICT,
                         RECV_ATTR_INT(MAIL_ATTR_FLAGS, &server_flags),
index b67c3051e7742a24fb25663a9562cce3fc5f894f..bbc34966bd8208b2356ccd796d3cb065e253f5fa 100644 (file)
@@ -68,7 +68,7 @@
 /* sasl_mech_filter - filter a SASL mechanism list */
 
 const char *sasl_mech_filter(STRING_LIST *filter,
-                                    const const char *words)
+                                    const char *words)
 {
     const char myname[] = "sasl_mech_filter";
     static VSTRING *buf;
index 536053234d06e80f3da33c3f817d28686cdd12d4..97fe8aa283e820da7acc67a93f695f5cc0dde287 100644 (file)
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
@@ -80,6 +85,15 @@ typedef struct {
 
 #define SCACHE_MAX_TRIES       2
 
+/* scache_clnt_handshake - receive server protocol announcement */
+
+static int scache_clnt_handshake(VSTREAM *stream)
+{
+    return (attr_scan(stream, ATTR_FLAG_STRICT,
+                  RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_SCACHE),
+                     ATTR_TYPE_END));
+}
+
 /* scache_clnt_save_endp - save endpoint */
 
 static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl,
@@ -414,8 +428,11 @@ SCACHE *scache_clnt_create(const char *server, int timeout,
     sp->scache->size = scache_clnt_size;
     sp->scache->free = scache_clnt_free;
 
-    service = concatenate("local:private/", server, (char *) 0);
+    service = concatenate("local:" MAIL_CLASS_PRIVATE "/", server, (char *) 0);
     sp->auto_clnt = auto_clnt_create(service, timeout, idle_limit, ttl_limit);
+    auto_clnt_control(sp->auto_clnt,
+                     AUTO_CLNT_CTL_HANDSHAKE, scache_clnt_handshake,
+                     AUTO_CLNT_CTL_END);
     myfree(service);
 
 #ifdef CANT_WRITE_BEFORE_SENDING_FD
index d451b4f457b89e44433b3163dcd038c6ee6713c2..22bdefe8b39dde7dea990c5eadd8d61354c22b12 100644 (file)
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
@@ -121,6 +126,7 @@ int     trace_append(int flags, const char *id, MSG_STATS *stats,
     my_dsn.reason = vstring_str(why);
 
     if (mail_command_client(MAIL_CLASS_PRIVATE, var_trace_service,
+                           MAIL_ATTR_PROTO_BOUNCE,
                            SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND),
                            SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
                            SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id),
@@ -145,6 +151,7 @@ int     trace_flush(int flags, const char *queue, const char *id,
                            const char *dsn_envid, int dsn_ret)
 {
     if (mail_command_client(MAIL_CLASS_PRIVATE, var_trace_service,
+                           MAIL_ATTR_PROTO_BOUNCE,
                            SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_TRACE),
                            SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
                            SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
index 131ca1cc7776bc7649f2f6e35800e264c7520856..bda4eb0b303a2fd5e5f645bbf5e8164bd2797ad1 100644 (file)
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
 
 CLNT_STREAM *vrfy_clnt;
 
+/* verify_clnt_handshake - receive server protocol announcement */
+
+static int verify_clnt_handshake(VSTREAM *stream)
+{
+    return (attr_scan(stream, ATTR_FLAG_STRICT,
+                  RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_VERIFY),
+                     ATTR_TYPE_END));
+}
+
 /* verify_clnt_init - initialize */
 
 static void verify_clnt_init(void)
@@ -87,7 +101,8 @@ static void verify_clnt_init(void)
     if (vrfy_clnt != 0)
        msg_panic("verify_clnt_init: multiple initialization");
     vrfy_clnt = clnt_stream_create(MAIL_CLASS_PRIVATE, var_verify_service,
-                                  var_ipc_idle_limit, var_ipc_ttl_limit);
+                                  var_ipc_idle_limit, var_ipc_ttl_limit,
+                                  verify_clnt_handshake);
 }
 
 /* verify_clnt_query - request address verification status */
@@ -111,10 +126,11 @@ int     verify_clnt_query(const char *addr, int *addr_status, VSTRING *why)
        stream = clnt_stream_access(vrfy_clnt);
        errno = 0;
        count += 1;
-       if (attr_print(stream, ATTR_FLAG_NONE,
-                      SEND_ATTR_STR(MAIL_ATTR_REQ, VRFY_REQ_QUERY),
-                      SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),
-                      ATTR_TYPE_END) != 0
+       if (stream == 0
+           || attr_print(stream, ATTR_FLAG_NONE,
+                         SEND_ATTR_STR(MAIL_ATTR_REQ, VRFY_REQ_QUERY),
+                         SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),
+                         ATTR_TYPE_END) != 0
            || vstream_fflush(stream)
            || attr_scan(stream, ATTR_FLAG_MISSING,
                         RECV_ATTR_INT(MAIL_ATTR_STATUS, &request_status),
@@ -153,12 +169,13 @@ int     verify_clnt_update(const char *addr, int addr_status, const char *why)
     for (;;) {
        stream = clnt_stream_access(vrfy_clnt);
        errno = 0;
-       if (attr_print(stream, ATTR_FLAG_NONE,
-                      SEND_ATTR_STR(MAIL_ATTR_REQ, VRFY_REQ_UPDATE),
-                      SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),
-                      SEND_ATTR_INT(MAIL_ATTR_ADDR_STATUS, addr_status),
-                      SEND_ATTR_STR(MAIL_ATTR_WHY, why),
-                      ATTR_TYPE_END) != 0
+       if (stream == 0
+           || attr_print(stream, ATTR_FLAG_NONE,
+                         SEND_ATTR_STR(MAIL_ATTR_REQ, VRFY_REQ_UPDATE),
+                         SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),
+                         SEND_ATTR_INT(MAIL_ATTR_ADDR_STATUS, addr_status),
+                         SEND_ATTR_STR(MAIL_ATTR_WHY, why),
+                         ATTR_TYPE_END) != 0
            || attr_scan(stream, ATTR_FLAG_MISSING,
                         RECV_ATTR_INT(MAIL_ATTR_STATUS, &request_status),
                         ATTR_TYPE_END) != 1) {
index 14367af014a3dff16d30d5037ecf67a4e9565334..722dcf7126b33a8940f4d1e046ac9ce3deb18aa0 100644 (file)
@@ -146,6 +146,7 @@ static FORWARD_INFO *forward_open(DELIVER_REQUEST *request, const char *sender)
     }
     close_on_exec(vstream_fileno(cleanup), CLOSE_ON_EXEC);
     if (attr_scan(cleanup, ATTR_FLAG_STRICT,
+                 RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP),
                  RECV_ATTR_STR(MAIL_ATTR_QUEUEID, buffer),
                  ATTR_TYPE_END) != 1) {
        vstream_fclose(cleanup);
index 0e750c0d9f4319d239ad402fb4d86df770750db2..9f81fc672da2526f69d205f8463155562b6aab29 100644 (file)
@@ -273,7 +273,6 @@ static unsigned event_server_generation;
 static void (*event_server_pre_disconn) (VSTREAM *, char *, char **);
 static void (*event_server_slow_exit) (char *, char **);
 static int event_server_watchdog = 1000;
-static int event_server_saved_flags;
 
 /* event_server_exit - normal termination */
 
@@ -373,8 +372,7 @@ void    event_server_disconnect(VSTREAM *stream)
 static void event_server_execute(int unused_event, void *context)
 {
     VSTREAM *stream = (VSTREAM *) context;
-    HTABLE *attr = (vstream_flags(stream) == event_server_saved_flags ?
-                   (HTABLE *) vstream_context(stream) : 0);
+    HTABLE *attr = (HTABLE *) vstream_context(stream);
 
     if (event_server_lock != 0
        && myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK,
@@ -432,7 +430,6 @@ static void event_server_wakeup(int fd, HTABLE *attr)
                    CA_VSTREAM_CTL_END);
     myfree(tmp);
     timed_ipc_setup(stream);
-    event_server_saved_flags = vstream_flags(stream);
     if (event_server_in_flow_delay && mail_flow_get(1) < 0)
        event_request_timer(event_server_execute, (void *) stream,
                            var_in_flow_delay);
index 7300b3f01047021e8e34b4199a0aa6fe85694e7c..93703daf7517257824245571da1ec0cb734e930b 100644 (file)
@@ -12,6 +12,7 @@
   * Utility library.
   */
 #include <vstream.h>
+#include <htable.h>
 
  /*
   * Global library.
 #define MAIL_SERVER_SLOW_EXIT  21
 #define MAIL_SERVER_BOUNCE_INIT        22
 #define MAIL_SERVER_RETIRE_ME  23
+#define MAIL_SERVER_POST_ACCEPT        24
 
 typedef void (*MAIL_SERVER_INIT_FN) (char *, char **);
 typedef int (*MAIL_SERVER_LOOP_FN) (char *, char **);
 typedef void (*MAIL_SERVER_EXIT_FN) (char *, char **);
 typedef void (*MAIL_SERVER_ACCEPT_FN) (char *, char **);
+typedef void (*MAIL_SERVER_POST_ACCEPT_FN) (VSTREAM *, char *, char **, HTABLE *);
 typedef void (*MAIL_SERVER_DISCONN_FN) (VSTREAM *, char *, char **);
 typedef void (*MAIL_SERVER_SLOW_EXIT_FN) (char *, char **);
 
@@ -67,6 +70,7 @@ typedef void (*MAIL_SERVER_SLOW_EXIT_FN) (char *, char **);
 #define CA_MAIL_SERVER_LOOP(v)         MAIL_SERVER_LOOP, CHECK_VAL(MAIL_SERVER, MAIL_SERVER_LOOP_FN, (v))
 #define CA_MAIL_SERVER_EXIT(v)         MAIL_SERVER_EXIT, CHECK_VAL(MAIL_SERVER, MAIL_SERVER_EXIT_FN, (v))
 #define CA_MAIL_SERVER_PRE_ACCEPT(v)   MAIL_SERVER_PRE_ACCEPT, CHECK_VAL(MAIL_SERVER, MAIL_SERVER_ACCEPT_FN, (v))
+#define CA_MAIL_SERVER_POST_ACCEPT(v)  MAIL_SERVER_POST_ACCEPT, CHECK_VAL(MAIL_SERVER, MAIL_SERVER_POST_ACCEPT_FN, (v))
 #define CA_MAIL_SERVER_SOLITARY        MAIL_SERVER_SOLITARY
 #define CA_MAIL_SERVER_UNLIMITED       MAIL_SERVER_UNLIMITED
 #define CA_MAIL_SERVER_PRE_DISCONN(v)  MAIL_SERVER_PRE_DISCONN, CHECK_VAL(MAIL_SERVER, MAIL_SERVER_DISCONN_FN, (v))
@@ -83,6 +87,7 @@ CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_INIT_FN);
 CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_EXIT_FN);
 CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_DISCONN_FN);
 CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_ACCEPT_FN);
+CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_POST_ACCEPT_FN);
 CHECK_PTR_HELPER_DCL(MAIL_SERVER, int);
 CHECK_PTR_HELPER_DCL(MAIL_SERVER, char);
 CHECK_PPTR_HELPER_DCL(MAIL_SERVER, char);
index 465a9e26ffd26f00894f92b9597a585701dc8b7f..fbdaf34cef3d71437dcc1e56634956a366f5b134 100644 (file)
@@ -35,9 +35,6 @@
 /*     function is run after the program has optionally dropped its
 /*     privileges. This function should not attempt to preserve state
 /*     across calls. The stream initial state is non-blocking mode.
-/*     Optional connection attributes are provided as a hash that
-/*     is attached as stream context. NOTE: the attributes are
-/*     destroyed after this function is called.
 /*     The service name argument corresponds to the service name in the
 /*     master.cf file.
 /*     The argv argument specifies command-line arguments left over
 /*     Function to be executed prior to accepting a new connection.
 /* .sp
 /*     Only the last instance of this parameter type is remembered.
+/* .IP "CA_MAIL_SERVER_POST_ACCEPT(void *(VSTREAM *stream, char *service_name, char **argv, HTABLE *attr))"
+/*     Function to be executed after accepting a new connection.
+/*     The stream, service_name and argv argunents are the same
+/*     as with the "service" argument. The attr argument is null
+/*     or a pointer to a table with 'pass' connection attributes.
+/*     The table is destroyed after the function returns.
+/* .sp
+/*     Only the last instance of this parameter type is remembered.
 /* .IP "CA_MAIL_SERVER_PRE_DISCONN(VSTREAM *, char *service_name, char **argv)"
 /*     A pointer to a function that is called
 /*     by the multi_server_disconnect() function (see below).
@@ -250,11 +255,11 @@ static char **multi_server_argv;
 static void (*multi_server_accept) (int, void *);
 static void (*multi_server_onexit) (char *, char **);
 static void (*multi_server_pre_accept) (char *, char **);
+static void (*multi_server_post_accept) (VSTREAM *, char *, char **, HTABLE *);
 static VSTREAM *multi_server_lock;
 static int multi_server_in_flow_delay;
 static unsigned multi_server_generation;
 static void (*multi_server_pre_disconn) (VSTREAM *, char *, char **);
-static int multi_server_saved_flags;
 
 /* multi_server_exit - normal termination */
 
@@ -336,8 +341,6 @@ void    multi_server_disconnect(VSTREAM *stream)
 static void multi_server_execute(int unused_event, void *context)
 {
     VSTREAM *stream = (VSTREAM *) context;
-    HTABLE *attr = (vstream_flags(stream) == multi_server_saved_flags ?
-                   (HTABLE *) vstream_context(stream) : 0);
 
     if (multi_server_lock != 0
        && myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
@@ -358,8 +361,6 @@ static void multi_server_execute(int unused_event, void *context)
     } else {
        multi_server_disconnect(stream);
     }
-    if (attr)
-       htable_free(attr, myfree);
 }
 
 /* multi_server_enable_read - enable read events */
@@ -404,16 +405,20 @@ static void multi_server_wakeup(int fd, HTABLE *attr)
     tmp = concatenate(multi_server_name, " socket", (char *) 0);
     vstream_control(stream,
                    CA_VSTREAM_CTL_PATH(tmp),
-                   CA_VSTREAM_CTL_CONTEXT((void *) attr),
                    CA_VSTREAM_CTL_END);
     myfree(tmp);
     timed_ipc_setup(stream);
-    multi_server_saved_flags = vstream_flags(stream);
     if (multi_server_in_flow_delay && mail_flow_get(1) < 0)
        event_request_timer(multi_server_enable_read, (void *) stream,
                            var_in_flow_delay);
     else
        multi_server_enable_read(0, (void *) stream);
+    if (multi_server_post_accept)
+       multi_server_post_accept(stream, multi_server_name, multi_server_argv, attr);
+    else if (attr)
+       msg_warn("service ignores 'pass' connection attributes");
+    if (attr)
+       htable_free(attr, myfree);
 }
 
 /* multi_server_accept_local - accept client connection request */
@@ -746,6 +751,9 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
        case MAIL_SERVER_PRE_ACCEPT:
            multi_server_pre_accept = va_arg(ap, MAIL_SERVER_ACCEPT_FN);
            break;
+       case MAIL_SERVER_POST_ACCEPT:
+           multi_server_post_accept = va_arg(ap, MAIL_SERVER_POST_ACCEPT_FN);
+           break;
        case MAIL_SERVER_PRE_DISCONN:
            multi_server_pre_disconn = va_arg(ap, MAIL_SERVER_DISCONN_FN);
            break;
index d8ec7bb00accf9ead847f10408424814243ef3c9..16fbc9e2a3f13e3877f32261ae27d7b2703f8ba6 100644 (file)
@@ -109,12 +109,12 @@ static int qmgr_deliver_initial_reply(VSTREAM *stream)
        msg_warn("%s: premature disconnect", VSTREAM_PATH(stream));
        return (DELIVER_STAT_CRASH);
     } else if (attr_scan(stream, ATTR_FLAG_STRICT,
-                        RECV_ATTR_INT(MAIL_ATTR_STATUS, &stat),
-                        ATTR_TYPE_END) != 1) {
+                 RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_DELIVER),
+                        ATTR_TYPE_END) != 0) {
        msg_warn("%s: malformed response", VSTREAM_PATH(stream));
-       return (DELIVER_STAT_CRASH);
+       return (DELIVER_STAT_DEFER);
     } else {
-       return (stat ? DELIVER_STAT_DEFER : 0);
+       return (0);
     }
 }
 
index 157970dbd795c393bc16adb0cd3d3b759302006a..4a77a476e51010bb696ad7ebb299fee4a17eb3be 100644 (file)
@@ -488,6 +488,7 @@ static int pickup_file(PICKUP_INFO *info)
 
     cleanup = mail_connect_wait(MAIL_CLASS_PUBLIC, var_cleanup_service);
     if (attr_scan(cleanup, ATTR_FLAG_STRICT,
+                 RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP),
                  RECV_ATTR_STR(MAIL_ATTR_QUEUEID, buf),
                  ATTR_TYPE_END) != 1
        || attr_print(cleanup, ATTR_FLAG_NONE,
index dc382fe1f7a6d105415abe554e5b1cf8ebca3f8f..33598bc023e8f2c2c6434db7aacdfb5d40fd7329 100644 (file)
@@ -9,8 +9,8 @@ OBJS    = postconf.o postconf_builtin.o postconf_edit.o postconf_main.o \
        postconf_lookup.o postconf_match.o postconf_print.o
 HDRS   = postconf.h
 TESTSRC        =
-DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
-CFLAGS = $(DEBUG) $(OPT) $(DEFS) -DLEGACY_DBMS_SUPPORT
+DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE) -DLEGACY_DBMS_SUPPORT
+CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG=
 MAKES  = bool_table.h bool_vars.h int_table.h int_vars.h str_table.h \
        str_vars.h time_table.h time_vars.h raw_table.h raw_vars.h \
index ca7846431f3fafffbd31ae4421814af07618b55b..7f32c95f27d514eb0baf3cb044bc84dd0a8a7f74 100644 (file)
@@ -381,6 +381,7 @@ int     main(int argc, char **argv)
     dst = mail_stream_file(MAIL_QUEUE_MAILDROP, MAIL_CLASS_PUBLIC,
                           var_pickup_service, 0444);
     attr_print(VSTREAM_OUT, ATTR_FLAG_NONE,
+              SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_POSTDROP),
               SEND_ATTR_STR(MAIL_ATTR_QUEUEID, dst->id),
               ATTR_TYPE_END);
     vstream_fflush(VSTREAM_OUT);
index bdf7d050f841a0b9ad4f500fa6828835d1bf1676..21fad76dd8566c0c928bce5c552b40adf03b2807 100644 (file)
@@ -61,14 +61,19 @@ depend: $(MAKES)
 
 # do not edit below this line - it is generated by 'make depend'
 postlogd.o: ../../include/check_arg.h
+postlogd.o: ../../include/htable.h
 postlogd.o: ../../include/logwriter.h
 postlogd.o: ../../include/mail_conf.h
 postlogd.o: ../../include/mail_params.h
 postlogd.o: ../../include/mail_server.h
+postlogd.o: ../../include/mail_task.h
 postlogd.o: ../../include/mail_version.h
+postlogd.o: ../../include/maillog_client.h
 postlogd.o: ../../include/msg.h
 postlogd.o: ../../include/msg_logger.h
+postlogd.o: ../../include/stringops.h
 postlogd.o: ../../include/sys_defs.h
 postlogd.o: ../../include/vbuf.h
 postlogd.o: ../../include/vstream.h
+postlogd.o: ../../include/vstring.h
 postlogd.o: postlogd.c
diff --git a/postfix/src/postqueue/.indent.pro b/postfix/src/postqueue/.indent.pro
new file mode 120000 (symlink)
index 0000000..5c837ec
--- /dev/null
@@ -0,0 +1 @@
+../../.indent.pro
\ No newline at end of file
index 7efc01ff975b07e2ad3732d3715864d75e8ae324..937176383f04bba56670faf5086771f107fefae6 100644 (file)
@@ -341,6 +341,26 @@ static const CONFIG_STR_TABLE str_table[] = {
     0,
 };
 
+/* showq_client - run the appropriate showq protocol client */
+
+static void showq_client(int mode, VSTREAM *showq)
+{
+    if (attr_scan(showq, ATTR_FLAG_STRICT,
+                 RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_SHOWQ),
+                 ATTR_TYPE_END) != 0)
+       msg_fatal_status(EX_SOFTWARE, "malformed showq server response");
+    switch (mode) {
+    case PQ_MODE_MAILQ_LIST:
+       showq_compat(showq);
+       break;
+    case PQ_MODE_JSON_LIST:
+       showq_json(showq);
+       break;
+    default:
+       msg_panic("show_queue: unknown mode %d", mode);
+    }
+}
+
 /* show_queue - show queue status */
 
 static void show_queue(int mode)
@@ -361,16 +381,7 @@ static void show_queue(int mode)
      * Connect to the show queue service.
      */
     if ((showq = mail_connect(MAIL_CLASS_PUBLIC, var_showq_service, BLOCKING)) != 0) {
-       switch (mode) {
-       case PQ_MODE_MAILQ_LIST:
-           showq_compat(showq);
-           break;
-       case PQ_MODE_JSON_LIST:
-           showq_json(showq);
-           break;
-       default:
-           msg_panic("show_queue: unknown mode %d", mode);
-       }
+       showq_client(mode, showq);
        if (vstream_fclose(showq))
            msg_warn("close: %m");
     }
@@ -407,23 +418,14 @@ static void show_queue(int mode)
                                   CA_VSTREAM_POPEN_END)) == 0) {
            stat = -1;
        } else {
-           switch (mode) {
-           case PQ_MODE_MAILQ_LIST:
-               showq_compat(showq);
-               break;
-           case PQ_MODE_JSON_LIST:
-               showq_json(showq);
-               break;
-           default:
-               msg_panic("show_queue: unknown mode %d", mode);
-           }
+           showq_client(mode, showq);
            stat = vstream_pclose(showq);
        }
        argv_free(argv);
+       myfree(showq_path);
        if (stat != 0)
            msg_fatal_status(stat < 0 ? EX_OSERR : EX_SOFTWARE,
                             "Error running %s", showq_path);
-       myfree(showq_path);
     }
 
     /*
index 3056d7130b94a7198758e9242b7721f4a6fc9eae..67dd3c1e1b5a0a166023d56e08a6c5ae023e0f2d 100644 (file)
@@ -88,6 +88,22 @@ typedef struct {
 
 static char *psc_tlsp_service = 0;
 
+/* Resume the dummy SMTP engine after an event handling error */
+
+#define PSC_STARTTLS_EVENT_ERR_RESUME_RETURN() do { \
+       event_disable_readwrite(vstream_fileno(tlsproxy_stream)); \
+       PSC_STARTTLS_EVENT_RESUME_RETURN(starttls_state); \
+    } while (0);
+
+/* Resume the dummy SMTP engine, possibly after swapping streams */
+
+#define PSC_STARTTLS_EVENT_RESUME_RETURN(starttls_state) do { \
+       vstream_fclose(tlsproxy_stream); \
+       starttls_state->resume_event(event, (void *) smtp_state); \
+       myfree((void *) starttls_state); \
+       return; \
+    } while (0)
+
 /* psc_starttls_finish - complete negotiation with TLS proxy */
 
 static void psc_starttls_finish(int event, void *context)
@@ -130,10 +146,11 @@ static void psc_starttls_finish(int event, void *context)
         * The TLS proxy reports that the TLS engine is not available (due to
         * configuration error, or other causes).
         */
-       event_disable_readwrite(vstream_fileno(tlsproxy_stream));
-       vstream_fclose(tlsproxy_stream);
+       msg_warn("%s receiving status from %s service",
+            event == EVENT_TIME ? "timeout" : "problem", psc_tlsp_service);
        PSC_SEND_REPLY(smtp_state,
                    "454 4.7.0 TLS not available due to local problem\r\n");
+       PSC_STARTTLS_EVENT_ERR_RESUME_RETURN();
     }
 
     /*
@@ -145,13 +162,10 @@ static void psc_starttls_finish(int event, void *context)
        /*
         * Some error: drop the TLS proxy stream.
         */
-       msg_warn("%s sending file handle to %s service",
-                event == EVENT_TIME ? "timeout" : "problem",
-                psc_tlsp_service);
-       event_disable_readwrite(vstream_fileno(tlsproxy_stream));
-       vstream_fclose(tlsproxy_stream);
+       msg_warn("problem sending file handle to %s service", psc_tlsp_service);
        PSC_SEND_REPLY(smtp_state,
                    "454 4.7.0 TLS not available due to local problem\r\n");
+       PSC_STARTTLS_EVENT_ERR_RESUME_RETURN();
     }
 
     /*
@@ -163,9 +177,10 @@ static void psc_starttls_finish(int event, void *context)
        PSC_SEND_REPLY(smtp_state, "220 2.0.0 Ready to start TLS\r\n");
 
        /*
-        * Replace our SMTP client stream by the TLS proxy stream.  Once the
-        * TLS handshake is done, the TLS proxy will deliver plaintext SMTP
-        * commands to postscreen(8).
+        * Swap the SMTP client stream and the TLS proxy stream, and close
+        * the direct connection to the SMTP client. The TLS proxy will talk
+        * directly to the SMTP client, and once the TLS handshake is
+        * completed, the TLS proxy will talk plaintext to postscreen(8).
         * 
         * Swap the file descriptors from under the VSTREAM so that we don't
         * have to worry about loss of user-configurable VSTREAM attributes.
@@ -174,15 +189,83 @@ static void psc_starttls_finish(int event, void *context)
        vstream_control(smtp_state->smtp_client_stream,
                        CA_VSTREAM_CTL_SWAP_FD(tlsproxy_stream),
                        CA_VSTREAM_CTL_END);
-       vstream_fclose(tlsproxy_stream);        /* direct-to-client stream! */
        smtp_state->flags |= PSC_STATE_FLAG_USING_TLS;
+       PSC_STARTTLS_EVENT_RESUME_RETURN(starttls_state);
     }
+}
+
+/* psc_starttls_first - start negotiation with TLS proxy */
+
+static void psc_starttls_first(int event, void *context)
+{
+    const char *myname = "psc_starttls_first";
+    PSC_STARTTLS *starttls_state = (PSC_STARTTLS *) context;
+    PSC_STATE *smtp_state = starttls_state->smtp_state;
+    VSTREAM *tlsproxy_stream = starttls_state->tlsproxy_stream;
+    static VSTRING *remote_endpt = 0;
+
+    if (msg_verbose)
+       msg_info("%s: receive server protocol on proxy socket %d"
+                " for smtp socket %d from [%s]:%s flags=%s",
+                myname, vstream_fileno(tlsproxy_stream),
+                vstream_fileno(smtp_state->smtp_client_stream),
+                smtp_state->smtp_client_addr, smtp_state->smtp_client_port,
+                psc_print_state_flags(smtp_state->flags, myname));
 
     /*
-     * Resume the postscreen(8) dummy SMTP engine and clean up.
+     * 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.
      */
-    starttls_state->resume_event(event, (void *) smtp_state);
-    myfree((void *) starttls_state);
+    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();
+    }
+
+    /*
+     * 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.
+     */
+    if (remote_endpt == 0)
+       remote_endpt = vstring_alloc(20);
+    vstring_sprintf(remote_endpt, "[%s]:%s", smtp_state->smtp_client_addr,
+                   smtp_state->smtp_client_port);
+    attr_print(tlsproxy_stream, ATTR_FLAG_NONE,
+              SEND_ATTR_STR(TLS_ATTR_REMOTE_ENDPT, STR(remote_endpt)),
+              SEND_ATTR_INT(TLS_ATTR_FLAGS, TLS_PROXY_FLAG_ROLE_SERVER),
+              SEND_ATTR_INT(TLS_ATTR_TIMEOUT, psc_normal_cmd_time_limit),
+              SEND_ATTR_INT(TLS_ATTR_TIMEOUT, psc_normal_cmd_time_limit),
+              SEND_ATTR_STR(TLS_ATTR_SERVERID, MAIL_SERVICE_SMTPD),    /* XXX */
+              ATTR_TYPE_END);
+    if (vstream_fflush(tlsproxy_stream) != 0) {
+       msg_warn("error sending request to %s service: %m", psc_tlsp_service);
+       PSC_SEND_REPLY(smtp_state,
+                   "454 4.7.0 TLS not available due to local problem\r\n");
+       PSC_STARTTLS_EVENT_ERR_RESUME_RETURN();
+    }
+
+    /*
+     * Set up a read event for the next phase of the TLS proxy handshake.
+     */
+    PSC_READ_EVENT_REQUEST(vstream_fileno(tlsproxy_stream), psc_starttls_finish,
+                          (void *) starttls_state, TLSPROXY_INIT_TIMEOUT);
 }
 
 /* psc_starttls_open - open negotiations with TLS proxy */
@@ -193,12 +276,10 @@ void    psc_starttls_open(PSC_STATE *smtp_state, EVENT_NOTIFY_FN resume_event)
     PSC_STARTTLS *starttls_state;
     VSTREAM *tlsproxy_stream;
     int     fd;
-    static VSTRING *remote_endpt = 0;
 
     if (psc_tlsp_service == 0) {
        psc_tlsp_service = concatenate(MAIL_CLASS_PRIVATE "/",
                                       var_tlsproxy_service, (char *) 0);
-       remote_endpt = vstring_alloc(20);
     }
 
     /*
@@ -213,38 +294,16 @@ void    psc_starttls_open(PSC_STATE *smtp_state, EVENT_NOTIFY_FN resume_event)
        return;
     }
     if (msg_verbose)
-       msg_info("%s: send client name/address on proxy socket %d"
+       msg_info("%s: connecting to proxy socket %d"
                 " for smtp socket %d from [%s]:%s flags=%s",
                 myname, fd, vstream_fileno(smtp_state->smtp_client_stream),
                 smtp_state->smtp_client_addr, smtp_state->smtp_client_port,
                 psc_print_state_flags(smtp_state->flags, myname));
 
-    /*
-     * Initial handshake. Send the data attributes now, and send the client
-     * file descriptor in a later transaction. We report all errors
-     * asynchronously, to avoid having to maintain multiple delivery paths.
-     * 
-     * XXX The formatted endpoint should be a state member. Then, we can
-     * simplify all the format strings throughout the program.
-     */
     tlsproxy_stream = vstream_fdopen(fd, O_RDWR);
-    vstring_sprintf(remote_endpt, "[%s]:%s", smtp_state->smtp_client_addr,
-                   smtp_state->smtp_client_port);
-    attr_print(tlsproxy_stream, ATTR_FLAG_NONE,
-              SEND_ATTR_STR(TLS_ATTR_REMOTE_ENDPT, STR(remote_endpt)),
-              SEND_ATTR_INT(TLS_ATTR_FLAGS, TLS_PROXY_FLAG_ROLE_SERVER),
-              SEND_ATTR_INT(TLS_ATTR_TIMEOUT, psc_normal_cmd_time_limit),
-              SEND_ATTR_INT(TLS_ATTR_TIMEOUT, psc_normal_cmd_time_limit),
-              SEND_ATTR_STR(TLS_ATTR_SERVERID, MAIL_SERVICE_SMTPD),    /* XXX */
-              ATTR_TYPE_END);
-    if (vstream_fflush(tlsproxy_stream) != 0) {
-       msg_warn("error sending request to %s service: %m", psc_tlsp_service);
-       vstream_fclose(tlsproxy_stream);
-       PSC_SEND_REPLY(smtp_state,
-                   "454 4.7.0 TLS not available due to local problem\r\n");
-       event_request_timer(resume_event, (void *) smtp_state, 0);
-       return;
-    }
+    vstream_control(tlsproxy_stream,
+                   VSTREAM_CTL_PATH, psc_tlsp_service,
+                   VSTREAM_CTL_END);
 
     /*
      * Set up a read event for the next phase of the TLS proxy handshake.
@@ -253,6 +312,6 @@ void    psc_starttls_open(PSC_STATE *smtp_state, EVENT_NOTIFY_FN resume_event)
     starttls_state->tlsproxy_stream = tlsproxy_stream;
     starttls_state->resume_event = resume_event;
     starttls_state->smtp_state = smtp_state;
-    PSC_READ_EVENT_REQUEST(vstream_fileno(tlsproxy_stream), psc_starttls_finish,
+    PSC_READ_EVENT_REQUEST(vstream_fileno(tlsproxy_stream), psc_starttls_first,
                           (void *) starttls_state, TLSPROXY_INIT_TIMEOUT);
 }
index e486c468527db1ccf1793e99eea62fcd4fb1a8b8..5783c99a18ea2961d573249c0e3029bea8dd8c61 100644 (file)
@@ -745,6 +745,21 @@ static void pre_accept(char *unused_name, char **unused_argv)
     }
 }
 
+/* post_accept - anounce our protocol name */
+
+static void post_accept(VSTREAM *stream, char *unused_name, char **unused_argv,
+                               HTABLE *unused_attr)
+{
+
+    /*
+     * Announce the protocol.
+     */
+    attr_print(stream, ATTR_FLAG_NONE,
+              SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_PROXYMAP),
+              ATTR_TYPE_END);
+    (void) vstream_fflush(stream);
+}
+
 MAIL_VERSION_STAMP_DECLARE;
 
 /* main - pass control to the multi-threaded skeleton */
@@ -782,6 +797,7 @@ int     main(int argc, char **argv)
                      CA_MAIL_SERVER_STR_TABLE(str_table),
                      CA_MAIL_SERVER_POST_INIT(post_jail_init),
                      CA_MAIL_SERVER_PRE_ACCEPT(pre_accept),
+                     CA_MAIL_SERVER_POST_ACCEPT(post_accept),
     /* XXX CA_MAIL_SERVER_SOLITARY if proxywrite */
                      0);
 }
index fe4cf0ca5be14826f438ebb5f4af6cf9a09296c9..c87f6c6f3b1a82e1a2bb2daec874e62cba06d896 100644 (file)
@@ -108,18 +108,16 @@ int     qmgr_deliver_concurrency;
 
 static int qmgr_deliver_initial_reply(VSTREAM *stream)
 {
-    int     stat;
-
     if (peekfd(vstream_fileno(stream)) < 0) {
        msg_warn("%s: premature disconnect", VSTREAM_PATH(stream));
        return (DELIVER_STAT_CRASH);
     } else if (attr_scan(stream, ATTR_FLAG_STRICT,
-                        RECV_ATTR_INT(MAIL_ATTR_STATUS, &stat),
-                        ATTR_TYPE_END) != 1) {
+                 RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_DELIVER),
+                        ATTR_TYPE_END) != 0) {
        msg_warn("%s: malformed response", VSTREAM_PATH(stream));
-       return (DELIVER_STAT_CRASH);
+       return (DELIVER_STAT_DEFER);
     } else {
-       return (stat ? DELIVER_STAT_DEFER : 0);
+       return (0);
     }
 }
 
index d06cfcad1b09581410940841ce313d072ab64802..85f32effaab0aef785b08f2f036ace7317cd22dc 100644 (file)
@@ -544,6 +544,21 @@ static void post_jail_init(char *unused_name, char **unused_argv)
     scache_start_time = event_time();
 }
 
+/* scache_post_accept - announce our protocol */
+
+static void scache_post_accept(VSTREAM *stream, char *unused_name,
+                                  char **unused_argv, HTABLE *unused_table)
+{
+
+    /*
+     * Announce the protocol.
+     */
+    attr_print(stream, ATTR_FLAG_NONE,
+              SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_SCACHE),
+              ATTR_TYPE_END);
+    (void) vstream_fflush(stream);
+}
+
 MAIL_VERSION_STAMP_DECLARE;
 
 /* main - pass control to the multi-threaded skeleton */
@@ -564,6 +579,7 @@ int     main(int argc, char **argv)
     multi_server_main(argc, argv, scache_service,
                      CA_MAIL_SERVER_TIME_TABLE(time_table),
                      CA_MAIL_SERVER_POST_INIT(post_jail_init),
+                     CA_MAIL_SERVER_POST_ACCEPT(scache_post_accept),
                      CA_MAIL_SERVER_EXIT(scache_status_dump),
                      CA_MAIL_SERVER_SOLITARY,
                      0);
index e6ca68feb28a6d9733fcf2dd16d0f1043e91c5eb..b8dd7e9948089252da5d3adad630db41aeaeceb7 100644 (file)
@@ -360,6 +360,13 @@ static void showq_service(VSTREAM *client, char *unused_service, char **argv)
     if (argv[0])
        msg_fatal("unexpected command-line argument: %s", argv[0]);
 
+    /*
+     * Protocol identification.
+     */
+    (void) attr_print(client, ATTR_FLAG_NONE,
+                     SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_SHOWQ),
+                     ATTR_TYPE_END);
+
     /*
      * Skip any files that have the wrong permissions. If we can't open an
      * existing file, assume the system is out of resources or that it is
index e4d23b7a6b5a654a715cbaa08e4d78d175ae3d0c..03dfd64dea4e667574f9a7ed587ece8408db4987 100644 (file)
@@ -280,7 +280,6 @@ smtpd_chat.o: ../../include/mail_params.h
 smtpd_chat.o: ../../include/mail_proto.h
 smtpd_chat.o: ../../include/mail_stream.h
 smtpd_chat.o: ../../include/maps.h
-smtpd_chat.o: ../../include/match_list.h
 smtpd_chat.o: ../../include/milter.h
 smtpd_chat.o: ../../include/msg.h
 smtpd_chat.o: ../../include/myaddrinfo.h
@@ -296,7 +295,6 @@ smtpd_chat.o: ../../include/smtp_reply_footer.h
 smtpd_chat.o: ../../include/smtp_stream.h
 smtpd_chat.o: ../../include/smtputf8.h
 smtpd_chat.o: ../../include/sock_addr.h
-smtpd_chat.o: ../../include/string_list.h
 smtpd_chat.o: ../../include/stringops.h
 smtpd_chat.o: ../../include/sys_defs.h
 smtpd_chat.o: ../../include/tls.h
@@ -400,7 +398,6 @@ smtpd_expand.o: ../../include/mac_parse.h
 smtpd_expand.o: ../../include/mail_params.h
 smtpd_expand.o: ../../include/mail_proto.h
 smtpd_expand.o: ../../include/mail_stream.h
-smtpd_expand.o: ../../include/match_list.h
 smtpd_expand.o: ../../include/milter.h
 smtpd_expand.o: ../../include/msg.h
 smtpd_expand.o: ../../include/myaddrinfo.h
@@ -409,7 +406,6 @@ smtpd_expand.o: ../../include/name_code.h
 smtpd_expand.o: ../../include/name_mask.h
 smtpd_expand.o: ../../include/nvtable.h
 smtpd_expand.o: ../../include/sock_addr.h
-smtpd_expand.o: ../../include/string_list.h
 smtpd_expand.o: ../../include/stringops.h
 smtpd_expand.o: ../../include/sys_defs.h
 smtpd_expand.o: ../../include/tls.h
@@ -428,7 +424,6 @@ smtpd_haproxy.o: ../../include/htable.h
 smtpd_haproxy.o: ../../include/iostuff.h
 smtpd_haproxy.o: ../../include/mail_params.h
 smtpd_haproxy.o: ../../include/mail_stream.h
-smtpd_haproxy.o: ../../include/match_list.h
 smtpd_haproxy.o: ../../include/milter.h
 smtpd_haproxy.o: ../../include/msg.h
 smtpd_haproxy.o: ../../include/myaddrinfo.h
@@ -438,7 +433,6 @@ smtpd_haproxy.o: ../../include/name_mask.h
 smtpd_haproxy.o: ../../include/nvtable.h
 smtpd_haproxy.o: ../../include/smtp_stream.h
 smtpd_haproxy.o: ../../include/sock_addr.h
-smtpd_haproxy.o: ../../include/string_list.h
 smtpd_haproxy.o: ../../include/stringops.h
 smtpd_haproxy.o: ../../include/sys_defs.h
 smtpd_haproxy.o: ../../include/tls.h
@@ -456,7 +450,6 @@ smtpd_milter.o: ../../include/dns.h
 smtpd_milter.o: ../../include/htable.h
 smtpd_milter.o: ../../include/mail_params.h
 smtpd_milter.o: ../../include/mail_stream.h
-smtpd_milter.o: ../../include/match_list.h
 smtpd_milter.o: ../../include/milter.h
 smtpd_milter.o: ../../include/myaddrinfo.h
 smtpd_milter.o: ../../include/mymalloc.h
@@ -468,7 +461,6 @@ smtpd_milter.o: ../../include/quote_flags.h
 smtpd_milter.o: ../../include/resolve_clnt.h
 smtpd_milter.o: ../../include/sock_addr.h
 smtpd_milter.o: ../../include/split_at.h
-smtpd_milter.o: ../../include/string_list.h
 smtpd_milter.o: ../../include/stringops.h
 smtpd_milter.o: ../../include/sys_defs.h
 smtpd_milter.o: ../../include/tls.h
@@ -491,7 +483,6 @@ smtpd_peer.o: ../../include/iostuff.h
 smtpd_peer.o: ../../include/mail_params.h
 smtpd_peer.o: ../../include/mail_proto.h
 smtpd_peer.o: ../../include/mail_stream.h
-smtpd_peer.o: ../../include/match_list.h
 smtpd_peer.o: ../../include/milter.h
 smtpd_peer.o: ../../include/msg.h
 smtpd_peer.o: ../../include/myaddrinfo.h
@@ -501,7 +492,6 @@ smtpd_peer.o: ../../include/name_mask.h
 smtpd_peer.o: ../../include/nvtable.h
 smtpd_peer.o: ../../include/sock_addr.h
 smtpd_peer.o: ../../include/split_at.h
-smtpd_peer.o: ../../include/string_list.h
 smtpd_peer.o: ../../include/stringops.h
 smtpd_peer.o: ../../include/sys_defs.h
 smtpd_peer.o: ../../include/tls.h
@@ -525,7 +515,6 @@ smtpd_proxy.o: ../../include/mail_params.h
 smtpd_proxy.o: ../../include/mail_proto.h
 smtpd_proxy.o: ../../include/mail_queue.h
 smtpd_proxy.o: ../../include/mail_stream.h
-smtpd_proxy.o: ../../include/match_list.h
 smtpd_proxy.o: ../../include/milter.h
 smtpd_proxy.o: ../../include/msg.h
 smtpd_proxy.o: ../../include/myaddrinfo.h
@@ -537,7 +526,6 @@ smtpd_proxy.o: ../../include/rec_type.h
 smtpd_proxy.o: ../../include/record.h
 smtpd_proxy.o: ../../include/smtp_stream.h
 smtpd_proxy.o: ../../include/sock_addr.h
-smtpd_proxy.o: ../../include/string_list.h
 smtpd_proxy.o: ../../include/stringops.h
 smtpd_proxy.o: ../../include/sys_defs.h
 smtpd_proxy.o: ../../include/tls.h
@@ -607,7 +595,6 @@ smtpd_sasl_proto.o: ../../include/mail_error.h
 smtpd_sasl_proto.o: ../../include/mail_params.h
 smtpd_sasl_proto.o: ../../include/mail_proto.h
 smtpd_sasl_proto.o: ../../include/mail_stream.h
-smtpd_sasl_proto.o: ../../include/match_list.h
 smtpd_sasl_proto.o: ../../include/milter.h
 smtpd_sasl_proto.o: ../../include/msg.h
 smtpd_sasl_proto.o: ../../include/myaddrinfo.h
@@ -616,7 +603,6 @@ smtpd_sasl_proto.o: ../../include/name_code.h
 smtpd_sasl_proto.o: ../../include/name_mask.h
 smtpd_sasl_proto.o: ../../include/nvtable.h
 smtpd_sasl_proto.o: ../../include/sock_addr.h
-smtpd_sasl_proto.o: ../../include/string_list.h
 smtpd_sasl_proto.o: ../../include/stringops.h
 smtpd_sasl_proto.o: ../../include/sys_defs.h
 smtpd_sasl_proto.o: ../../include/tls.h
@@ -641,7 +627,6 @@ smtpd_state.o: ../../include/mail_error.h
 smtpd_state.o: ../../include/mail_params.h
 smtpd_state.o: ../../include/mail_proto.h
 smtpd_state.o: ../../include/mail_stream.h
-smtpd_state.o: ../../include/match_list.h
 smtpd_state.o: ../../include/milter.h
 smtpd_state.o: ../../include/msg.h
 smtpd_state.o: ../../include/myaddrinfo.h
@@ -650,7 +635,6 @@ smtpd_state.o: ../../include/name_code.h
 smtpd_state.o: ../../include/name_mask.h
 smtpd_state.o: ../../include/nvtable.h
 smtpd_state.o: ../../include/sock_addr.h
-smtpd_state.o: ../../include/string_list.h
 smtpd_state.o: ../../include/sys_defs.h
 smtpd_state.o: ../../include/tls.h
 smtpd_state.o: ../../include/vbuf.h
@@ -676,7 +660,6 @@ smtpd_xforward.o: ../../include/htable.h
 smtpd_xforward.o: ../../include/iostuff.h
 smtpd_xforward.o: ../../include/mail_proto.h
 smtpd_xforward.o: ../../include/mail_stream.h
-smtpd_xforward.o: ../../include/match_list.h
 smtpd_xforward.o: ../../include/milter.h
 smtpd_xforward.o: ../../include/msg.h
 smtpd_xforward.o: ../../include/myaddrinfo.h
@@ -685,7 +668,6 @@ smtpd_xforward.o: ../../include/name_code.h
 smtpd_xforward.o: ../../include/name_mask.h
 smtpd_xforward.o: ../../include/nvtable.h
 smtpd_xforward.o: ../../include/sock_addr.h
-smtpd_xforward.o: ../../include/string_list.h
 smtpd_xforward.o: ../../include/sys_defs.h
 smtpd_xforward.o: ../../include/tls.h
 smtpd_xforward.o: ../../include/vbuf.h
index 5097697d5242f2712ebaa6394f985554879e9002..74c6d6d18da1efd40561db5c48e6394277c943a5 100644 (file)
@@ -62,6 +62,7 @@ depend: $(MAKES)
 spawn.o: ../../include/argv.h
 spawn.o: ../../include/check_arg.h
 spawn.o: ../../include/dict.h
+spawn.o: ../../include/htable.h
 spawn.o: ../../include/mail_conf.h
 spawn.o: ../../include/mail_params.h
 spawn.o: ../../include/mail_parm_split.h
index b2bdcdc1117890029ceed901a6a16c2b7c2dc60c..b69ddf6c81d8a9127a5ca5d49e1d0bdfd2ca0b44 100644 (file)
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
 
 static ATTR_CLNT *tls_mgr;
 
+/* tls_mgr_handshake - receive server protocol announcement */
+
+static int tls_mgr_handshake(VSTREAM *stream)
+{
+    return (attr_scan(stream, ATTR_FLAG_STRICT,
+                  RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TLSMGR),
+                     ATTR_TYPE_END));
+}
+
 /* tls_mgr_open - create client handle */
 
 static void tls_mgr_open(void)
@@ -168,6 +182,7 @@ static void tls_mgr_open(void)
 
     attr_clnt_control(tls_mgr,
                      ATTR_CLNT_CTL_PROTO, attr_vprint, attr_vscan,
+                     ATTR_CLNT_CTL_HANDSHAKE, tls_mgr_handshake,
                      ATTR_CLNT_CTL_END);
 }
 
index beeafa7f1014f7c8695c30aa2680aa7e139cc4e0..ca6a2e407ee401d390a22bfd9214b7479ae77b25 100644 (file)
@@ -187,6 +187,14 @@ VSTREAM *tls_proxy_open(const char *service, int flags,
      * remote peer file descriptor in a later transaction.
      */
     tlsproxy_stream = vstream_fdopen(fd, O_RDWR);
+    if (attr_scan(tlsproxy_stream, ATTR_FLAG_STRICT,
+                 RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TLSPROXY),
+                 ATTR_TYPE_END) != 0) {
+       msg_warn("error receiving %s service initial response",
+                STR(tlsproxy_service));
+       vstream_fclose(tlsproxy_stream);
+       return (0);
+    }
     vstring_sprintf(remote_endpt, "[%s]:%s", peer_addr, peer_port);
     attr_print(tlsproxy_stream, ATTR_FLAG_NONE,
               SEND_ATTR_STR(TLS_ATTR_REMOTE_ENDPT, STR(remote_endpt)),
index db48ffbc2c12d4f7fe5886843cd89d6aef41d4e2..3b937339380d8d00b444fbfae0ef4dc918a04995 100644 (file)
@@ -1004,6 +1004,22 @@ static void tlsmgr_post_init(char *unused_name, char **unused_argv)
            tlsmgr_cache_run_event(NULL_EVENT, (void *) ent);
 }
 
+/* tlsmgr_post_accept - announce our protocol */
+
+static void tlsmgr_post_accept(VSTREAM *stream, char *unused_name,
+                                  char **unused_argv, HTABLE *unused_table)
+{
+
+    /*
+     * Announce the protocol.
+     */
+    attr_print(stream, ATTR_FLAG_NONE,
+              SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TLSMGR),
+              ATTR_TYPE_END);
+    (void) vstream_fflush(stream);
+}
+
+
 /* tlsmgr_before_exit - save PRNG state before exit */
 
 static void tlsmgr_before_exit(char *unused_service_name, char **unused_argv)
@@ -1061,6 +1077,7 @@ int     main(int argc, char **argv)
                      CA_MAIL_SERVER_STR_TABLE(str_table),
                      CA_MAIL_SERVER_PRE_INIT(tlsmgr_pre_init),
                      CA_MAIL_SERVER_POST_INIT(tlsmgr_post_init),
+                     CA_MAIL_SERVER_POST_ACCEPT(tlsmgr_post_accept),
                      CA_MAIL_SERVER_EXIT(tlsmgr_before_exit),
                      CA_MAIL_SERVER_LOOP(tlsmgr_loop),
                      CA_MAIL_SERVER_SOLITARY,
index b11ce92c3fd9ba3975527face2816d428db93bf6..c1774a90293016422b46ab549ebeded13ed3b5b3 100644 (file)
@@ -1481,6 +1481,12 @@ static void tlsp_service(VSTREAM *plaintext_stream,
                    CA_VSTREAM_CTL_TIMEOUT(5),
                    CA_VSTREAM_CTL_END);
 
+    (void) attr_print(plaintext_stream, ATTR_FLAG_NONE,
+                  SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TLSPROXY),
+                     ATTR_TYPE_END);
+    if (vstream_fflush(plaintext_stream) != 0)
+       msg_warn("write %s attribute: %m", MAIL_ATTR_PROTO);
+
     /*
      * Receive postscreen's remote SMTP client address/port and socket.
      */
index 29c55c9b3b9d5301d33344ae2014649ec4b6e82a..dcc555c6fef736e2c0a511b99185ae7863894fdb 100644 (file)
 /*     matches subdomains of example.com,
 /*     instead of requiring an explicit ".example.com" pattern.
 /* .IP "\fBrelayhost (empty)\fR"
-/*     The next-hop destination of non-local mail; overrides non-local
+/*     The next-hop destination(s) for non-local mail; overrides non-local
 /*     domains in recipient addresses.
 /* .IP "\fBtransport_maps (empty)\fR"
 /*     Optional lookup tables with mappings from recipient address to
@@ -522,6 +522,21 @@ static void pre_accept(char *unused_name, char **unused_argv)
 
 #endif
 
+/* post_accept - anounce our protocol name */
+
+static void post_accept(VSTREAM *stream, char *unused_name, char **unused_argv,
+                               HTABLE *unused_attr)
+{
+
+    /*
+     * Announce the protocol.
+     */
+    attr_print(stream, ATTR_FLAG_NONE,
+              SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TRIVIAL),
+              ATTR_TYPE_END);
+    (void) vstream_fflush(stream);
+}
+
 static void check_table_stats(int unused_event, void *unused_context)
 {
     const char *table;
@@ -648,5 +663,6 @@ int     main(int argc, char **argv)
 #ifdef CHECK_TABLE_STATS_BEFORE_ACCEPT
                      CA_MAIL_SERVER_PRE_ACCEPT(pre_accept),
 #endif
+                     CA_MAIL_SERVER_POST_ACCEPT(post_accept),
                      0);
 }
index 6c23678ab4fede21731d92e071e3059f10fff938..d2815bee76d9d0ca1c4baa1646c98d4e7ff7e40c 100644 (file)
@@ -17,7 +17,7 @@ SRCS  = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \
        msg_output.c msg_syslog.c msg_vstream.c mvect.c myaddrinfo.c myflock.c \
        mymalloc.c myrand.c mystrtok.c name_code.c name_mask.c netstring.c \
        neuter.c non_blocking.c nvtable.c open_as.c open_limit.c open_lock.c \
-       peekfd.c percentm.c posix_signals.c printable.c rand_sleep.c \
+       peekfd.c posix_signals.c printable.c rand_sleep.c \
        readlline.c ring.c safe_getenv.c safe_open.c \
        sane_accept.c sane_connect.c sane_link.c sane_rename.c \
        sane_socketpair.c sane_time.c scan_dir.c set_eugid.c set_ugid.c \
@@ -62,7 +62,7 @@ OBJS  = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
        msg_output.o msg_syslog.o msg_vstream.o mvect.o myaddrinfo.o myflock.o \
        mymalloc.o myrand.o mystrtok.o name_code.o name_mask.o netstring.o \
        neuter.o non_blocking.o nvtable.o open_as.o open_limit.o open_lock.o \
-       peekfd.o percentm.o posix_signals.o printable.o rand_sleep.o \
+       peekfd.o posix_signals.o printable.o rand_sleep.o \
        readlline.o ring.o safe_getenv.o safe_open.o \
        sane_accept.o sane_connect.o sane_link.o sane_rename.o \
        sane_socketpair.o sane_time.o scan_dir.o set_eugid.o set_ugid.o \
@@ -104,7 +104,7 @@ HDRS        = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
        mac_parse.h make_dirs.h mask_addr.h match_list.h msg.h \
        msg_output.h msg_syslog.h msg_vstream.h mvect.h myaddrinfo.h myflock.h \
        mymalloc.h myrand.h name_code.h name_mask.h netstring.h nvtable.h \
-       open_as.h open_lock.h percentm.h posix_signals.h readlline.h ring.h \
+       open_as.h open_lock.h posix_signals.h readlline.h ring.h \
        safe.h safe_open.h sane_accept.h sane_connect.h sane_fsops.h \
        load_lib.h \
        sane_socketpair.h sane_time.h scan_dir.h set_eugid.h set_ugid.h \
@@ -1949,6 +1949,8 @@ load_file.o: vbuf.h
 load_file.o: vstream.h
 load_file.o: warn_stat.h
 load_lib.o: load_lib.c
+load_lib.o: load_lib.h
+load_lib.o: msg.h
 load_lib.o: sys_defs.h
 logwriter.o: check_arg.h
 logwriter.o: iostuff.h
@@ -2070,7 +2072,6 @@ msg_output.o: msg_output.c
 msg_output.o: msg_output.h
 msg_output.o: msg_vstream.h
 msg_output.o: mymalloc.h
-msg_output.o: percentm.h
 msg_output.o: stringops.h
 msg_output.o: sys_defs.h
 msg_output.o: vbuf.h
@@ -2220,12 +2221,6 @@ pass_trigger.o: trigger.h
 peekfd.o: iostuff.h
 peekfd.o: peekfd.c
 peekfd.o: sys_defs.h
-percentm.o: check_arg.h
-percentm.o: percentm.c
-percentm.o: percentm.h
-percentm.o: sys_defs.h
-percentm.o: vbuf.h
-percentm.o: vstring.h
 poll_fd.o: iostuff.h
 poll_fd.o: msg.h
 poll_fd.o: poll_fd.c
index 754e1259ffde6480136eded904e556d8efbf2b2b..fe44beb1ebc318f475e3461c6113694ea32f9d6a 100644 (file)
@@ -45,6 +45,7 @@ typedef int (*ATTR_PRINT_CUSTOM_FN) (ATTR_PRINT_COMMON_FN, VSTREAM *, int, void
 #define ATTR_TYPE_LONG         4       /* Unsigned long */
 #define ATTR_TYPE_DATA         5       /* Binary data */
 #define ATTR_TYPE_FUNC         6       /* Function pointer */
+#define ATTR_TYPE_STREQ                7       /* Requires (name, value) match */
 
  /*
   * Optional sender-specified grouping for hash or nameval tables.
@@ -70,6 +71,7 @@ typedef int (*ATTR_PRINT_CUSTOM_FN) (ATTR_PRINT_COMMON_FN, VSTREAM *, int, void
 
 #define RECV_ATTR_INT(name, val)       ATTR_TYPE_INT, CHECK_CPTR(ATTR, char, (name)), CHECK_PTR(ATTR, int, (val))
 #define RECV_ATTR_STR(name, val)       ATTR_TYPE_STR, CHECK_CPTR(ATTR, char, (name)), CHECK_PTR(ATTR, VSTRING, (val))
+#define RECV_ATTR_STREQ(name, val)     ATTR_TYPE_STREQ, CHECK_CPTR(ATTR, char, (name)), CHECK_CPTR(ATTR, char, (val))
 #define RECV_ATTR_HASH(val)            ATTR_TYPE_HASH, CHECK_PTR(ATTR, HTABLE, (val))
 #define RECV_ATTR_NV(val)              ATTR_TYPE_NV, CHECK_PTR(ATTR, NVTABLE, (val))
 #define RECV_ATTR_LONG(name, val)      ATTR_TYPE_LONG, CHECK_CPTR(ATTR, char, (name)), CHECK_PTR(ATTR, long, (val))
index 0ec09449bf7f78d557e463114bc87deb51b6fd5c..d944be509fc5be9ab61111f572e0ebd9c896d6fa 100644 (file)
@@ -8,6 +8,7 @@
 /*
 /*     typedef int (*ATTR_CLNT_PRINT_FN) (VSTREAM *, int, va_list);
 /*     typedef int (*ATTR_CLNT_SCAN_FN) (VSTREAM *, int, va_list);
+/*     typedef int (*ATTR_CLNT_HANDSHAKE_FN) (VSTREAM *);
 /*
 /*     ATTR_CLNT *attr_clnt_create(server, timeout, max_idle, max_ttl)
 /*     const char *server;
@@ -65,6 +66,9 @@
 /* .IP "ATTR_CLNT_CTL_TRY_DELAY(int)"
 /*     The time in seconds between attempts to send a request
 /*     (default: 1).  Specify a value greater than zero.
+/* .IP "ATTR_CLNT_CTL_HANDSHAKE(VSTREAM *)"
+/*      A pointer to function that will be called at the start of a
+/*      new connection, and that returns 0 in case of success.
 /* DIAGNOSTICS
 /*     Warnings: communication failure.
 /* SEE ALSO
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
@@ -254,6 +263,12 @@ void    attr_clnt_control(ATTR_CLNT *client, int name,...)
            client->print = va_arg(ap, ATTR_CLNT_PRINT_FN);
            client->scan = va_arg(ap, ATTR_CLNT_SCAN_FN);
            break;
+       case ATTR_CLNT_CTL_HANDSHAKE:
+           auto_clnt_control(client->auto_clnt,
+                             AUTO_CLNT_CTL_HANDSHAKE,
+                             va_arg(ap, ATTR_CLNT_HANDSHAKE_FN),
+                             AUTO_CLNT_CTL_END);
+           break;
        case ATTR_CLNT_CTL_REQ_LIMIT:
            client->req_limit = va_arg(ap, int);
            if (client->req_limit < 0)
index c5e5ac0ae454657798985d41d7f015aab23446b5..ca630cd0e6df518145d29f11e65b2562f9f5fbd6 100644 (file)
@@ -27,6 +27,7 @@
 typedef struct ATTR_CLNT ATTR_CLNT;
 typedef int (*ATTR_CLNT_PRINT_FN) (VSTREAM *, int, va_list);
 typedef int (*ATTR_CLNT_SCAN_FN) (VSTREAM *, int, va_list);
+typedef int (*ATTR_CLNT_HANDSHAKE_FN) (VSTREAM *);
 
 extern ATTR_CLNT *attr_clnt_create(const char *, int, int, int);
 extern int attr_clnt_request(ATTR_CLNT *, int,...);
@@ -38,6 +39,7 @@ extern void attr_clnt_control(ATTR_CLNT *, int,...);
 #define ATTR_CLNT_CTL_REQ_LIMIT        2       /* requests per connection */
 #define ATTR_CLNT_CTL_TRY_LIMIT        3       /* attempts per request */
 #define ATTR_CLNT_CTL_TRY_DELAY        4       /* pause between requests */
+#define ATTR_CLNT_CTL_HANDSHAKE        5       /* handshake before first request */
 
 /* LICENSE
 /* .ad
@@ -48,6 +50,11 @@ extern void attr_clnt_control(ATTR_CLNT *, int,...);
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 #endif
index 20c2c5a1e44d27ee25e7203a18b05a279b6f2d0d..98c511850f2c66e1b47d72722a75d77b2a9afa56 100644 (file)
@@ -228,6 +228,7 @@ int     main(int unused_argc, char **argv)
     htable_enter(table, "foo-name", mystrdup("foo-value"));
     htable_enter(table, "bar-name", mystrdup("bar-value"));
     attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE,
+               SEND_ATTR_STR("protocol", "test"),
                SEND_ATTR_INT(ATTR_NAME_INT, 4711),
                SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
                SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
@@ -236,11 +237,15 @@ int     main(int unused_argc, char **argv)
                SEND_ATTR_LONG(ATTR_NAME_LONG, 4321L),
                ATTR_TYPE_END);
     attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE,
+               SEND_ATTR_STR("protocol", "test"),
                SEND_ATTR_INT(ATTR_NAME_INT, 4711),
                SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
                SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
                SEND_ATTR_DATA(ATTR_NAME_DATA, strlen("whoopee"), "whoopee"),
                ATTR_TYPE_END);
+    attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE,
+               SEND_ATTR_STR("protocol", "not-test"),
+               ATTR_TYPE_END);
     if (vstream_fflush(VSTREAM_OUT) != 0)
        msg_fatal("write error: %m");
 
index 1008979aa9f8ba8eec449a1a03c976a58eff2abb..085ba33ccb03510b39e516a90017a436ce009b12 100644 (file)
@@ -269,6 +269,7 @@ int     main(int unused_argc, char **argv)
     htable_enter(table, "foo-name", mystrdup("foo-value"));
     htable_enter(table, "bar-name", mystrdup("bar-value"));
     attr_print64(VSTREAM_OUT, ATTR_FLAG_NONE,
+                SEND_ATTR_STR("protocol", "test"),
                 SEND_ATTR_INT(ATTR_NAME_INT, 4711),
                 SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
                 SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
@@ -277,11 +278,15 @@ int     main(int unused_argc, char **argv)
                 SEND_ATTR_LONG(ATTR_NAME_LONG, 4321L),
                 ATTR_TYPE_END);
     attr_print64(VSTREAM_OUT, ATTR_FLAG_NONE,
+                SEND_ATTR_STR("protocol", "test"),
                 SEND_ATTR_INT(ATTR_NAME_INT, 4711),
                 SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
                 SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
               SEND_ATTR_DATA(ATTR_NAME_DATA, strlen("whoopee"), "whoopee"),
                 ATTR_TYPE_END);
+    attr_print64(VSTREAM_OUT, ATTR_FLAG_NONE,
+                SEND_ATTR_STR("protocol", "not-test"),
+                ATTR_TYPE_END);
     if (vstream_fflush(VSTREAM_OUT) != 0)
        msg_fatal("write error: %m");
 
index 7ef03be8edbf07144c102ae1bde2979bf41711d1..7d2d02fdb7b68b96351bd51b8130098d9d2d8641 100644 (file)
@@ -224,6 +224,7 @@ int     main(int unused_argc, char **argv)
     htable_enter(table, "foo-name", mystrdup("foo-value"));
     htable_enter(table, "bar-name", mystrdup("bar-value"));
     attr_print_plain(VSTREAM_OUT, ATTR_FLAG_NONE,
+                    SEND_ATTR_STR("protocol", "test"),
                     SEND_ATTR_INT(ATTR_NAME_INT, 4711),
                     SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
                     SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
@@ -232,11 +233,15 @@ int     main(int unused_argc, char **argv)
                     SEND_ATTR_LONG(ATTR_NAME_LONG, 4321L),
                     ATTR_TYPE_END);
     attr_print_plain(VSTREAM_OUT, ATTR_FLAG_NONE,
+                    SEND_ATTR_STR("protocol", "test"),
                     SEND_ATTR_INT(ATTR_NAME_INT, 4711),
                     SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
                     SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
               SEND_ATTR_DATA(ATTR_NAME_DATA, strlen("whoopee"), "whoopee"),
                     ATTR_TYPE_END);
+    attr_print_plain(VSTREAM_OUT, ATTR_FLAG_NONE,
+                    SEND_ATTR_STR("protocol", "not-test"),
+                    ATTR_TYPE_END);
     if (vstream_fflush(VSTREAM_OUT) != 0)
        msg_fatal("write error: %m");
 
index 6dd15487780e883446bdb93e335d299dea62b4f1..57746407c0819be8695fed3681b0892e6427bd39 100644 (file)
 /*     This argument is followed by an attribute name and a long pointer.
 /* .IP "RECV_ATTR_STR(const char *name, VSTRING *vp)"
 /*     This argument is followed by an attribute name and a VSTRING pointer.
+/* .IP "RECV_ATTR_STREQ(const char *name, const char *value)"
+/*     The name and value must match what the client sends.
+/*     This attribute does not increment the result value.
 /* .IP "RECV_ATTR_DATA(const char *name, VSTRING *vp)"
 /*     This argument is followed by an attribute name and a VSTRING pointer.
 /* .IP "RECV_ATTR_FUNC(ATTR_SCAN_CUSTOM_FN, void *data)"
@@ -278,6 +281,7 @@ int     attr_vscan0(VSTREAM *fp, int flags, va_list ap)
     int     conversions;
     ATTR_SCAN_CUSTOM_FN scan_fn;
     void   *scan_arg;
+    const char *expect_val;
 
     /*
      * Sanity check.
@@ -421,6 +425,19 @@ int     attr_vscan0(VSTREAM *fp, int flags, va_list ap)
            if (scan_fn(attr_scan0, fp, flags | ATTR_FLAG_MORE, scan_arg) < 0)
                return (-1);
            break;
+       case ATTR_TYPE_STREQ:
+           expect_val = va_arg(ap, const char *);
+           if ((ch = attr_scan0_string(fp, str_buf,
+                                       "input attribute value")) < 0)
+               return (-1);
+           if (strcmp(expect_val, STR(str_buf)) != 0) {
+               msg_warn("unexpected %s %s from %s (expected: %s)",
+                        STR(name_buf), STR(str_buf), VSTREAM_PATH(fp),
+                        expect_val);
+               return (-1);
+           }
+           conversions -= 1;
+           break;
        case ATTR_TYPE_HASH:
        case ATTR_TYPE_CLOSE:
            if ((ch = attr_scan0_string(fp, str_buf,
@@ -513,6 +530,7 @@ int     main(int unused_argc, char **used_argv)
     msg_vstream_init(used_argv[0], VSTREAM_ERR);
     if ((ret = attr_scan0(VSTREAM_IN,
                          ATTR_FLAG_STRICT,
+                         RECV_ATTR_STREQ("protocol", "test"),
                          RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
                          RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
                          RECV_ATTR_STR(ATTR_NAME_STR, str_val),
@@ -534,6 +552,7 @@ int     main(int unused_argc, char **used_argv)
     }
     if ((ret = attr_scan0(VSTREAM_IN,
                          ATTR_FLAG_STRICT,
+                         RECV_ATTR_STREQ("protocol", "test"),
                          RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
                          RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
                          RECV_ATTR_STR(ATTR_NAME_STR, str_val),
@@ -550,6 +569,11 @@ int     main(int unused_argc, char **used_argv)
     } else {
        vstream_printf("return: %d\n", ret);
     }
+    if ((ret = attr_scan0(VSTREAM_IN,
+                         ATTR_FLAG_STRICT,
+                         RECV_ATTR_STREQ("protocol", "test"),
+                         ATTR_TYPE_END)) != 0)
+       vstream_printf("return: %d\n", ret);
     if (vstream_fflush(VSTREAM_OUT) != 0)
        msg_fatal("write error: %m");
 
index 125faeb5965760b112a9e7368636f50736020292..1fe09fc9f75a1aecf3a1d95ed5df73c1a5c0a91c 100644 (file)
@@ -1,3 +1,4 @@
+./attr_print0: send attr protocol = test
 ./attr_print0: send attr number = 4711
 ./attr_print0: send attr long_number = 1234
 ./attr_print0: send attr string = whoopee
@@ -5,10 +6,15 @@
 ./attr_print0: send attr name foo-name value foo-value
 ./attr_print0: send attr name bar-name value bar-value
 ./attr_print0: send attr long_number = 4321
+./attr_print0: send attr protocol = test
 ./attr_print0: send attr number = 4711
 ./attr_print0: send attr long_number = 1234
 ./attr_print0: send attr string = whoopee
 ./attr_print0: send attr data = [data 7 bytes]
+./attr_print0: send attr protocol = not-test
+./attr_scan0: unknown_stream: wanted attribute: protocol
+./attr_scan0: input attribute name: protocol
+./attr_scan0: input attribute value: test
 ./attr_scan0: unknown_stream: wanted attribute: number
 ./attr_scan0: input attribute name: number
 ./attr_scan0: input attribute value: 4711
@@ -36,6 +42,9 @@
 ./attr_scan0: input attribute value: 4321
 ./attr_scan0: unknown_stream: wanted attribute: (list terminator)
 ./attr_scan0: input attribute name: (end)
+./attr_scan0: unknown_stream: wanted attribute: protocol
+./attr_scan0: input attribute name: protocol
+./attr_scan0: input attribute value: test
 ./attr_scan0: unknown_stream: wanted attribute: number
 ./attr_scan0: input attribute name: number
 ./attr_scan0: input attribute value: 4711
 ./attr_scan0: input attribute value: d2hvb3BlZQ==
 ./attr_scan0: unknown_stream: wanted attribute: (list terminator)
 ./attr_scan0: input attribute name: (end)
+./attr_scan0: unknown_stream: wanted attribute: protocol
+./attr_scan0: input attribute name: protocol
+./attr_scan0: input attribute value: not-test
+./attr_scan0: warning: unexpected protocol not-test from unknown_stream (expected: test)
 number 4711
 long_number 1234
 string whoopee
@@ -63,3 +76,4 @@ string whoopee
 data whoopee
 (hash) foo-name foo-value
 (hash) bar-name bar-value
+return: -1
index 4ea1e2874c8468d95feecf9f60eecaa3b9280730..0a5eb3ee53dddbcb3aa8b0d857cb06127ace290d 100644 (file)
 /*     This argument is followed by an attribute name and a long pointer.
 /* .IP "RECV_ATTR_STR(const char *name, VSTRING *vp)"
 /*     This argument is followed by an attribute name and a VSTRING pointer.
+/* .IP "RECV_ATTR_STREQ(const char *name, const char *value)"
+/*     The name and value must match what the client sends.
+/*     This attribute does not increment the result value.
 /* .IP "RECV_ATTR_DATA(const char *name, VSTRING *vp)"
 /*     This argument is followed by an attribute name and a VSTRING pointer.
 /* .IP "RECV_ATTR_FUNC(ATTR_SCAN_CUSTOM_FN, void *data)"
@@ -281,6 +284,7 @@ int     attr_vscan64(VSTREAM *fp, int flags, va_list ap)
     int     conversions;
     ATTR_SCAN_CUSTOM_FN scan_fn;
     void   *scan_arg;
+    const char *expect_val;
 
     /*
      * Sanity check.
@@ -470,6 +474,29 @@ int     attr_vscan64(VSTREAM *fp, int flags, va_list ap)
            if (scan_fn(attr_scan64, fp, flags | ATTR_FLAG_MORE, scan_arg) < 0)
                return (-1);
            break;
+       case ATTR_TYPE_STREQ:
+           if (ch != ':') {
+               msg_warn("missing value for string attribute %s from %s",
+                        STR(name_buf), VSTREAM_PATH(fp));
+               return (-1);
+           }
+           expect_val = va_arg(ap, const char *);
+           if ((ch = attr_scan64_string(fp, str_buf,
+                                        "input attribute value")) < 0)
+               return (-1);
+           if (ch != '\n') {
+               msg_warn("multiple values for attribute %s from %s",
+                        STR(name_buf), VSTREAM_PATH(fp));
+               return (-1);
+           }
+           if (strcmp(expect_val, STR(str_buf)) != 0) {
+               msg_warn("unexpected %s %s from %s (expected: %s)",
+                        STR(name_buf), STR(str_buf), VSTREAM_PATH(fp),
+                        expect_val);
+               return (-1);
+           }
+           conversions -= 1;
+           break;
        case ATTR_TYPE_HASH:
        case ATTR_TYPE_CLOSE:
            if (ch != ':') {
@@ -572,6 +599,7 @@ int     main(int unused_argc, char **used_argv)
     msg_vstream_init(used_argv[0], VSTREAM_ERR);
     if ((ret = attr_scan64(VSTREAM_IN,
                           ATTR_FLAG_STRICT,
+                          RECV_ATTR_STREQ("protocol", "test"),
                           RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
                           RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
                           RECV_ATTR_STR(ATTR_NAME_STR, str_val),
@@ -593,6 +621,7 @@ int     main(int unused_argc, char **used_argv)
     }
     if ((ret = attr_scan64(VSTREAM_IN,
                           ATTR_FLAG_STRICT,
+                          RECV_ATTR_STREQ("protocol", "test"),
                           RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
                           RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
                           RECV_ATTR_STR(ATTR_NAME_STR, str_val),
@@ -609,6 +638,11 @@ int     main(int unused_argc, char **used_argv)
     } else {
        vstream_printf("return: %d\n", ret);
     }
+    if ((ret = attr_scan64(VSTREAM_IN,
+                          ATTR_FLAG_STRICT,
+                          RECV_ATTR_STREQ("protocol", "test"),
+                          ATTR_TYPE_END)) != 0)
+       vstream_printf("return: %d\n", ret);
     if (vstream_fflush(VSTREAM_OUT) != 0)
        msg_fatal("write error: %m");
 
index 2fe353f802e2b353b8d176c51dd1b31efae1032f..9f9217afe730f1c94b1cd7d19db06991d804c35a 100644 (file)
@@ -1,3 +1,4 @@
+./attr_print64: send attr protocol = test
 ./attr_print64: send attr number = 4711
 ./attr_print64: send attr long_number = 1234
 ./attr_print64: send attr string = whoopee
@@ -5,10 +6,15 @@
 ./attr_print64: send attr name foo-name value foo-value
 ./attr_print64: send attr name bar-name value bar-value
 ./attr_print64: send attr long_number = 4321
+./attr_print64: send attr protocol = test
 ./attr_print64: send attr number = 4711
 ./attr_print64: send attr long_number = 1234
 ./attr_print64: send attr string = whoopee
 ./attr_print64: send attr data = [data 7 bytes]
+./attr_print64: send attr protocol = not-test
+./attr_scan64: unknown_stream: wanted attribute: protocol
+./attr_scan64: input attribute name: protocol
+./attr_scan64: input attribute value: test
 ./attr_scan64: unknown_stream: wanted attribute: number
 ./attr_scan64: input attribute name: number
 ./attr_scan64: input attribute value: 4711
@@ -36,6 +42,9 @@
 ./attr_scan64: input attribute value: 4321
 ./attr_scan64: unknown_stream: wanted attribute: (list terminator)
 ./attr_scan64: input attribute name: (end)
+./attr_scan64: unknown_stream: wanted attribute: protocol
+./attr_scan64: input attribute name: protocol
+./attr_scan64: input attribute value: test
 ./attr_scan64: unknown_stream: wanted attribute: number
 ./attr_scan64: input attribute name: number
 ./attr_scan64: input attribute value: 4711
 ./attr_scan64: input attribute value: whoopee
 ./attr_scan64: unknown_stream: wanted attribute: (list terminator)
 ./attr_scan64: input attribute name: (end)
+./attr_scan64: unknown_stream: wanted attribute: protocol
+./attr_scan64: input attribute name: protocol
+./attr_scan64: input attribute value: not-test
+./attr_scan64: warning: unexpected protocol not-test from unknown_stream (expected: test)
 number 4711
 long_number 1234
 string whoopee
@@ -63,3 +76,4 @@ string whoopee
 data whoopee
 (hash) foo-name foo-value
 (hash) bar-name bar-value
+return: -1
index 41cfc8d4dff7504a2f69f427f838f5335f4d5206..b003d4585fa513c5e7cf3ca4642940911ab174da 100644 (file)
 /*     This argument is followed by an attribute name and a long pointer.
 /* .IP "RECV_ATTR_STR(const char *name, VSTRING *vp)"
 /*     This argument is followed by an attribute name and a VSTRING pointer.
+/* .IP "RECV_ATTR_STREQ(const char *name, const char *value)"
+/*     The name and value must match what the client sends.
+/*     This attribute does not increment the result value.
 /* .IP "RECV_ATTR_DATA(const char *name, VSTRING *vp)"
 /*     This argument is followed by an attribute name and a VSTRING pointer.
 /* .IP "RECV_ATTR_FUNC(ATTR_SCAN_CUSTOM_FN, void *data)"
@@ -294,6 +297,7 @@ int     attr_vscan_plain(VSTREAM *fp, int flags, va_list ap)
     int     conversions;
     ATTR_SCAN_CUSTOM_FN scan_fn;
     void   *scan_arg;
+    const char *expect_val;
 
     /*
      * Sanity check.
@@ -458,6 +462,24 @@ int     attr_vscan_plain(VSTREAM *fp, int flags, va_list ap)
            if (scan_fn(attr_scan_plain, fp, flags | ATTR_FLAG_MORE, scan_arg) < 0)
                return (-1);
            break;
+       case ATTR_TYPE_STREQ:
+           if (ch != '=') {
+               msg_warn("missing value for string attribute %s from %s",
+                        STR(name_buf), VSTREAM_PATH(fp));
+               return (-1);
+           }
+           expect_val = va_arg(ap, const char *);
+           if ((ch = attr_scan_plain_string(fp, str_buf, 0,
+                                            "input attribute value")) < 0)
+               return (-1);
+           if (strcmp(expect_val, STR(str_buf)) != 0) {
+               msg_warn("unexpected %s %s from %s (expected: %s)",
+                        STR(name_buf), STR(str_buf), VSTREAM_PATH(fp),
+                        expect_val);
+               return (-1);
+           }
+           conversions -= 1;
+           break;
        case ATTR_TYPE_HASH:
        case ATTR_TYPE_CLOSE:
            if (ch != '=') {
@@ -555,6 +577,7 @@ int     main(int unused_argc, char **used_argv)
     msg_vstream_init(used_argv[0], VSTREAM_ERR);
     if ((ret = attr_scan_plain(VSTREAM_IN,
                               ATTR_FLAG_STRICT,
+                              RECV_ATTR_STREQ("protocol", "test"),
                               RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
                               RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
                               RECV_ATTR_STR(ATTR_NAME_STR, str_val),
@@ -576,6 +599,7 @@ int     main(int unused_argc, char **used_argv)
     }
     if ((ret = attr_scan_plain(VSTREAM_IN,
                               ATTR_FLAG_STRICT,
+                              RECV_ATTR_STREQ("protocol", "test"),
                               RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
                               RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
                               RECV_ATTR_STR(ATTR_NAME_STR, str_val),
@@ -592,6 +616,11 @@ int     main(int unused_argc, char **used_argv)
     } else {
        vstream_printf("return: %d\n", ret);
     }
+    if ((ret = attr_scan_plain(VSTREAM_IN,
+                              ATTR_FLAG_STRICT,
+                              RECV_ATTR_STREQ("protocol", "test"),
+                              ATTR_TYPE_END)) != 0)
+       vstream_printf("return: %d\n", ret);
     if (vstream_fflush(VSTREAM_OUT) != 0)
        msg_fatal("write error: %m");
 
index 6e962c81fd1de76c1830a9f997f5d28012f8c3ee..994ba3ce3565c1eee8fca83c149ea8fd0fb03b73 100644 (file)
@@ -1,3 +1,4 @@
+./attr_print_plain: send attr protocol = test
 ./attr_print_plain: send attr number = 4711
 ./attr_print_plain: send attr long_number = 1234
 ./attr_print_plain: send attr string = whoopee
@@ -5,10 +6,15 @@
 ./attr_print_plain: send attr name foo-name value foo-value
 ./attr_print_plain: send attr name bar-name value bar-value
 ./attr_print_plain: send attr long_number = 4321
+./attr_print_plain: send attr protocol = test
 ./attr_print_plain: send attr number = 4711
 ./attr_print_plain: send attr long_number = 1234
 ./attr_print_plain: send attr string = whoopee
 ./attr_print_plain: send attr data = [data 7 bytes]
+./attr_print_plain: send attr protocol = not-test
+./attr_scan_plain: unknown_stream: wanted attribute: protocol
+./attr_scan_plain: input attribute name: protocol
+./attr_scan_plain: input attribute value: test
 ./attr_scan_plain: unknown_stream: wanted attribute: number
 ./attr_scan_plain: input attribute name: number
 ./attr_scan_plain: input attribute value: 4711
@@ -36,6 +42,9 @@
 ./attr_scan_plain: input attribute value: 4321
 ./attr_scan_plain: unknown_stream: wanted attribute: (list terminator)
 ./attr_scan_plain: input attribute name: (end)
+./attr_scan_plain: unknown_stream: wanted attribute: protocol
+./attr_scan_plain: input attribute name: protocol
+./attr_scan_plain: input attribute value: test
 ./attr_scan_plain: unknown_stream: wanted attribute: number
 ./attr_scan_plain: input attribute name: number
 ./attr_scan_plain: input attribute value: 4711
 ./attr_scan_plain: input attribute value: d2hvb3BlZQ==
 ./attr_scan_plain: unknown_stream: wanted attribute: (list terminator)
 ./attr_scan_plain: input attribute name: (end)
+./attr_scan_plain: unknown_stream: wanted attribute: protocol
+./attr_scan_plain: input attribute name: protocol
+./attr_scan_plain: input attribute value: not-test
+./attr_scan_plain: warning: unexpected protocol not-test from unknown_stream (expected: test)
 number 4711
 long_number 1234
 string whoopee
@@ -63,3 +76,4 @@ string whoopee
 data whoopee
 (hash) foo-name foo-value
 (hash) bar-name bar-value
+return: -1
index 2703054e8039d70d0f99eda54e34b77aa3278cfb..cdbbe225353de24ee6b92a27155f6b7d11b7eed3 100644 (file)
@@ -6,6 +6,8 @@
 /* SYNOPSIS
 /*     #include <auto_clnt.h>
 /*
+/*     typedef void (*AUTO_CLNT_HANDSHAKE_FN)(VSTREAM *);
+/*
 /*     AUTO_CLNT *auto_clnt_create(service, timeout, max_idle, max_ttl)
 /*     const char *service;
 /*     int     timeout;
 /*
 /*     void    auto_clnt_free(auto_clnt)
 /*     AUTO_CLNT *auto_clnt;
+/*
+/*     void    auto_clnt_control(auto_clnt, name, value, ... AUTO_CLNT_CTL_END)
+/*     AUTO_CLNT *auto_clnt;
+/*     int     name;
 /* DESCRIPTION
 /*     This module maintains IPC client endpoints that automatically
 /*     disconnect after a being idle for a configurable amount of time,
 /*
 /*     auto_clnt_free() destroys of the specified client endpoint.
 /*
+/*     auto_clnt_control() allows the user to fine tune the behavior of
+/*      the specified client. The arguments are a list of (name, value)
+/*      terminated with AUTO_CLNT_CTL_END.
+/*      The following lists the names and the types of the corresponding
+/*      value arguments.
+/* .IP "AUTO_CLNT_CTL_HANDSHAKE(VSTREAM *)"
+/*      A pointer to function that will be called at the start of a
+/*      new connection, and that returns 0 in case of success.
+/* .PP
 /*     Arguments:
 /* .IP service
 /*     The service argument specifies "transport:servername" where
 /*     is expected to set the stream pathname to the server endpoint name.
 /* .IP context
 /*     Application context that is passed to the open_action routine.
+/* .IP handshake
+/*     A null pointer, or a pointer to function that will be called
+/*     at the start of a new connection and that returns 0 in case
+/*     of success.
 /* DIAGNOSTICS
 /*     Warnings: communication failure. Fatal error: out of memory.
 /* LICENSE
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
@@ -120,6 +144,7 @@ struct AUTO_CLNT {
     int     timeout;                   /* I/O time limit */
     int     max_idle;                  /* time before client disconnect */
     int     max_ttl;                   /* time before client disconnect */
+    AUTO_CLNT_HANDSHAKE_FN handshake;  /* new connection only */
     int     (*connect) (const char *, int, int);       /* unix, local, inet */
 };
 
@@ -250,6 +275,7 @@ void    auto_clnt_recover(AUTO_CLNT *auto_clnt)
 
 VSTREAM *auto_clnt_access(AUTO_CLNT *auto_clnt)
 {
+    AUTO_CLNT_HANDSHAKE_FN handshake;
 
     /*
      * Open a stream or restart the idle timer.
@@ -258,11 +284,15 @@ VSTREAM *auto_clnt_access(AUTO_CLNT *auto_clnt)
      */
     if (auto_clnt->vstream == 0) {
        auto_clnt_open(auto_clnt);
+       handshake = (auto_clnt->vstream ? auto_clnt->handshake : 0);
     } else {
        if (auto_clnt->max_idle > 0)
            event_request_timer(auto_clnt_event, (void *) auto_clnt,
                                auto_clnt->max_idle);
+       handshake = 0;
     }
+    if (handshake != 0 && handshake(auto_clnt->vstream) != 0)
+       return (0);
     return (auto_clnt->vstream);
 }
 
@@ -290,6 +320,7 @@ AUTO_CLNT *auto_clnt_create(const char *service, int timeout,
     auto_clnt->timeout = timeout;
     auto_clnt->max_idle = max_idle;
     auto_clnt->max_ttl = max_ttl;
+    auto_clnt->handshake = 0;
     if (strcmp(transport, "inet") == 0) {
        auto_clnt->connect = inet_connect;
     } else if (strcmp(transport, "local") == 0) {
@@ -320,3 +351,22 @@ void    auto_clnt_free(AUTO_CLNT *auto_clnt)
     myfree(auto_clnt->endpoint);
     myfree((void *) auto_clnt);
 }
+
+/* auto_clnt_control - fine control */
+
+void    auto_clnt_control(AUTO_CLNT *client, int name,...)
+{
+    const char *myname = "auto_clnt_control";
+    va_list ap;
+
+    for (va_start(ap, name); name != AUTO_CLNT_CTL_END; name = va_arg(ap, int)) {
+       switch (name) {
+       case AUTO_CLNT_CTL_HANDSHAKE:
+           client->handshake = va_arg(ap, AUTO_CLNT_HANDSHAKE_FN);
+           break;
+       default:
+           msg_panic("%s: bad name %d", myname, name);
+       }
+    }
+    va_end(ap);
+}
index a168c1adc3a0f3cdff4108a60d1313592b97a6c6..61c66804d7de2bf443b7c49b9b01d6cd93e810c9 100644 (file)
   * External interface.
   */
 typedef struct AUTO_CLNT AUTO_CLNT;
+typedef int (*AUTO_CLNT_HANDSHAKE_FN) (VSTREAM *);
 
 extern AUTO_CLNT *auto_clnt_create(const char *, int, int, int);
 extern VSTREAM *auto_clnt_access(AUTO_CLNT *);
 extern void auto_clnt_recover(AUTO_CLNT *);
 extern const char *auto_clnt_name(AUTO_CLNT *);
 extern void auto_clnt_free(AUTO_CLNT *);
+extern void auto_clnt_control(AUTO_CLNT *, int,...);
+
+#define AUTO_CLNT_CTL_END       0
+#define AUTO_CLNT_CTL_HANDSHAKE 1      /* handshake before first request */
 
 /* LICENSE
 /* .ad
@@ -36,6 +41,11 @@ extern void auto_clnt_free(AUTO_CLNT *);
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 #endif
index 7031089a98a20f6700044dfab1cd9dc9b66a7aa0..6663877d7367170b24a1412aca75299ef3b53b8f 100644 (file)
@@ -95,7 +95,6 @@
 #include <vstream.h>
 #include <msg_vstream.h>
 #include <stringops.h>
-#include <percentm.h>
 #include <msg_output.h>
 
  /*
@@ -165,7 +164,7 @@ void    msg_vprintf(int level, const char *format, va_list ap)
            msg_vstream_init("unknown", VSTREAM_ERR);
        vp = msg_buffers[msg_vprintf_level - 1];
        /* OK if terminating signal handler hijacks control before next stmt. */
-       vstring_vsprintf(vp, percentm(format, errno), ap);
+       vstring_vsprintf(vp, format, ap);
        printable(vstring_str(vp), '?');
        for (i = 0; i < msg_output_fn_count; i++)
            msg_output_fn[i] (level, vstring_str(vp));
diff --git a/postfix/src/util/percentm.c b/postfix/src/util/percentm.c
deleted file mode 100644 (file)
index 854f186..0000000
+++ /dev/null
@@ -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));
-}
-
diff --git a/postfix/src/util/percentm.h b/postfix/src/util/percentm.h
deleted file mode 100644 (file)
index d170e95..0000000
+++ /dev/null
@@ -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
index 148f2aa32eca01d10cd39a3cc43803d606ecec6f..60c5d9bc005817fe6e3f47c988e8b1b3d6f822ae 100644 (file)
@@ -526,8 +526,8 @@ static void verify_query_service(VSTREAM *client_stream)
     (addr_status != DEL_RCPT_STAT_OK && updated + var_verify_neg_try < now)
 
        if (now - probed > PROBE_TTL
-              && (POSITIVE_REFRESH_NEEDED(addr_status, updated)
-                  || NEGATIVE_REFRESH_NEEDED(addr_status, updated))) {
+           && (POSITIVE_REFRESH_NEEDED(addr_status, updated)
+               || NEGATIVE_REFRESH_NEEDED(addr_status, updated))) {
            if (msg_verbose)
                msg_info("PROBE %s status=%d probed=%ld updated=%ld",
                         STR(addr), addr_status, now, updated);
@@ -723,6 +723,21 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
     RESTORE_SAVED_EUGID();
 }
 
+/* post_accept_init - announce our protocol */
+
+static void post_accept_init(VSTREAM *stream, char *unused_name,
+                                  char **unused_argv, HTABLE *unused_table)
+{
+
+    /*
+     * Announce the protocol.
+     */
+    attr_print(stream, ATTR_FLAG_NONE,
+              SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_VERIFY),
+              ATTR_TYPE_END);
+    (void) vstream_fflush(stream);
+}
+
 MAIL_VERSION_STAMP_DECLARE;
 
 /* main - pass control to the multi-threaded skeleton */
@@ -754,6 +769,7 @@ int     main(int argc, char **argv)
                      CA_MAIL_SERVER_TIME_TABLE(time_table),
                      CA_MAIL_SERVER_PRE_INIT(pre_jail_init),
                      CA_MAIL_SERVER_POST_INIT(post_jail_init),
+                     CA_MAIL_SERVER_POST_ACCEPT(post_accept_init),
                      CA_MAIL_SERVER_SOLITARY,
                      CA_MAIL_SERVER_EXIT(verify_dump),
                      0);