]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.5-20071004
authorWietse Venema <wietse@porcupine.org>
Thu, 4 Oct 2007 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:33:22 +0000 (06:33 +0000)
52 files changed:
postfix/HISTORY
postfix/README_FILES/MILTER_README
postfix/README_FILES/XCLIENT_README
postfix/README_FILES/XFORWARD_README
postfix/WISHLIST
postfix/html/MILTER_README.html
postfix/html/XCLIENT_README.html
postfix/html/XFORWARD_README.html
postfix/html/pipe.8.html
postfix/html/regexp_table.5.html
postfix/html/smtp-sink.1.html
postfix/man/man1/smtp-sink.1
postfix/man/man5/regexp_table.5
postfix/man/man8/pipe.8
postfix/proto/MILTER_README.html
postfix/proto/XCLIENT_README.html
postfix/proto/XFORWARD_README.html
postfix/proto/regexp_table
postfix/src/cleanup/cleanup_milter.c
postfix/src/flush/flush.c
postfix/src/global/deliver_pass.c
postfix/src/global/deliver_request.c
postfix/src/global/deliver_request.h
postfix/src/global/mail_proto.h
postfix/src/global/mail_version.h
postfix/src/milter/milter.h
postfix/src/milter/test-milter.c
postfix/src/oqmgr/qmgr.h
postfix/src/oqmgr/qmgr_active.c
postfix/src/oqmgr/qmgr_deliver.c
postfix/src/oqmgr/qmgr_message.c
postfix/src/pipe/pipe.c
postfix/src/qmgr/qmgr.h
postfix/src/qmgr/qmgr_active.c
postfix/src/qmgr/qmgr_deliver.c
postfix/src/qmgr/qmgr_message.c
postfix/src/qmqpd/qmqpd.c
postfix/src/qmqpd/qmqpd.h
postfix/src/qmqpd/qmqpd_peer.c
postfix/src/smtp/smtp.h
postfix/src/smtp/smtp_proto.c
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd.h
postfix/src/smtpd/smtpd_milter.c
postfix/src/smtpd/smtpd_peer.c
postfix/src/smtpd/smtpd_proxy.c
postfix/src/smtpd/smtpd_xforward.c
postfix/src/smtpstone/smtp-sink.c
postfix/src/util/attr_scan0.c
postfix/src/util/attr_scan64.c
postfix/src/util/attr_scan_plain.c
postfix/src/util/events.c

index 8c7acdf968b9f5065366b50f4d44f46a79aa5a66..1fd2f8758b7a83d8d8210e4242f1194da3b482e4 100644 (file)
@@ -13712,3 +13712,47 @@ Apologies for any names omitted.
        unparsable canonical name caused the SMTPD policy client
        to allocate zero-length memory, triggering an assertion
        that it shouldn't do such things.  File: smtpd/smtpd_check.c.
+
+20070912
+
+       Bugfix (introduced Postfix 2.4) missing initialization of
+       event mask in the event_mask_drain() routine (used by the
+       obsolete postkick(1) command). Found by Coverity.  File:
+       util/events.c.
+
+20070917
+
+       Workaround: the flush daemon forces an access time update
+       for the per-destination logfile, to prevent an excessive
+       rate of delivery attempts when the queue file system is
+       mounted with "noatime".  File: flush/flush.c.
+
+20070923
+
+       Cleanup: don't complain when a "corrupt" queue file is 
+       deleted before it can be saved to the "corrupt" queue.
+       Files: *qmgr/qmgr_active.c.
+
+20071003
+
+       Logging: the Postfix SMTP server now logs the number of
+       bytes received after the DATA command when a connection
+       breaks before mail delivery completes.  This may help finding
+       the cause of the problem: packet loss, MTU, or other. File:
+       smtpd/smtpd.c.
+
+20071004
+
+       Logging: all daemons now log the TCP port number of remote
+       SMTP or QMQP clients.  The information is overruled with
+       the SMTP XCLIENT command, is propagated through SMTP-based
+       content filters with XFORWARD, and is sent to Milter
+       applications.  Files: smtpd/smtpd_peer.c, smtpd/smtpd.c,
+       smtpd/smtpd_proxy.c, smtpd/smtpd_milter.c, qmqpd/qmqpd_peer.c,
+       cleanup/cleanup_milter.c, *qmgr/qmgr_message.c,
+       *qmgr/qmgr_deliver.c, smtp/smtp_proto.c, pipe/pipe.c,
+       global/deliver_request.c, global/deliver_pass.c,
+       proto/XFORWARD_README, proto/XCLIENT_README.
+
+       Feature: per-command delays in smtp-sink. File:
+       smtpstone/smtp-sink.c.  Victor Duchovni.
index a667ce4118a5dbad2027d864cd828ad892c78999..6f0ca58e39c57a95e7a9b8bad7eb5bb776ed2b51 100644 (file)
@@ -7,14 +7,15 @@ I\bIn\bnt\btr\bro\bod\bdu\buc\bct\bti\bio\bon\bn
 Postfix version 2.3 introduces support for the Sendmail version 8 Milter (mail
 filter) protocol. This protocol is used by applications that run outside the
 MTA to inspect SMTP events (CONNECT, DISCONNECT), SMTP commands (HELO, MAIL
-FROM, etc.) as well as mail content. All this happens before mail is queued.
+FROM, etc.) as well as mail content (headers and body). All this happens before
+mail is queued.
 
 The reason for adding Milter support to Postfix is that there exists a large
 collection of applications, not only to block unwanted mail, but also to verify
-authenticity (examples: Domain keys identified mail, SenderID+SPF and Domain
-keys) or to digitally sign mail (examples: Domain keys identified mail, Domain
-keys). Having yet another Postfix-specific version of all that software is a
-poor use of human and system resources.
+authenticity (examples: DomainKeys Identified Mail (DKIM), SenderID+SPF and
+DomainKeys) or to digitally sign mail (examples: DomainKeys Identified Mail
+(DKIM), DomainKeys). Having yet another Postfix-specific version of all that
+software is a poor use of human and system resources.
 
 Postfix version 2.4 implements all the requests of Sendmail version 8 Milter
 protocols up to version 4, including message body replacement (body replacement
@@ -336,6 +337,9 @@ workarounds section below for solutions.
     |{client_name}       |Always                   |when lookup or            |
     |                    |                         |verification fails        |
     |_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
+    |{client_port}       |Always                   |Client TCP port           |
+    |                    |(Postfix >=2.5)          |                          |
+    |_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
     |                    |                         |Client name from reverse  |
     |{client_ptr}        |CONNECT, HELO, MAIL, DATA|lookup, "unknown" when    |
     |                    |                         |lookup fails              |
index f9b084eefeb2f466a8413a560d31d9bc9f717c63..d3ca8daac73363f3745bcda29b3c7b57ac1fa621 100644 (file)
@@ -48,7 +48,7 @@ are in fact case insensitive.
 
     xclient-command = XCLIENT 1*( SP attribute-name"="attribute-value )
 
-    attribute-name = ( NAME | ADDR | PROTO | HELO )
+    attribute-name = ( NAME | ADDR | PORT | PROTO | HELO )
 
     attribute-value = xtext
 
@@ -63,6 +63,9 @@ are in fact case insensitive.
     an IPv6 address prefixed with IPV6:, or [UNAVAILABLE] when the address
     information is unavailable. Address information is not enclosed with [].
 
+  * The PORT attribute specifies the SMTP client TCP port number as a decimal
+    number, or [UNAVAILABLE] when the information is unavailable.
+
   * The PROTO attribute specifies either SMTP or ESMTP.
 
   * The HELO attribute specifies an SMTP HELO parameter value, or the value
@@ -81,6 +84,9 @@ Note 3: Postfix implementations prior to version 2.3 do not xtext encode
 attribute values. Servers that wish to interoperate with these older
 implementations should be prepared to receive unencoded information.
 
+Note 4: Postfix implementations prior to version 2.5 do not implement the PORT
+attribute.
+
 X\bXC\bCL\bLI\bIE\bEN\bNT\bT S\bSe\ber\brv\bve\ber\br r\bre\bes\bsp\bpo\bon\bns\bse\be
 
 Upon receipt of a correctly formatted XCLIENT command, the server resets state
index dd6aa39c274fc9aeb6036d8df831dadd2a7c5e35..bd075127355a88f090f2621971f4c1b916b09b49 100644 (file)
@@ -41,7 +41,7 @@ are in fact case insensitive.
 
     xforward-command = XFORWARD 1*( SP attribute-name"="attribute-value )
 
-    attribute-name = ( NAME | ADDR | PROTO | HELO | SOURCE )
+    attribute-name = ( NAME | ADDR | PORT | PROTO | HELO | SOURCE )
 
     attribute-value = xtext
 
@@ -54,6 +54,9 @@ are in fact case insensitive.
     [UNAVAILABLE] when the information is unavailable. Address information is
     not enclosed with []. The address may be a non-IP address.
 
+  * The PORT attribute specifies an up-stream client TCP port number in
+    decimal, or [UNAVAILABLE] when the information is unavailable.
+
   * The PROTO attribute specifies the mail protocol for receiving mail from the
     up-stream host. This may be an SMTP or non-SMTP protocol name of up to 64
     characters, or [UNAVAILABLE] when the information is unavailable.
index 2d41e5cd63991fde222f5ac6670d8246f24a824c..ceb73dee81ffb76c4778eaa3338412d8b40481d1 100644 (file)
@@ -1,5 +1,12 @@
 Wish list:
 
+       Combine smtpd_peer.c and qmqpd_peer.c into a single function
+       that produces a client context object, and provide attribute
+       print/scan routines that pass these client context objects
+       around. With this, we no longer have to update a multiple
+       pieces of code when a client attribute is added. Ditto for
+       SASL and TLS context.
+
        Make TLS_BIO_BUFSIZE run-time adjustable, to future-proof
        Postfix for remote connections with MSS > 8 kbytes.
 
index 226f62e2ebdc00b72553ddece23dcf8319b6728a..4236a3bc6dc3c63157e790243150be1c2c1070f8 100644 (file)
 <p> Postfix version 2.3 introduces support for the Sendmail version
 8 Milter (mail filter) protocol. This protocol is used by applications
 that run outside the MTA to inspect SMTP events (CONNECT, DISCONNECT),
-SMTP commands (HELO, MAIL FROM, etc.) as well as mail content.  All
-this happens before mail is queued.  </p>
+SMTP commands (HELO, MAIL FROM, etc.) as well as mail content (headers
+and body).  All this happens before mail is queued.  </p>
 
 <p> The reason for adding Milter support to Postfix is that there
 exists a large collection of applications, not only to block unwanted
 mail, but also to verify authenticity (examples: <a
-href="http://sourceforge.net/projects/dkim-milter/">Domain keys
-identified mail</a>, <a
+href="http://sourceforge.net/projects/dkim-milter/">DomainKeys
+Identified Mail (DKIM)</a>, <a
 href="http://sourceforge.net/projects/sid-milter/">SenderID+SPF</a> and
-<a href="http://sourceforge.net/projects/dk-milter/">Domain keys</a>)
+<a href="http://sourceforge.net/projects/dk-milter/">DomainKeys</a>)
 or to digitally sign mail (examples: <a
-href="http://sourceforge.net/projects/dkim-milter/">Domain keys
-identified mail</a>, <a
-href="http://sourceforge.net/projects/dk-milter/">Domain keys</a>).
+href="http://sourceforge.net/projects/dkim-milter/">DomainKeys
+Identified Mail (DKIM)</a>, <a
+href="http://sourceforge.net/projects/dk-milter/">DomainKeys</a>).
 Having yet another Postfix-specific version of all that software
 is a poor use of human and system resources. </p>
 
@@ -548,6 +548,9 @@ Connection concurrency for this client </td> </tr>
 <tr> <td> {client_name} </td> <td> Always </td> <td> Client hostname,
 "unknown" when lookup or verification fails </td> </tr>
 
+<tr> <td> {client_port} </td> <td> Always <br> (Postfix &ge;2.5) </td>
+<td> Client TCP port </td> </tr>
+
 <tr> <td> {client_ptr} </td> <td> CONNECT, HELO, MAIL, DATA </td>
 <td> Client name from reverse lookup, "unknown" when lookup fails
 </td> </tr>
index 09425094ee8f0db67684baa06195f9da7cd78a76..c66093482dbb8b7c3295ad59b279112f0d8860e0 100644 (file)
@@ -77,7 +77,7 @@ names are shown in upper case, they are in fact case insensitive.
     xclient-command = XCLIENT 1*( SP attribute-name"="attribute-value )
 </p>
 <p>
-    attribute-name = ( NAME | ADDR | PROTO | HELO )
+    attribute-name = ( NAME | ADDR | PORT | PROTO | HELO )
 </p>
 <p>
     attribute-value = xtext
@@ -86,7 +86,7 @@ names are shown in upper case, they are in fact case insensitive.
 
 <ul>
 
-    <li> <p> Attribute values are xtext encoded as per <a href="http://www.faqs.org/rfcs/rfc1891.html">RFC 1891</a>.
+    <li> <p> Attribute values are xtext encoded as per <a href="http://tools.ietf.org/html/rfc1891">RFC 1891</a>.
     </p>
 
     <li> <p> The NAME attribute specifies an SMTP client hostname
@@ -99,6 +99,10 @@ names are shown in upper case, they are in fact case insensitive.
     [UNAVAILABLE] when the address information is unavailable.
     Address information is not enclosed with []. </p>
 
+    <li> <p> The PORT attribute specifies the SMTP client TCP port
+    number as a decimal number, or [UNAVAILABLE] when the information
+    is unavailable.  </p>
+
     <li> <p> The PROTO attribute specifies either SMTP or ESMTP.
     </p>
 
@@ -123,6 +127,9 @@ xtext encode attribute values. Servers that wish to interoperate
 with these older implementations should be prepared to receive
 unencoded information. </p>
 
+<p> Note 4: Postfix implementations prior to version 2.5 do not
+implement the PORT attribute.  </p>
+
 <h2>XCLIENT Server response</h2>
 
 <p> Upon receipt of a correctly formatted XCLIENT command, the
@@ -236,7 +243,7 @@ before each MAIL FROM command. </p>
 <h2> References </h2>
 
 <p> Moore, K, "SMTP Service Extension for Delivery Status Notifications",
-<a href="http://www.faqs.org/rfcs/rfc1891.html">RFC 1891</a>, January 1996. </p>
+<a href="http://tools.ietf.org/html/rfc1891">RFC 1891</a>, January 1996. </p>
 
 </body>
 
index 1847d3cdd0c5065de54e218d3ff2e93d75bc9e56..10eaf96ee9eef77611c4985d6dc2b1287905eb14 100644 (file)
@@ -68,7 +68,7 @@ names are shown in upper case, they are in fact case insensitive.
     xforward-command = XFORWARD 1*( SP attribute-name"="attribute-value )
 </p>
 <p>
-    attribute-name = ( NAME | ADDR | PROTO | HELO | SOURCE )
+    attribute-name = ( NAME | ADDR | PORT | PROTO | HELO | SOURCE )
 </p>
 <p>
     attribute-value = xtext
@@ -77,7 +77,7 @@ names are shown in upper case, they are in fact case insensitive.
 
 <ul>
 
-    <li> <p> Attribute values are xtext encoded as per <a href="http://www.faqs.org/rfcs/rfc1891.html">RFC 1891</a>.
+    <li> <p> Attribute values are xtext encoded as per <a href="http://tools.ietf.org/html/rfc1891">RFC 1891</a>.
     </p>
 
     <li> <p> The NAME attribute specifies the up-stream hostname,
@@ -89,6 +89,10 @@ names are shown in upper case, they are in fact case insensitive.
     Address information is not enclosed with []. The address may
     be a non-IP address. </p>
 
+    <li> <p> The PORT attribute specifies an up-stream client TCP
+    port number in decimal, or [UNAVAILABLE] when the information
+    is unavailable.  </p>
+
     <li> <p> The PROTO attribute specifies the mail protocol for
     receiving mail from the up-stream host. This may be an SMTP or
     non-SMTP protocol name of up to 64 characters, or [UNAVAILABLE]
@@ -211,7 +215,7 @@ so there is no risk of information leakage. </p>
 <h2> References </h2>
 
 <p> Moore, K, "SMTP Service Extension for Delivery Status Notifications",
-<a href="http://www.faqs.org/rfcs/rfc1891.html">RFC 1891</a>, January 1996. </p>
+<a href="http://tools.ietf.org/html/rfc1891">RFC 1891</a>, January 1996. </p>
 
 </body>
 
index 539ef320f27ca01a94f1567085ee08998181d868..7f26870f37295f1cbafcb805e542628fb365e1a9 100644 (file)
@@ -239,6 +239,12 @@ PIPE(8)                                                                PIPE(8)
 
                      This is available in Postfix 2.2 and  later.
 
+              <b>${client_port</b>}
+                     This  macro expands to the remote client TCP
+                     port number.
+
+                     This is available in Postfix 2.5 and  later.
+
               <b>${client_protocol</b>}
                      This macro expands to the remote client pro-
                      tocol.
index 5ec01696fca57f568a2a578ef53b7fc20c7fa2d7..3261a4b9040476db3433db56edf712319cd423e6 100644 (file)
@@ -99,11 +99,6 @@ REGEXP_TABLE(5)                                                REGEXP_TABLE(5)
               Toggles  the  case  sensitivity  flag.  By default,
               matching is case insensitive.
 
-       <b>x</b> (default: on)
-              Toggles the extended  expression  syntax  flag.  By
-              default,  support for extended expression syntax is
-              enabled.
-
        <b>m</b> (default: off)
               Toggle the multi-line mode flag. When this flag  is
               on,  the  <b>^</b>  and <b>$</b> metacharacters match immediately
@@ -111,6 +106,11 @@ REGEXP_TABLE(5)                                                REGEXP_TABLE(5)
               respectively,  in addition to matching at the start
               and end of the input string.
 
+       <b>x</b> (default: on)
+              Toggles the extended  expression  syntax  flag.  By
+              default,  support for extended expression syntax is
+              enabled.
+
 <b>TABLE SEARCH ORDER</b>
        Patterns are applied in the order as specified in the  ta-
        ble,  until  a  pattern  is  found  that matches the input
index 6dfc676fedaf3ab857f47cba93751a8b882a0534..c8cf0592e64a72e37b8380f4fa56e89a2fbbc3df 100644 (file)
@@ -185,6 +185,15 @@ SMTP-SINK(1)                                                      SMTP-SINK(1)
               Wait <i>delay</i> seconds before responding to a DATA com-
               mand.
 
+       <b>-W</b> <i>command:delay[:odds]</i>
+              Wait  <i>delay</i>  seconds  before responding to <i>command</i>.
+              If <i>odds</i> is also specified (a  number  between  1-99
+              inclusive),  wait  for  a random multiple of <i>delay</i>.
+              The random multiplier is equal  to  the  number  of
+              times the program needs to roll a dice with a range
+              of 0..99 inclusive,  before  the  dice  produces  a
+              result greater than or equal to <i>odds</i>.
+
        [<b>inet:</b>][<i>host</i>]:<i>port</i>
               Listen  on  network  interface  <i>host</i>  (default: any
               interface) TCP port <i>port</i>. Both <i>host</i> and <i>port</i> may be
index b03f7ad92898245bcf70e649ef2f702932545411..11cc709689e16d54043cce6d8759698ef4f38518 100644 (file)
@@ -156,6 +156,13 @@ with super-user privileges. See also the \fB-R\fR option.
 Show the SMTP conversations.
 .IP "\fB-w \fIdelay\fR"
 Wait \fIdelay\fR seconds before responding to a DATA command.
+.IP "\fB-W \fIcommand:delay[:odds]\fR"
+Wait \fIdelay\fR seconds before responding to \fIcommand\fR.
+If \fIodds\fR is also specified (a number between 1-99
+inclusive), wait for a random multiple of \fIdelay\fR. The
+random multiplier is equal to the number of times the program
+needs to roll a dice with a range of 0..99 inclusive, before
+the dice produces a result greater than or equal to \fIodds\fR.
 .IP [\fBinet:\fR][\fIhost\fR]:\fIport\fR
 Listen on network interface \fIhost\fR (default: any interface)
 TCP port \fIport\fR. Both \fIhost\fR and \fIport\fR may be
index 4b4d98231af7178338eb01533fcf1476cba994b3..d67d710a825a5e973b7dbc8eb9850e6c612284a4 100644 (file)
@@ -91,14 +91,14 @@ characters after the pattern:
 .IP "\fBi\fR (default: on)"
 Toggles the case sensitivity flag. By default, matching is case
 insensitive.
-.IP "\fBx\fR (default: on)"
-Toggles the extended expression syntax flag. By default, support
-for extended expression syntax is enabled.
 .IP "\fBm\fR (default: off)"
 Toggle the multi-line mode flag. When this flag is on, the \fB^\fR
 and \fB$\fR metacharacters match immediately after and immediately
 before a newline character, respectively, in addition to
 matching at the start and end of the input string.
+.IP "\fBx\fR (default: on)"
+Toggles the extended expression syntax flag. By default, support
+for extended expression syntax is enabled.
 .SH "TABLE SEARCH ORDER"
 .na
 .nf
index 8f4fa8535f83da5b8fb2880b078daaf293549529..13c767013209b8fc094be4d11ba8853940416ce9 100644 (file)
@@ -216,6 +216,10 @@ This is available in Postfix 2.2 and later.
 This macro expands to the remote client hostname.
 .sp
 This is available in Postfix 2.2 and later.
+.IP \fB${\fBclient_port\fR}\fR
+This macro expands to the remote client TCP port number.
+.sp
+This is available in Postfix 2.5 and later.
 .IP \fB${\fBclient_protocol\fR}\fR
 This macro expands to the remote client protocol.
 .sp
index a5a3d2753bb07d4ea33b34d1bb28a8af2d84f5c4..edef90fde5842f3be8fdbc04eba6ecc91428fa71 100644 (file)
 <p> Postfix version 2.3 introduces support for the Sendmail version
 8 Milter (mail filter) protocol. This protocol is used by applications
 that run outside the MTA to inspect SMTP events (CONNECT, DISCONNECT),
-SMTP commands (HELO, MAIL FROM, etc.) as well as mail content.  All
-this happens before mail is queued.  </p>
+SMTP commands (HELO, MAIL FROM, etc.) as well as mail content (headers
+and body).  All this happens before mail is queued.  </p>
 
 <p> The reason for adding Milter support to Postfix is that there
 exists a large collection of applications, not only to block unwanted
 mail, but also to verify authenticity (examples: <a
-href="http://sourceforge.net/projects/dkim-milter/">Domain keys
-identified mail</a>, <a
+href="http://sourceforge.net/projects/dkim-milter/">DomainKeys
+Identified Mail (DKIM)</a>, <a
 href="http://sourceforge.net/projects/sid-milter/">SenderID+SPF</a> and
-<a href="http://sourceforge.net/projects/dk-milter/">Domain keys</a>)
+<a href="http://sourceforge.net/projects/dk-milter/">DomainKeys</a>)
 or to digitally sign mail (examples: <a
-href="http://sourceforge.net/projects/dkim-milter/">Domain keys
-identified mail</a>, <a
-href="http://sourceforge.net/projects/dk-milter/">Domain keys</a>).
+href="http://sourceforge.net/projects/dkim-milter/">DomainKeys
+Identified Mail (DKIM)</a>, <a
+href="http://sourceforge.net/projects/dk-milter/">DomainKeys</a>).
 Having yet another Postfix-specific version of all that software
 is a poor use of human and system resources. </p>
 
@@ -548,6 +548,9 @@ Connection concurrency for this client </td> </tr>
 <tr> <td> {client_name} </td> <td> Always </td> <td> Client hostname,
 "unknown" when lookup or verification fails </td> </tr>
 
+<tr> <td> {client_port} </td> <td> Always <br> (Postfix &ge;2.5) </td>
+<td> Client TCP port </td> </tr>
+
 <tr> <td> {client_ptr} </td> <td> CONNECT, HELO, MAIL, DATA </td>
 <td> Client name from reverse lookup, "unknown" when lookup fails
 </td> </tr>
index 3fe786047a28deefd205b7da737fff08acc1fece..cfa3852858bb854b341a5734f2bc1bff89dcfabf 100644 (file)
@@ -77,7 +77,7 @@ names are shown in upper case, they are in fact case insensitive.
     xclient-command = XCLIENT 1*( SP attribute-name"="attribute-value )
 </p>
 <p>
-    attribute-name = ( NAME | ADDR | PROTO | HELO )
+    attribute-name = ( NAME | ADDR | PORT | PROTO | HELO )
 </p>
 <p>
     attribute-value = xtext
@@ -99,6 +99,10 @@ names are shown in upper case, they are in fact case insensitive.
     [UNAVAILABLE] when the address information is unavailable.
     Address information is not enclosed with []. </p>
 
+    <li> <p> The PORT attribute specifies the SMTP client TCP port
+    number as a decimal number, or [UNAVAILABLE] when the information
+    is unavailable.  </p>
+
     <li> <p> The PROTO attribute specifies either SMTP or ESMTP.
     </p>
 
@@ -123,6 +127,9 @@ xtext encode attribute values. Servers that wish to interoperate
 with these older implementations should be prepared to receive
 unencoded information. </p>
 
+<p> Note 4: Postfix implementations prior to version 2.5 do not
+implement the PORT attribute.  </p>
+
 <h2>XCLIENT Server response</h2>
 
 <p> Upon receipt of a correctly formatted XCLIENT command, the
index 01c373f0807bf550a14f2e0b0855ea4584036abd..7af960cc00cb43017f341afb8e0e7dda94efa1a5 100644 (file)
@@ -68,7 +68,7 @@ names are shown in upper case, they are in fact case insensitive.
     xforward-command = XFORWARD 1*( SP attribute-name"="attribute-value )
 </p>
 <p>
-    attribute-name = ( NAME | ADDR | PROTO | HELO | SOURCE )
+    attribute-name = ( NAME | ADDR | PORT | PROTO | HELO | SOURCE )
 </p>
 <p>
     attribute-value = xtext
@@ -89,6 +89,10 @@ names are shown in upper case, they are in fact case insensitive.
     Address information is not enclosed with []. The address may
     be a non-IP address. </p>
 
+    <li> <p> The PORT attribute specifies an up-stream client TCP
+    port number in decimal, or [UNAVAILABLE] when the information
+    is unavailable.  </p>
+
     <li> <p> The PROTO attribute specifies the mail protocol for
     receiving mail from the up-stream host. This may be an SMTP or
     non-SMTP protocol name of up to 64 characters, or [UNAVAILABLE]
index 6e225b33cb6c9f448b32b3a7105a9b643dae6f0d..5375ad787e765ba71b071a7137adfd18e7d28d80 100644 (file)
 # .IP "\fBi\fR (default: on)"
 #      Toggles the case sensitivity flag. By default, matching is case
 #      insensitive.
-# .IP "\fBx\fR (default: on)"
-#      Toggles the extended expression syntax flag. By default, support
-#      for extended expression syntax is enabled.
 # .IP "\fBm\fR (default: off)"
 #      Toggle the multi-line mode flag. When this flag is on, the \fB^\fR
 #      and \fB$\fR metacharacters match immediately after and immediately
 #      before a newline character, respectively, in addition to
 #      matching at the start and end of the input string.
+# .IP "\fBx\fR (default: on)"
+#      Toggles the extended expression syntax flag. By default, support
+#      for extended expression syntax is enabled.
 # TABLE SEARCH ORDER
 # .ad
 # .fi
index 51755e8f308558deed174ab49de95273732e7881..cb30af472790b3cdbeae761200705b9ccac185df 100644 (file)
@@ -1283,6 +1283,8 @@ static const char *cleanup_milter_eval(const char *name, void *ptr)
        return (state->client_addr);
     if (strcmp(name, S8_MAC_CLIENT_NAME) == 0)
        return (state->client_name);
+    if (strcmp(name, S8_MAC_CLIENT_PORT) == 0)
+       return (state->client_port);
     if (strcmp(name, S8_MAC_CLIENT_PTR) == 0)
        return (state->reverse_name);
 
@@ -1450,6 +1452,7 @@ static void cleanup_milter_client_init(CLEANUP_STATE *state)
        state->client_af = atoi(proto_attr);
     if (state->reverse_name == 0)
        state->reverse_name = state->client_name;
+    /* Compatibility with pre-2.5 queue files. */
     if (state->client_port == 0)
        state->client_port = NO_CLIENT_PORT;
 }
index 41ffafa87f14719a43f3e184148cfb8b91dc335e..853769144174febf44fc2744071b59336a46a48c 100644 (file)
 
 #include <sys_defs.h>
 #include <sys/stat.h>
+#include <sys/time.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <utime.h>
@@ -576,6 +577,11 @@ static int flush_send_path(const char *path, int how)
     if (count > 0 && ftruncate(vstream_fileno(log), (off_t) 0) < 0)
        msg_fatal("%s: truncate fast flush logfile %s: %m", myname, path);
 
+    /*
+     * Workaround for noatime mounts. Use futimes() if available.
+     */
+    (void) utimes(VSTREAM_PATH(log), (struct timeval *) 0);
+
     /*
      * Request delivery and clean up.
      */
index 603b04b383a31d3ba115e54c4c360495ddc0a030..5799597aaae843e9efac160a13ca04c7e10733ba 100644 (file)
@@ -109,13 +109,17 @@ static int deliver_pass_send_request(VSTREAM *stream, DELIVER_REQUEST *request,
               ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, request->dsn_envid,
               ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, request->dsn_ret,
               ATTR_TYPE_FUNC, msg_stats_print, (void *) &request->msg_stats,
+    /* XXX Should be encapsulated with ATTR_TYPE_FUNC. */
             ATTR_TYPE_STR, MAIL_ATTR_LOG_CLIENT_NAME, request->client_name,
             ATTR_TYPE_STR, MAIL_ATTR_LOG_CLIENT_ADDR, request->client_addr,
+            ATTR_TYPE_STR, MAIL_ATTR_LOG_CLIENT_PORT, request->client_port,
             ATTR_TYPE_STR, MAIL_ATTR_LOG_PROTO_NAME, request->client_proto,
               ATTR_TYPE_STR, MAIL_ATTR_LOG_HELO_NAME, request->client_helo,
+    /* XXX Should be encapsulated with ATTR_TYPE_FUNC. */
               ATTR_TYPE_STR, MAIL_ATTR_SASL_METHOD, request->sasl_method,
             ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, request->sasl_username,
               ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, request->sasl_sender,
+    /* XXX Ditto if we want to pass TLS certificate info. */
             ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, request->rewrite_context,
               ATTR_TYPE_INT, MAIL_ATTR_RCPT_COUNT, 1,
               ATTR_TYPE_END);
index 17be6541e2bce835aaa97341594180b99f12a5de..7ee6dbabbda0d2ea192f775d71272dd953387322 100644 (file)
@@ -22,6 +22,7 @@
 /*             DSN     *hop_status;
 /*             char    *client_name;
 /*             char    *client_addr;
+/*             char    *client_port;
 /*             char    *client_proto;
 /*             char    *client_helo;
 /*             char    *sasl_method;
@@ -195,6 +196,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
     static VSTRING *address;
     static VSTRING *client_name;
     static VSTRING *client_addr;
+    static VSTRING *client_port;
     static VSTRING *client_proto;
     static VSTRING *client_helo;
     static VSTRING *sasl_method;
@@ -219,6 +221,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
        address = vstring_alloc(10);
        client_name = vstring_alloc(10);
        client_addr = vstring_alloc(10);
+       client_port = vstring_alloc(10);
        client_proto = vstring_alloc(10);
        client_helo = vstring_alloc(10);
        sasl_method = vstring_alloc(10);
@@ -245,16 +248,20 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
                  ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid,
                  ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, &dsn_ret,
               ATTR_TYPE_FUNC, msg_stats_scan, (void *) &request->msg_stats,
+    /* XXX Should be encapsulated with ATTR_TYPE_FUNC. */
                  ATTR_TYPE_STR, MAIL_ATTR_LOG_CLIENT_NAME, client_name,
                  ATTR_TYPE_STR, MAIL_ATTR_LOG_CLIENT_ADDR, client_addr,
+                 ATTR_TYPE_STR, MAIL_ATTR_LOG_CLIENT_PORT, client_port,
                  ATTR_TYPE_STR, MAIL_ATTR_LOG_PROTO_NAME, client_proto,
                  ATTR_TYPE_STR, MAIL_ATTR_LOG_HELO_NAME, client_helo,
+    /* XXX Should be encapsulated with ATTR_TYPE_FUNC. */
                  ATTR_TYPE_STR, MAIL_ATTR_SASL_METHOD, sasl_method,
                  ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, sasl_username,
                  ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, sasl_sender,
+    /* XXX Ditto if we want to pass TLS certificate info. */
                  ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, rewrite_context,
                  ATTR_TYPE_INT, MAIL_ATTR_RCPT_COUNT, &rcpt_count,
-                 ATTR_TYPE_END) != 20) {
+                 ATTR_TYPE_END) != 21) {
        msg_warn("%s: error receiving common attributes", myname);
        return (-1);
     }
@@ -273,6 +280,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
     request->sender = mystrdup(vstring_str(address));
     request->client_name = mystrdup(vstring_str(client_name));
     request->client_addr = mystrdup(vstring_str(client_addr));
+    request->client_port = mystrdup(vstring_str(client_port));
     request->client_proto = mystrdup(vstring_str(client_proto));
     request->client_helo = mystrdup(vstring_str(client_helo));
     request->sasl_method = mystrdup(vstring_str(sasl_method));
@@ -353,6 +361,7 @@ static DELIVER_REQUEST *deliver_request_alloc(void)
     request->hop_status = 0;
     request->client_name = 0;
     request->client_addr = 0;
+    request->client_port = 0;
     request->client_proto = 0;
     request->client_helo = 0;
     request->sasl_method = 0;
@@ -386,6 +395,8 @@ static void deliver_request_free(DELIVER_REQUEST *request)
        myfree(request->client_name);
     if (request->client_addr)
        myfree(request->client_addr);
+    if (request->client_port)
+       myfree(request->client_port);
     if (request->client_proto)
        myfree(request->client_proto);
     if (request->client_helo)
index e0d520ae94e8acea9da5e63f10e88b0689767119..8f4298d723d409c601d18645652b3cbddb5d0c22 100644 (file)
@@ -42,6 +42,7 @@ typedef struct DELIVER_REQUEST {
     DSN    *hop_status;                        /* DSN status */
     char   *client_name;               /* client hostname */
     char   *client_addr;               /* client address */
+    char   *client_port;               /* client port */
     char   *client_proto;              /* client protocol */
     char   *client_helo;               /* helo parameter */
     char   *sasl_method;               /* SASL method */
index 0d5a174afff72b365ee90372f5154894ab797250..89b16883b6cc5ef8e6f22801ef7e1905e2eeea2c 100644 (file)
@@ -5,7 +5,7 @@
 /* NAME
 /*     mail_proto 3h
 /* SUMMARY
-/*     mail internal IPC support
+/*     mail internal and external protocol support
 /* SYNOPSIS
 /*     #include <mail_proto.h>
 /* DESCRIPTION
@@ -169,9 +169,10 @@ extern char *mail_pathname(const char *, const char *);
 
 #define MAIL_ATTR_LOG_CLIENT_NAME "log_client_name"    /* client hostname */
 #define MAIL_ATTR_LOG_CLIENT_ADDR "log_client_address" /* client address */
+#define MAIL_ATTR_LOG_CLIENT_PORT "log_client_port"    /* client port */
 #define MAIL_ATTR_LOG_HELO_NAME        "log_helo_name" /* SMTP helo name */
 #define MAIL_ATTR_LOG_PROTO_NAME "log_protocol_name"   /* SMTP/ESMTP/QMQP */
-#define MAIL_ATTR_LOG_ORIGIN   "log_message_origin"    /* hostname[address] */
+#define MAIL_ATTR_LOG_ORIGIN   "log_message_origin"    /* name[addr]:port */
 
 #define MAIL_ATTR_ACT_CLIENT   "client"/* client name addr */
 #define MAIL_ATTR_ACT_CLIENT_NAME "client_name"        /* client name */
@@ -191,27 +192,29 @@ extern char *mail_pathname(const char *, const char *);
   * XCLIENT/XFORWARD in SMTP.
   */
 #define XCLIENT_CMD            "XCLIENT"       /* XCLIENT command */
-#define XCLIENT_NAME           "NAME"          /* client name */
+#define XCLIENT_NAME           "NAME"  /* client name */
 #define XCLIENT_REVERSE_NAME   "REVERSE_NAME"  /* reverse client name */
 #ifdef FORWARD_CLIENT_NAME
 #define XCLIENT_FORWARD_NAME   "FORWARD_NAME"  /* forward client name */
 #endif
-#define XCLIENT_ADDR           "ADDR"          /* client address */
-#define XCLIENT_PROTO          "PROTO"         /* client protocol */
-#define XCLIENT_HELO           "HELO"          /* client helo */
+#define XCLIENT_ADDR           "ADDR"  /* client address */
+#define XCLIENT_PORT           "PORT"  /* client port */
+#define XCLIENT_PROTO          "PROTO" /* client protocol */
+#define XCLIENT_HELO           "HELO"  /* client helo */
 
 #define XCLIENT_UNAVAILABLE    "[UNAVAILABLE]" /* permanently unavailable */
 #define XCLIENT_TEMPORARY      "[TEMPUNAVAIL]" /* temporarily unavailable */
 
 #define XFORWARD_CMD           "XFORWARD"      /* XFORWARD command */
-#define XFORWARD_NAME          "NAME"          /* client name */
-#define XFORWARD_ADDR          "ADDR"          /* client address */
-#define XFORWARD_PROTO         "PROTO"         /* client protocol */
-#define XFORWARD_HELO          "HELO"          /* client helo */
-#define XFORWARD_IDENT         "IDENT"         /* message identifier */
-#define XFORWARD_DOMAIN                "SOURCE"        /* origin type */
-#define XFORWARD_DOM_LOCAL     "LOCAL"         /* local origin */
-#define XFORWARD_DOM_REMOTE    "REMOTE"        /* remote origin */
+#define XFORWARD_NAME          "NAME"  /* client name */
+#define XFORWARD_ADDR          "ADDR"  /* client address */
+#define XFORWARD_PORT          "PORT"  /* client port */
+#define XFORWARD_PROTO         "PROTO" /* client protocol */
+#define XFORWARD_HELO          "HELO"  /* client helo */
+#define XFORWARD_IDENT         "IDENT" /* message identifier */
+#define XFORWARD_DOMAIN                "SOURCE"/* origin type */
+#define XFORWARD_DOM_LOCAL     "LOCAL" /* local origin */
+#define XFORWARD_DOM_REMOTE    "REMOTE"/* remote origin */
 
 #define XFORWARD_UNAVAILABLE   "[UNAVAILABLE]" /* attribute unavailable */
 
index 19fd0c0c9152846e6c096e51dde67683fb8c1325..eeb6dca2922f88e5205d2e287a290049e70db970 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      "20070911"
+#define MAIL_RELEASE_DATE      "20071004"
 #define MAIL_VERSION_NUMBER    "2.5"
 
 #ifdef SNAPSHOT
index e0a4067efb3f17ac2ab573f38a2d8b5d061f610c..b29fff511d468ade5de8805065441825a642ea9f 100644 (file)
@@ -125,6 +125,7 @@ extern void milter_free(MILTERS *);
 #define S8_MAC_CLIENT_ADDR     "{client_addr}"
 #define S8_MAC_CLIENT_CONN     "{client_connections}"
 #define S8_MAC_CLIENT_NAME     "{client_name}"
+#define S8_MAC_CLIENT_PORT     "{client_port}"
 #define S8_MAC_CLIENT_PTR      "{client_ptr}"
 #define S8_MAC_CLIENT_RES      "{client_resolve}"
 
index 0c33d8a5a7cf22d114e0de854e62210e27f2bf46..c645b316ed44859999b711fa4e7f3a4176eb110c 100644 (file)
@@ -162,7 +162,7 @@ static sfsistat test_connect(SMFICTX *ctx, char *name, struct sockaddr * sa)
            print_addr = inet_ntop(AF_INET, &sin->sin_addr, buf, sizeof(buf));
            if (print_addr == 0)
                print_addr = strerror(errno);
-           printf("AF_INET (%s)\n", print_addr);
+           printf("AF_INET (%s:%d)\n", print_addr, ntohs(sin->sin_port));
        }
        break;
 #ifdef HAS_IPV6
@@ -173,7 +173,7 @@ static sfsistat test_connect(SMFICTX *ctx, char *name, struct sockaddr * sa)
            print_addr = inet_ntop(AF_INET, &sin6->sin6_addr, buf, sizeof(buf));
            if (print_addr == 0)
                print_addr = strerror(errno);
-           printf("AF_INET6 (%s)\n", print_addr);
+           printf("AF_INET6 (%s:%d)\n", print_addr, ntohs(sin6->sin6_port));
        }
        break;
 #endif
index 20f8c3a1861b269d1761caf643dc59a83a910f59..bcc33aadc4e0ce82eb45b48c90009c65770c6c15 100644 (file)
@@ -235,6 +235,7 @@ struct QMGR_MESSAGE {
     long    rcpt_offset;               /* more recipients here */
     char   *client_name;               /* client hostname */
     char   *client_addr;               /* client address */
+    char   *client_port;               /* client port */
     char   *client_proto;              /* client protocol */
     char   *client_helo;               /* helo parameter */
     char   *sasl_method;               /* SASL method */
index 59bae9af82e1af3882743ff3f3c866cec5714825..eeec88d3b40d81dbc4f57d157af5db7bd799dd70 100644 (file)
@@ -130,8 +130,6 @@ static void qmgr_active_corrupt(const char *queue_id)
        if (errno != ENOENT)
            msg_fatal("%s: save corrupt file queue %s id %s: %m",
                      myname, MAIL_QUEUE_ACTIVE, queue_id);
-       msg_warn("%s: save corrupt file queue %s id %s: %m",
-                myname, MAIL_QUEUE_ACTIVE, queue_id);
     } else {
        msg_warn("saving corrupt file \"%s\" from queue \"%s\" to queue \"%s\"",
                 queue_id, MAIL_QUEUE_ACTIVE, MAIL_QUEUE_CORRUPT);
index 7e06b5dc5b8dae99178d79ffe80cbc33106f270b..e952b36608f2b8e9a2269c49a2dcce505e164a39 100644 (file)
@@ -165,13 +165,17 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
               ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, message->dsn_envid,
               ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, message->dsn_ret,
               ATTR_TYPE_FUNC, msg_stats_print, (void *) &stats,
+    /* XXX Should be encapsulated with ATTR_TYPE_FUNC. */
             ATTR_TYPE_STR, MAIL_ATTR_LOG_CLIENT_NAME, message->client_name,
             ATTR_TYPE_STR, MAIL_ATTR_LOG_CLIENT_ADDR, message->client_addr,
+            ATTR_TYPE_STR, MAIL_ATTR_LOG_CLIENT_PORT, message->client_port,
             ATTR_TYPE_STR, MAIL_ATTR_LOG_PROTO_NAME, message->client_proto,
               ATTR_TYPE_STR, MAIL_ATTR_LOG_HELO_NAME, message->client_helo,
+    /* XXX Should be encapsulated with ATTR_TYPE_FUNC. */
               ATTR_TYPE_STR, MAIL_ATTR_SASL_METHOD, message->sasl_method,
             ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, message->sasl_username,
               ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, message->sasl_sender,
+    /* XXX Ditto if we want to pass TLS certificate info. */
             ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, message->rewrite_context,
               ATTR_TYPE_INT, MAIL_ATTR_RCPT_COUNT, list.len,
               ATTR_TYPE_END);
index 4e3938506deb90029c16b4e0c5879ad35eeacf8c..f5fdd4a037b5523c9155ea70ccfec3d7feab12de 100644 (file)
@@ -179,6 +179,7 @@ static QMGR_MESSAGE *qmgr_message_create(const char *queue_name,
     message->verp_delims = 0;
     message->client_name = 0;
     message->client_addr = 0;
+    message->client_port = 0;
     message->client_proto = 0;
     message->client_helo = 0;
     message->sasl_method = 0;
@@ -634,6 +635,10 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
                if (message->client_addr != 0)
                    myfree(message->client_addr);
                message->client_addr = mystrdup(value);
+           } else if (strcmp(name, MAIL_ATTR_LOG_CLIENT_PORT) == 0) {
+               if (message->client_port != 0)
+                   myfree(message->client_port);
+               message->client_port = mystrdup(value);
            } else if (strcmp(name, MAIL_ATTR_LOG_PROTO_NAME) == 0) {
                if (message->client_proto != 0)
                    myfree(message->client_proto);
@@ -735,6 +740,8 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
        message->client_name = mystrdup("");
     if (message->client_addr == 0)
        message->client_addr = mystrdup("");
+    if (message->client_port == 0)
+       message->client_port = mystrdup("");
     if (message->client_proto == 0)
        message->client_proto = mystrdup("");
     if (message->client_helo == 0)
@@ -1253,6 +1260,8 @@ void    qmgr_message_free(QMGR_MESSAGE *message)
        myfree(message->client_name);
     if (message->client_addr)
        myfree(message->client_addr);
+    if (message->client_port)
+       myfree(message->client_port);
     if (message->client_proto)
        myfree(message->client_proto);
     if (message->client_helo)
index 07696f50c37e69d5c3ac73cb328330e7e4a79ae7..b768d6fc779779285ec2440bd0d5a1146aa1a5a3 100644 (file)
 /*     This macro expands to the remote client hostname.
 /* .sp
 /*     This is available in Postfix 2.2 and later.
+/* .IP \fB${\fBclient_port\fR}\fR
+/*     This macro expands to the remote client TCP port number.
+/* .sp
+/*     This is available in Postfix 2.5 and later.
 /* .IP \fB${\fBclient_protocol\fR}\fR
 /*     This macro expands to the remote client protocol.
 /* .sp
 #define PIPE_DICT_SIZE         "size"  /* key */
 #define PIPE_DICT_CLIENT_ADDR  "client_address"        /* key */
 #define PIPE_DICT_CLIENT_NAME  "client_hostname"       /* key */
+#define PIPE_DICT_CLIENT_PORT  "client_port"   /* key */
 #define PIPE_DICT_CLIENT_PROTO "client_protocol"       /* key */
 #define PIPE_DICT_CLIENT_HELO  "client_helo"   /* key */
 #define PIPE_DICT_SASL_METHOD  "sasl_method"   /* key */
@@ -570,6 +575,7 @@ static int parse_callback(int type, VSTRING *buf, char *context)
        PIPE_DICT_SIZE, 0,
        PIPE_DICT_CLIENT_ADDR, 0,
        PIPE_DICT_CLIENT_NAME, 0,
+       PIPE_DICT_CLIENT_PORT, 0,
        PIPE_DICT_CLIENT_PROTO, 0,
        PIPE_DICT_CLIENT_HELO, 0,
        PIPE_DICT_SASL_METHOD, 0,
@@ -1177,6 +1183,8 @@ static int deliver_message(DELIVER_REQUEST *request, char *service, char **argv)
                request->client_helo);
     dict_update(PIPE_DICT_TABLE, PIPE_DICT_CLIENT_NAME,
                request->client_name);
+    dict_update(PIPE_DICT_TABLE, PIPE_DICT_CLIENT_PORT,
+               request->client_port);
     dict_update(PIPE_DICT_TABLE, PIPE_DICT_CLIENT_PROTO,
                request->client_proto);
     dict_update(PIPE_DICT_TABLE, PIPE_DICT_SASL_METHOD,
index f4b35460217fff7a084c59b0ab7c328febc4a85e..6392e098f6c70e800e69aea249529c6730581f3d 100644 (file)
@@ -280,6 +280,7 @@ struct QMGR_MESSAGE {
     long    rcpt_offset;               /* more recipients here */
     char   *client_name;               /* client hostname */
     char   *client_addr;               /* client address */
+    char   *client_port;               /* client port */
     char   *client_proto;              /* client protocol */
     char   *client_helo;               /* helo parameter */
     char   *sasl_method;               /* SASL method */
index 59bae9af82e1af3882743ff3f3c866cec5714825..eeec88d3b40d81dbc4f57d157af5db7bd799dd70 100644 (file)
@@ -130,8 +130,6 @@ static void qmgr_active_corrupt(const char *queue_id)
        if (errno != ENOENT)
            msg_fatal("%s: save corrupt file queue %s id %s: %m",
                      myname, MAIL_QUEUE_ACTIVE, queue_id);
-       msg_warn("%s: save corrupt file queue %s id %s: %m",
-                myname, MAIL_QUEUE_ACTIVE, queue_id);
     } else {
        msg_warn("saving corrupt file \"%s\" from queue \"%s\" to queue \"%s\"",
                 queue_id, MAIL_QUEUE_ACTIVE, MAIL_QUEUE_CORRUPT);
index 2785e59a95c959767777853842c63a11a6900dfe..346562897ecac1ec9d069100865250779316208c 100644 (file)
@@ -170,13 +170,17 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
               ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, message->dsn_envid,
               ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, message->dsn_ret,
               ATTR_TYPE_FUNC, msg_stats_print, (void *) &stats,
+    /* XXX Should be encapsulated with ATTR_TYPE_FUNC. */
             ATTR_TYPE_STR, MAIL_ATTR_LOG_CLIENT_NAME, message->client_name,
             ATTR_TYPE_STR, MAIL_ATTR_LOG_CLIENT_ADDR, message->client_addr,
+            ATTR_TYPE_STR, MAIL_ATTR_LOG_CLIENT_PORT, message->client_port,
             ATTR_TYPE_STR, MAIL_ATTR_LOG_PROTO_NAME, message->client_proto,
               ATTR_TYPE_STR, MAIL_ATTR_LOG_HELO_NAME, message->client_helo,
+    /* XXX Should be encapsulated with ATTR_TYPE_FUNC. */
               ATTR_TYPE_STR, MAIL_ATTR_SASL_METHOD, message->sasl_method,
             ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, message->sasl_username,
               ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, message->sasl_sender,
+    /* XXX Ditto if we want to pass TLS certificate info. */
             ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, message->rewrite_context,
               ATTR_TYPE_INT, MAIL_ATTR_RCPT_COUNT, list.len,
               ATTR_TYPE_END);
index eeedefbcfe115f2a7e6c6260e0b273194e4a31bd..dc2b7327235003461e5c76e4a0d38a55e3d4e416 100644 (file)
@@ -190,6 +190,7 @@ static QMGR_MESSAGE *qmgr_message_create(const char *queue_name,
     message->verp_delims = 0;
     message->client_name = 0;
     message->client_addr = 0;
+    message->client_port = 0;
     message->client_proto = 0;
     message->client_helo = 0;
     message->sasl_method = 0;
@@ -675,6 +676,10 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
                if (message->client_addr != 0)
                    myfree(message->client_addr);
                message->client_addr = mystrdup(value);
+           } else if (strcmp(name, MAIL_ATTR_LOG_CLIENT_PORT) == 0) {
+               if (message->client_port != 0)
+                   myfree(message->client_port);
+               message->client_port = mystrdup(value);
            } else if (strcmp(name, MAIL_ATTR_LOG_PROTO_NAME) == 0) {
                if (message->client_proto != 0)
                    myfree(message->client_proto);
@@ -783,6 +788,8 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
        message->client_name = mystrdup("");
     if (message->client_addr == 0)
        message->client_addr = mystrdup("");
+    if (message->client_port == 0)
+       message->client_port = mystrdup("");
     if (message->client_proto == 0)
        message->client_proto = mystrdup("");
     if (message->client_helo == 0)
@@ -1374,6 +1381,8 @@ void    qmgr_message_free(QMGR_MESSAGE *message)
        myfree(message->client_name);
     if (message->client_addr)
        myfree(message->client_addr);
+    if (message->client_port)
+       myfree(message->client_port);
     if (message->client_proto)
        myfree(message->client_proto);
     if (message->client_helo)
index 171ecae6328d7c4b1738e1faecae281f017c4681..b88d5a45938ec2de0aa82f9e74cb7f8192936846 100644 (file)
@@ -322,6 +322,9 @@ static void qmqpd_write_attributes(QMQPD_STATE *state)
     if (IS_AVAIL_CLIENT_ADDR(state->addr))
        rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
                    MAIL_ATTR_LOG_CLIENT_ADDR, state->rfc_addr);
+    if (IS_AVAIL_CLIENT_PORT(state->port))
+       rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
+                   MAIL_ATTR_LOG_CLIENT_PORT, state->port);
     if (IS_AVAIL_CLIENT_NAMADDR(state->namaddr))
        rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
                    MAIL_ATTR_LOG_ORIGIN, state->namaddr);
@@ -335,6 +338,8 @@ static void qmqpd_write_attributes(QMQPD_STATE *state)
                MAIL_ATTR_ACT_CLIENT_NAME, state->name);
     rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
                MAIL_ATTR_ACT_CLIENT_ADDR, state->rfc_addr);
+    rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
+               MAIL_ATTR_ACT_CLIENT_PORT, state->port);
     rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%u",
                MAIL_ATTR_ACT_CLIENT_AF, state->addr_family);
 }
index 40fde59b4c1797d4404a2de0ab7e2f6c32eb6138..86e98efaa6e1d267a0d466f7f7e90b54362d2e52 100644 (file)
@@ -35,7 +35,8 @@ typedef struct {
     struct timeval arrival_time;       /* start of session */
     char   *name;                      /* client name */
     char   *addr;                      /* client IP address */
-    char   *namaddr;                   /* name[addr] */
+    char   *port;                      /* client TCP port */
+    char   *namaddr;                   /* name[addr]:port */
     char   *rfc_addr;                  /* RFC 2821 client IP address */
     int     addr_family;               /* address family */
     char   *queue_id;                  /* queue file ID */
@@ -60,12 +61,14 @@ typedef struct {
 
 #define CLIENT_NAME_UNKNOWN    CLIENT_ATTR_UNKNOWN
 #define CLIENT_ADDR_UNKNOWN    CLIENT_ATTR_UNKNOWN
+#define CLIENT_PORT_UNKNOWN    CLIENT_ATTR_UNKNOWN
 #define CLIENT_NAMADDR_UNKNOWN CLIENT_ATTR_UNKNOWN
 
 #define IS_AVAIL_CLIENT_ATTR(v)        ((v) && strcmp((v), CLIENT_ATTR_UNKNOWN))
 
 #define IS_AVAIL_CLIENT_NAME(v)        IS_AVAIL_CLIENT_ATTR(v)
 #define IS_AVAIL_CLIENT_ADDR(v)        IS_AVAIL_CLIENT_ATTR(v)
+#define IS_AVAIL_CLIENT_PORT(v)        IS_AVAIL_CLIENT_ATTR(v)
 #define IS_AVAIL_CLIENT_NAMADDR(v) IS_AVAIL_CLIENT_ATTR(v)
 
  /*
index 711501981effcdc0236c2f9de167ccf88b0b2f7c..f0c6cc66e2ec03d6ce36f66f415a786d7f729109 100644 (file)
@@ -24,7 +24,7 @@
 /* .IP addr
 /*     Printable representation of the client address.
 /* .IP namaddr
-/*     String of the form: "name[addr]".
+/*     String of the form: "name[addr]:port".
 /* .PP
 /*     qmqpd_peer_reset() releases memory allocated by qmqpd_peer_init().
 /* LICENSE
@@ -96,6 +96,7 @@ void    qmqpd_peer_init(QMQPD_STATE *state)
        state->addr = mystrdup(CLIENT_ADDR_UNKNOWN);
        state->rfc_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
        state->addr_family = AF_UNSPEC;
+       state->port = mystrdup(CLIENT_PORT_UNKNOWN);
     }
 
     /*
@@ -114,6 +115,7 @@ void    qmqpd_peer_init(QMQPD_STATE *state)
                 )) {
        MAI_HOSTNAME_STR client_name;
        MAI_HOSTADDR_STR client_addr;
+       MAI_SERVPORT_STR client_port;
        int     aierr;
        char   *colonp;
 
@@ -143,9 +145,10 @@ void    qmqpd_peer_init(QMQPD_STATE *state)
         * Convert the client address to printable form.
         */
        if ((aierr = sockaddr_to_hostaddr(sa, sa_length, &client_addr,
-                                         (MAI_SERVPORT_STR *) 0, 0)) != 0)
-           msg_fatal("%s: cannot convert client address to string: %s",
+                                         &client_port, 0)) != 0)
+           msg_fatal("%s: cannot convert client address/port to string: %s",
                      myname, MAI_STRERROR(aierr));
+       state->port = mystrdup(client_port.buf);
 
        /*
         * We convert IPv4-in-IPv6 address to 'true' IPv4 address early on,
@@ -266,13 +269,15 @@ void    qmqpd_peer_init(QMQPD_STATE *state)
        state->addr = mystrdup("127.0.0.1");    /* XXX bogus. */
        state->rfc_addr = mystrdup("127.0.0.1");/* XXX bogus. */
        state->addr_family = AF_UNSPEC;
+       state->port = mystrdup("0");            /* XXX bogus. */
     }
 
     /*
-     * Do the name[addr] formatting for pretty reports.
+     * Do the name[addr]:port formatting for pretty reports.
      */
     state->namaddr =
-       concatenate(state->name, "[", state->addr, "]", (char *) 0);
+       concatenate(state->name, "[", state->addr,
+                   "]:", state->port, (char *) 0);
 }
 
 /* qmqpd_peer_reset - destroy peer information */
@@ -283,4 +288,5 @@ void    qmqpd_peer_reset(QMQPD_STATE *state)
     myfree(state->addr);
     myfree(state->namaddr);
     myfree(state->rfc_addr);
+    myfree(state->port);
 }
index f55eafe46cbcb63447899d18d4a1dc58b55ef789..72005bfc0c41e0474c7210e34f7fe1b2f92383df 100644 (file)
@@ -117,6 +117,7 @@ typedef struct SMTP_STATE {
 #define SMTP_FEATURE_DSN               (1<<15) /* DSN supported */
 #define SMTP_FEATURE_PIX_NO_ESMTP      (1<<16) /* PIX smtp fixup mode */
 #define SMTP_FEATURE_PIX_DELAY_DOTCRLF (1<<17) /* PIX smtp fixup mode */
+#define SMTP_FEATURE_XFORWARD_PORT     (1<<18)
 
  /*
   * Features that passivate under the endpoint.
index 2d1a12c5fe3f5c64cb9226456023b47a153e7d66..a4acfa0cbcaadef087159ccc587dfdd39489f45c 100644 (file)
@@ -255,6 +255,7 @@ int     smtp_helo(SMTP_STATE *state)
     static NAME_CODE xforward_features[] = {
        XFORWARD_NAME, SMTP_FEATURE_XFORWARD_NAME,
        XFORWARD_ADDR, SMTP_FEATURE_XFORWARD_ADDR,
+       XFORWARD_PORT, SMTP_FEATURE_XFORWARD_PORT,
        XFORWARD_PROTO, SMTP_FEATURE_XFORWARD_PROTO,
        XFORWARD_HELO, SMTP_FEATURE_XFORWARD_HELO,
        XFORWARD_DOMAIN, SMTP_FEATURE_XFORWARD_DOMAIN,
@@ -1167,6 +1168,12 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state,
                                   DEL_REQ_ATTR_AVAIL(request->client_addr) ?
                           request->client_addr : XFORWARD_UNAVAILABLE, "");
            }
+           if (session->features & SMTP_FEATURE_XFORWARD_PORT) {
+               vstring_strcat(next_command, " " XFORWARD_PORT "=");
+               xtext_quote_append(next_command,
+                                  DEL_REQ_ATTR_AVAIL(request->client_port) ?
+                          request->client_port : XFORWARD_UNAVAILABLE, "");
+           }
            if (session->send_proto_helo)
                next_state = SMTP_STATE_XFORWARD_PROTO_HELO;
            else
index b45d170f1adc292102f14174aef339e575afdff7..91230cc063aedf2fb85075bc122d3d7d01ac802c 100644 (file)
@@ -1533,13 +1533,13 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
            ENQUEUE_FIX_REPLY(state, reply_buf, XCLIENT_CMD
                              " " XCLIENT_NAME " " XCLIENT_ADDR
                              " " XCLIENT_PROTO " " XCLIENT_HELO
-                             " " XCLIENT_REVERSE_NAME);
+                             " " XCLIENT_REVERSE_NAME " " XCLIENT_PORT);
     if ((discard_mask & EHLO_MASK_XFORWARD) == 0)
        if (xforward_allowed)
            ENQUEUE_FIX_REPLY(state, reply_buf, XFORWARD_CMD
                              " " XFORWARD_NAME " " XFORWARD_ADDR
                              " " XFORWARD_PROTO " " XFORWARD_HELO
-                             " " XFORWARD_DOMAIN);
+                             " " XFORWARD_DOMAIN " " XFORWARD_PORT);
     if ((discard_mask & EHLO_MASK_ENHANCEDSTATUSCODES) == 0)
        ENQUEUE_FIX_REPLY(state, reply_buf, "ENHANCEDSTATUSCODES");
     if ((discard_mask & EHLO_MASK_8BITMIME) == 0)
@@ -1716,6 +1716,9 @@ static int mail_open_stream(SMTPD_STATE *state)
            if (IS_AVAIL_CLIENT_ADDR(FORWARD_ADDR(state)))
                rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
                            MAIL_ATTR_LOG_CLIENT_ADDR, FORWARD_ADDR(state));
+           if (IS_AVAIL_CLIENT_PORT(FORWARD_PORT(state)))
+               rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
+                           MAIL_ATTR_LOG_CLIENT_PORT, FORWARD_PORT(state));
            if (IS_AVAIL_CLIENT_NAMADDR(FORWARD_NAMADDR(state)))
                rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
                            MAIL_ATTR_LOG_ORIGIN, FORWARD_NAMADDR(state));
@@ -1736,6 +1739,8 @@ static int mail_open_stream(SMTPD_STATE *state)
                    MAIL_ATTR_ACT_REVERSE_CLIENT_NAME, state->reverse_name);
            rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
                        MAIL_ATTR_ACT_CLIENT_ADDR, state->addr);
+           rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
+                       MAIL_ATTR_ACT_CLIENT_PORT, state->port);
            if (state->helo_name)
                rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
                            MAIL_ATTR_ACT_HELO_NAME, state->helo_name);
@@ -3294,6 +3299,25 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
            update_namaddr = 1;
        }
 
+       /*
+        * PORT=substitute SMTP client port number.
+        */
+       else if (STREQ(attr_name, XCLIENT_PORT)) {
+           if (STREQ(attr_value, XCLIENT_UNAVAILABLE)) {
+               attr_value = CLIENT_PORT_UNKNOWN;
+           } else {
+               if (!alldig(attr_value)
+                   || strlen(attr_value) > sizeof("65535") - 1) {
+                   state->error_mask |= MAIL_ERROR_PROTOCOL;
+                   smtpd_chat_reply(state, "501 5.5.4 Bad %s syntax: %s",
+                                    XCLIENT_PORT, attr_value);
+                   return (-1);
+               }
+           }
+           UPDATE_STR(state->port, attr_value);
+           update_namaddr = 1;
+       }
+
        /*
         * HELO=substitute SMTP client HELO parameter. Censor special
         * characters that could mess up message headers.
@@ -3346,7 +3370,8 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        if (state->namaddr)
            myfree(state->namaddr);
        state->namaddr =
-           concatenate(state->name, "[", state->addr, "]", (char *) 0);
+           concatenate(state->name, "[", state->addr, "]:",
+                       state->port, (char *) 0);
     }
 
     /*
@@ -3401,6 +3426,7 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
     static NAME_CODE xforward_flags[] = {
        XFORWARD_NAME, SMTPD_STATE_XFORWARD_NAME,
        XFORWARD_ADDR, SMTPD_STATE_XFORWARD_ADDR,
+       XFORWARD_PORT, SMTPD_STATE_XFORWARD_PORT,
        XFORWARD_PROTO, SMTPD_STATE_XFORWARD_PROTO,
        XFORWARD_HELO, SMTPD_STATE_XFORWARD_HELO,
        XFORWARD_DOMAIN, SMTPD_STATE_XFORWARD_DOMAIN,
@@ -3520,6 +3546,24 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
            UPDATE_STR(state->xforward.rfc_addr, attr_value);
            break;
 
+           /*
+            * PORT=up-stream port number.
+            */
+       case SMTPD_STATE_XFORWARD_PORT:
+           if (STREQ(attr_value, XFORWARD_UNAVAILABLE)) {
+               attr_value = CLIENT_PORT_UNKNOWN;
+           } else {
+               if (!alldig(attr_value)
+                   || strlen(attr_value) > sizeof("65535") - 1) {
+                   state->error_mask |= MAIL_ERROR_PROTOCOL;
+                   smtpd_chat_reply(state, "501 5.5.4 Bad %s syntax: %s",
+                                    XFORWARD_PORT, attr_value);
+                   return (-1);
+               }
+           }
+           UPDATE_STR(state->xforward.port, attr_value);
+           break;
+
            /*
             * HELO=hostname that the up-stream MTA introduced itself with
             * (not necessarily SMTP HELO). Censor special characters that
@@ -3593,7 +3637,8 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        state->xforward.namaddr =
            IS_AVAIL_CLIENT_ADDR(state->xforward.addr) ?
            concatenate(state->xforward.name, "[",
-                       state->xforward.addr, "]",
+                       state->xforward.addr, "]:",
+                       state->xforward.port,
                        (char *) 0) : mystrdup(state->xforward.name);
     }
     smtpd_chat_reply(state, "250 2.0.0 Ok");
@@ -4004,14 +4049,13 @@ static void smtpd_proto(SMTPD_STATE *state)
         * HELO or EHLO, but we do change the feature list that is announced
         * in the EHLO response.
         */
-#define XXX_NO_PORT    "0"
        else {
            err = 0;
            if (smtpd_milters != 0 && SMTPD_STAND_ALONE(state) == 0) {
                milter_macro_callback(smtpd_milters, smtpd_milter_eval,
                                      (void *) state);
                if ((err = milter_conn_event(smtpd_milters, state->name,
-                                            state->addr, XXX_NO_PORT,
+                                            state->addr, state->port,
                                             state->addr_family)) != 0)
                    err = check_milter_reply(state, err);
            }
@@ -4142,13 +4186,20 @@ static void smtpd_proto(SMTPD_STATE *state)
      * Log abnormal session termination, in case postmaster notification has
      * been turned off. In the log, indicate the last recognized state before
      * things went wrong. Don't complain about clients that go away without
-     * sending QUIT.
+     * sending QUIT. Log the byte count after DATA to help diagnose MTU
+     * troubles.
      */
-    if (state->reason && state->where
-       && (strcmp(state->where, SMTPD_AFTER_DOT)
-           || strcmp(state->reason, REASON_LOST_CONNECTION)))
-       msg_info("%s after %s from %s[%s]",
-                state->reason, state->where, state->name, state->addr);
+    if (state->reason && state->where) {
+       if (strcmp(state->where, SMTPD_CMD_DATA) == 0) {
+           msg_info("%s after %s (%lu bytes) from %s[%s]",
+                    state->reason, state->where, (long) state->act_size,
+                    state->name, state->addr);
+       } else if (strcmp(state->where, SMTPD_AFTER_DOT)
+                  || strcmp(state->reason, REASON_LOST_CONNECTION)) {
+           msg_info("%s after %s from %s[%s]",
+                    state->reason, state->where, state->name, state->addr);
+       }
+    }
 
     /*
      * Cleanup whatever information the client gave us during the SMTP
@@ -4193,7 +4244,7 @@ static void smtpd_service(VSTREAM *stream, char *service, char **argv)
      * machines.
      */
     smtpd_state_init(&state, stream, service);
-    msg_info("connect from %s[%s]", state.name, state.addr);
+    msg_info("connect from %s", state.namaddr);
 
     /*
      * With TLS wrapper mode, we run on a dedicated port and turn on TLS
@@ -4243,7 +4294,7 @@ static void smtpd_service(VSTREAM *stream, char *service, char **argv)
      * After the client has gone away, clean up whatever we have set up at
      * connection time.
      */
-    msg_info("disconnect from %s[%s]", state.name, state.addr);
+    msg_info("disconnect from %s", state.namaddr);
     smtpd_state_reset(&state);
     debug_peer_restore();
 }
index d44978050dda8876e44333482794c655bce5ea58..b4e1aeb8a8172ab0d57883eff72db41744e514fc 100644 (file)
@@ -55,7 +55,8 @@ typedef struct {
     int     flags;                     /* XFORWARD server state */
     char   *name;                      /* name for access control */
     char   *addr;                      /* address for access control */
-    char   *namaddr;                   /* name[address] */
+    char   *port;                      /* port for logging */
+    char   *namaddr;                   /* name[address]:port */
     char   *rfc_addr;                  /* address for RFC 2821 */
     char   *protocol;                  /* email protocol */
     char   *helo_name;                 /* helo/ehlo parameter */
@@ -74,7 +75,8 @@ typedef struct SMTPD_STATE {
     char   *name;                      /* verified client hostname */
     char   *reverse_name;              /* unverified client hostname */
     char   *addr;                      /* client host address string */
-    char   *namaddr;                   /* combined name and address */
+    char   *port;                      /* port for logging */
+    char   *namaddr;                   /* name[address]:port */
     char   *rfc_addr;                  /* address for RFC 2821 */
     int     addr_family;               /* address family */
     struct sockaddr_storage sockaddr;  /* binary client endpoint */
@@ -187,10 +189,12 @@ typedef struct SMTPD_STATE {
 #define SMTPD_STATE_XFORWARD_HELO  (1<<4)      /* client helo received */
 #define SMTPD_STATE_XFORWARD_IDENT (1<<5)      /* message identifier */
 #define SMTPD_STATE_XFORWARD_DOMAIN (1<<6)     /* message identifier */
+#define SMTPD_STATE_XFORWARD_PORT  (1<<7)      /* client port received */
 
 #define SMTPD_STATE_XFORWARD_CLIENT_MASK \
        (SMTPD_STATE_XFORWARD_NAME | SMTPD_STATE_XFORWARD_ADDR \
-       | SMTPD_STATE_XFORWARD_PROTO | SMTPD_STATE_XFORWARD_HELO)
+       | SMTPD_STATE_XFORWARD_PROTO | SMTPD_STATE_XFORWARD_HELO \
+       | SMTPD_STATE_XFORWARD_PORT)
 
 extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *, const char *);
 extern void smtpd_state_reset(SMTPD_STATE *);
@@ -232,6 +236,7 @@ extern void smtpd_state_reset(SMTPD_STATE *);
 
 #define CLIENT_NAME_UNKNOWN    CLIENT_ATTR_UNKNOWN
 #define CLIENT_ADDR_UNKNOWN    CLIENT_ATTR_UNKNOWN
+#define CLIENT_PORT_UNKNOWN    CLIENT_ATTR_UNKNOWN
 #define CLIENT_NAMADDR_UNKNOWN CLIENT_ATTR_UNKNOWN
 #define CLIENT_HELO_UNKNOWN    0
 #define CLIENT_PROTO_UNKNOWN   CLIENT_ATTR_UNKNOWN
@@ -242,6 +247,7 @@ extern void smtpd_state_reset(SMTPD_STATE *);
 
 #define IS_AVAIL_CLIENT_NAME(v)        IS_AVAIL_CLIENT_ATTR(v)
 #define IS_AVAIL_CLIENT_ADDR(v)        IS_AVAIL_CLIENT_ATTR(v)
+#define IS_AVAIL_CLIENT_PORT(v)        IS_AVAIL_CLIENT_ATTR(v)
 #define IS_AVAIL_CLIENT_NAMADDR(v) IS_AVAIL_CLIENT_ATTR(v)
 #define IS_AVAIL_CLIENT_HELO(v)        ((v) != 0)
 #define IS_AVAIL_CLIENT_PROTO(v) IS_AVAIL_CLIENT_ATTR(v)
@@ -299,6 +305,7 @@ extern void smtpd_peer_reset(SMTPD_STATE *state);
 #define FORWARD_NAMADDR(s)     FORWARD_CLIENT_ATTR((s), namaddr)
 #define FORWARD_PROTO(s)       FORWARD_CLIENT_ATTR((s), protocol)
 #define FORWARD_HELO(s)                FORWARD_CLIENT_ATTR((s), helo_name)
+#define FORWARD_PORT(s)                FORWARD_CLIENT_ATTR((s), port)
 
 #define FORWARD_IDENT(s) \
        (((s)->xforward.flags & SMTPD_STATE_XFORWARD_IDENT) ? \
index 44480ed0ba61390af4d2db5b759052569de92e1d..7e3546e4d7fda91b16843123ecc6544d86a6bfef 100644 (file)
@@ -92,6 +92,8 @@ const char *smtpd_milter_eval(const char *name, void *ptr)
        return (var_myhostname);
     if (strcmp(name, S8_MAC_CLIENT_ADDR) == 0)
        return (state->rfc_addr);
+    if (strcmp(name, S8_MAC_CLIENT_PORT) == 0)
+       return (state->port);
     if (strcmp(name, S8_MAC_CLIENT_CONN) == 0) {
        if (state->expand_buf == 0)
            state->expand_buf = vstring_alloc(10);
index 7e2423371259e93c2539752cdeb55c7100b1638d..dc5ea0d9f8bed964673d527ab20e06e45fcd74ff 100644 (file)
@@ -41,7 +41,7 @@
 /* .IP addr
 /*     Printable representation of the client address.
 /* .IP namaddr
-/*     String of the form: "name[addr]".
+/*     String of the form: "name[addr]:port".
 /* .IP rfc_addr
 /*      String of the form "ipv4addr" or "ipv6:ipv6addr" for use
 /*     in Received: message headers.
@@ -170,6 +170,7 @@ void    smtpd_peer_init(SMTPD_STATE *state)
        state->addr_family = AF_UNSPEC;
        state->name_status = SMTPD_PEER_CODE_PERM;
        state->reverse_name_status = SMTPD_PEER_CODE_PERM;
+       state->port = mystrdup(CLIENT_PORT_UNKNOWN);
     }
 
     /*
@@ -188,6 +189,7 @@ void    smtpd_peer_init(SMTPD_STATE *state)
                 )) {
        MAI_HOSTNAME_STR client_name;
        MAI_HOSTADDR_STR client_addr;
+       MAI_SERVPORT_STR client_port;
        int     aierr;
        char   *colonp;
 
@@ -217,9 +219,10 @@ void    smtpd_peer_init(SMTPD_STATE *state)
         * Convert the client address to printable form.
         */
        if ((aierr = sockaddr_to_hostaddr(sa, sa_length, &client_addr,
-                                         (MAI_SERVPORT_STR *) 0, 0)) != 0)
-           msg_fatal("%s: cannot convert client address to string: %s",
+                                         &client_port, 0)) != 0)
+           msg_fatal("%s: cannot convert client address/port to string: %s",
                      myname, MAI_STRERROR(aierr));
+       state->port = mystrdup(client_port.buf);
 
        /*
         * We convert IPv4-in-IPv6 address to 'true' IPv4 address early on,
@@ -364,13 +367,15 @@ void    smtpd_peer_init(SMTPD_STATE *state)
        state->addr_family = AF_UNSPEC;
        state->name_status = SMTPD_PEER_CODE_OK;
        state->reverse_name_status = SMTPD_PEER_CODE_OK;
+       state->port = mystrdup("0");            /* XXX bogus. */
     }
 
     /*
-     * Do the name[addr] formatting for pretty reports.
+     * Do the name[addr]:port formatting for pretty reports.
      */
     state->namaddr =
-       concatenate(state->name, "[", state->addr, "]", (char *) 0);
+       concatenate(state->name, "[", state->addr,
+                   "]:", state->port, (char *) 0);
 }
 
 /* smtpd_peer_reset - destroy peer information */
@@ -382,4 +387,5 @@ void    smtpd_peer_reset(SMTPD_STATE *state)
     myfree(state->addr);
     myfree(state->namaddr);
     myfree(state->rfc_addr);
+    myfree(state->port);
 }
index 345485abd30f9e047bf748530201e5c73247fe57..e4804de8f628ed5557dc9f7eb5492ab30db542eb 100644 (file)
 #define SMTPD_PROXY_XFORWARD_HELO  (1<<3)      /* client helo */
 #define SMTPD_PROXY_XFORWARD_IDENT (1<<4)      /* message identifier */
 #define SMTPD_PROXY_XFORWARD_DOMAIN (1<<5)     /* origin type */
+#define SMTPD_PROXY_XFORWARD_PORT  (1<<6)      /* client port */
 
  /*
   * SLMs.
@@ -257,6 +258,7 @@ int     smtpd_proxy_open(SMTPD_STATE *state, const char *service,
     static NAME_CODE xforward_features[] = {
        XFORWARD_NAME, SMTPD_PROXY_XFORWARD_NAME,
        XFORWARD_ADDR, SMTPD_PROXY_XFORWARD_ADDR,
+       XFORWARD_PORT, SMTPD_PROXY_XFORWARD_PORT,
        XFORWARD_PROTO, SMTPD_PROXY_XFORWARD_PROTO,
        XFORWARD_HELO, SMTPD_PROXY_XFORWARD_HELO,
        XFORWARD_DOMAIN, SMTPD_PROXY_XFORWARD_DOMAIN,
@@ -367,6 +369,11 @@ int     smtpd_proxy_open(SMTPD_STATE *state, const char *service,
            bad = smtpd_xforward(state, buf, XFORWARD_ADDR,
                                 IS_AVAIL_CLIENT_ADDR(FORWARD_ADDR(state)),
                                 FORWARD_ADDR(state));
+       if (bad == 0
+           && (state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_PORT))
+           bad = smtpd_xforward(state, buf, XFORWARD_PORT,
+                                IS_AVAIL_CLIENT_PORT(FORWARD_PORT(state)),
+                                FORWARD_PORT(state));
        if (bad == 0
            && (state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_HELO))
            bad = smtpd_xforward(state, buf, XFORWARD_HELO,
index 614c96147ed2fbb6ae678df10fd56d29053c1fa5..977640946bbc024ec184e1b37afbf77b93df94cd 100644 (file)
@@ -55,6 +55,7 @@ void    smtpd_xforward_init(SMTPD_STATE *state)
     state->xforward.flags = 0;
     state->xforward.name = 0;
     state->xforward.addr = 0;
+    state->xforward.port = 0;
     state->xforward.namaddr = 0;
     state->xforward.protocol = 0;
     state->xforward.helo_name = 0;
@@ -82,6 +83,7 @@ void    smtpd_xforward_preset(SMTPD_STATE *state)
     state->xforward.flags = SMTPD_STATE_XFORWARD_INIT;
     state->xforward.name = mystrdup(CLIENT_NAME_UNKNOWN);
     state->xforward.addr = mystrdup(CLIENT_ADDR_UNKNOWN);
+    state->xforward.port = mystrdup(CLIENT_PORT_UNKNOWN);
     state->xforward.namaddr = mystrdup(CLIENT_NAMADDR_UNKNOWN);
     state->xforward.rfc_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
     /* Leave helo at zero. */
@@ -99,6 +101,7 @@ void    smtpd_xforward_reset(SMTPD_STATE *state)
     state->xforward.flags = 0;
     FREE_AND_WIPE(state->xforward.name);
     FREE_AND_WIPE(state->xforward.addr);
+    FREE_AND_WIPE(state->xforward.port);
     FREE_AND_WIPE(state->xforward.namaddr);
     FREE_AND_WIPE(state->xforward.rfc_addr);
     FREE_AND_WIPE(state->xforward.protocol);
index ea1cbc7fd3beb8ffa5f5e71c5f404f0694b24f48..242756124b5d1f037965a4a4773238073dc0269a 100644 (file)
 /*     Show the SMTP conversations.
 /* .IP "\fB-w \fIdelay\fR"
 /*     Wait \fIdelay\fR seconds before responding to a DATA command.
+/* .IP "\fB-W \fIcommand:delay[:odds]\fR"
+/*     Wait \fIdelay\fR seconds before responding to \fIcommand\fR.
+/*     If \fIodds\fR is also specified (a number between 1-99
+/*     inclusive), wait for a random multiple of \fIdelay\fR. The
+/*     random multiplier is equal to the number of times the program
+/*     needs to roll a dice with a range of 0..99 inclusive, before
+/*     the dice produces a result greater than or equal to \fIodds\fR.
 /* .IP [\fBinet:\fR][\fIhost\fR]:\fIport\fR
 /*     Listen on network interface \fIhost\fR (default: any interface)
 /*     TCP port \fIport\fR. Both \fIhost\fR and \fIport\fR may be
@@ -286,6 +293,8 @@ typedef struct SINK_STATE {
     time_t  start_time;                        /* MAIL command time */
     int     id;                                /* pseudo-random */
     VSTREAM *dump_file;                        /* dump file or null */
+    void    (*delayed_response) (struct SINK_STATE *state, const char *);
+    char   *delayed_args;
 } SINK_STATE;
 
 #define ST_ANY                 0
@@ -318,7 +327,6 @@ static int mesg_count;
 static int max_quit_count;
 static int disable_pipelining;
 static int disable_8bitmime;
-static int fixed_delay;
 static int disable_esmtp;
 static int enable_lmtp;
 static int pretend_pix;
@@ -708,18 +716,6 @@ static void data_response(SINK_STATE *state, const char *unused_args)
        mail_file_finish_header(state);
 }
 
-/* data_event - delayed response to DATA command */
-
-static void data_event(int unused_event, char *context)
-{
-    SINK_STATE *state = (SINK_STATE *) context;
-
-    data_response(state, "");
-    /* Resume input event handling after the delayed DATA response. */
-    event_enable_read(vstream_fileno(state->stream), read_event, (char *) state);
-    event_request_timer(read_timeout, (char *) state, var_tmout);
-}
-
 /* dot_resp_hard - hard error response to . command */
 
 static void dot_resp_hard(SINK_STATE *state)
@@ -782,6 +778,25 @@ static void conn_response(SINK_STATE *state, const char *unused_args)
     smtp_flush(state->stream);
 }
 
+/* delay_event - delayed command response */
+
+static void delay_event(int unused_event, char *context)
+{
+    SINK_STATE *state = (SINK_STATE *) context;
+
+    state->delayed_response(state, state->delayed_args);
+    myfree(state->delayed_args);
+    state->delayed_args = 0;
+
+    if (state->delayed_response == quit_response) {
+       disconnect(state);
+       return;
+    }
+    /* Resume input event handling after the delayed response. */
+    event_enable_read(vstream_fileno(state->stream), read_event, (char *) state);
+    event_request_timer(read_timeout, (char *) state, var_tmout);
+}
+
 /* data_read - read data from socket */
 
 static int data_read(SINK_STATE *state)
@@ -863,6 +878,8 @@ typedef struct SINK_COMMAND {
     void    (*hard_response) (SINK_STATE *);
     void    (*soft_response) (SINK_STATE *);
     int     flags;
+    int     delay;
+    int     delay_odds;
 } SINK_COMMAND;
 
 #define FLAG_ENABLE    (1<<0)          /* command is enabled */
@@ -872,21 +889,21 @@ typedef struct SINK_COMMAND {
 #define FLAG_DISCONNECT        (1<<4)          /* disconnect */
 
 static SINK_COMMAND command_table[] = {
-    "connect", conn_response, hard_err_resp, soft_err_resp, 0,
-    "helo", helo_response, hard_err_resp, soft_err_resp, 0,
-    "ehlo", ehlo_response, hard_err_resp, soft_err_resp, 0,
-    "lhlo", ehlo_response, hard_err_resp, soft_err_resp, 0,
-    "xclient", ok_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
-    "xforward", ok_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
-    "auth", ok_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
-    "mail", mail_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
-    "rcpt", rcpt_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
-    "data", data_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
-    ".", dot_response, dot_resp_hard, dot_resp_soft, FLAG_ENABLE,
-    "rset", rset_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
-    "noop", ok_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
-    "vrfy", ok_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
-    "quit", quit_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
+    "connect", conn_response, hard_err_resp, soft_err_resp, 0, 0, 0,
+    "helo", helo_response, hard_err_resp, soft_err_resp, 0, 0, 0,
+    "ehlo", ehlo_response, hard_err_resp, soft_err_resp, 0, 0, 0,
+    "lhlo", ehlo_response, hard_err_resp, soft_err_resp, 0, 0, 0,
+    "xclient", ok_response, hard_err_resp, soft_err_resp, FLAG_ENABLE, 0, 0,
+    "xforward", ok_response, hard_err_resp, soft_err_resp, FLAG_ENABLE, 0, 0,
+    "auth", ok_response, hard_err_resp, soft_err_resp, FLAG_ENABLE, 0, 0,
+    "mail", mail_response, hard_err_resp, soft_err_resp, FLAG_ENABLE, 0, 0,
+    "rcpt", rcpt_response, hard_err_resp, soft_err_resp, FLAG_ENABLE, 0, 0,
+    "data", data_response, hard_err_resp, soft_err_resp, FLAG_ENABLE, 0, 0,
+    ".", dot_response, dot_resp_hard, dot_resp_soft, FLAG_ENABLE, 0, 0,
+    "rset", rset_response, hard_err_resp, soft_err_resp, FLAG_ENABLE, 0, 0,
+    "noop", ok_response, hard_err_resp, soft_err_resp, FLAG_ENABLE, 0, 0,
+    "vrfy", ok_response, hard_err_resp, soft_err_resp, FLAG_ENABLE, 0, 0,
+    "quit", quit_response, hard_err_resp, soft_err_resp, FLAG_ENABLE, 0, 0,
     0,
 };
 
@@ -932,6 +949,47 @@ static void set_cmds_flags(const char *cmds, int flags)
     myfree(saved_cmds);
 }
 
+/* set_cmd_delay - set per-command delay */
+
+static void set_cmd_delay(const char *cmd, int delay, int odds)
+{
+    SINK_COMMAND *cmdp;
+
+    for (cmdp = command_table; cmdp->name != 0; cmdp++)
+       if (strcasecmp(cmd, cmdp->name) == 0)
+           break;
+    if (cmdp->name == 0)
+       msg_fatal("unknown command: %s", cmd);
+
+    if (delay <= 0)
+       msg_fatal("non-positive '%s' delay", cmd);
+    if (odds < 0 || odds > 99)
+       msg_fatal("delay odds for '%s' out of range", cmd);
+
+    cmdp->delay = delay;
+    cmdp->delay_odds = odds;
+}
+
+/* set_cmd_delay_arg - set per-command delay from option argument */
+
+static void set_cmd_delay_arg(char *arg)
+{
+    char   *cp;
+    char   *saved_arg;
+    char   *cmd;
+    char   *delay;
+    char   *odds;
+
+    saved_arg = cp = mystrdup(arg);
+    cmd = mystrtok(&cp, ":");
+    delay = mystrtok(&cp, ":");
+    if (cmd == 0 || delay == 0)
+       msg_fatal("invalid command delay argument: %s", arg);
+    odds = mystrtok(&cp, "");
+    set_cmd_delay(cmd, atoi(delay), odds ? atoi(odds) : 0);
+    myfree(saved_arg);
+}
+
 /* command_resp - respond to command */
 
 static int command_resp(SINK_STATE *state, SINK_COMMAND *cmdp,
@@ -950,11 +1008,20 @@ static int command_resp(SINK_STATE *state, SINK_COMMAND *cmdp,
        cmdp->soft_response(state);
        return (0);
     }
-    if (cmdp->response == data_response && fixed_delay > 0) {
-       /* Suspend input event handling while delaying the DATA response. */
+    if (cmdp->delay > 0) {
+       int     delay = cmdp->delay;
+
+       if (cmdp->delay_odds > 0)
+           for (delay = 0;
+            ((int) (100.0 * rand() / (RAND_MAX + 1.0))) < cmdp->delay_odds;
+                delay += cmdp->delay)
+                /* NOP */ ;
+       /* Suspend input event handling while delaying the command response. */
        event_disable_readwrite(vstream_fileno(state->stream));
        event_cancel_timer(read_timeout, (char *) state);
-       event_request_timer(data_event, (char *) state, fixed_delay);
+       event_request_timer(delay_event, (char *) state, delay);
+       state->delayed_response = cmdp->response;
+       state->delayed_args = mystrdup(args);
     } else {
        cmdp->response(state, args);
        if (cmdp->response == quit_response)
@@ -1153,6 +1220,8 @@ static void disconnect(SINK_STATE *state)
        myfree(state->helo_args);
     /* Delete incomplete mail transaction. */
     mail_cmd_reset(state);
+    if (state->delayed_args)
+       myfree(state->delayed_args);
     myfree((char *) state);
     if (max_quit_count > 0 && quit_count >= max_quit_count)
        exit(0);
@@ -1201,6 +1270,8 @@ static void connect_event(int unused_event, char *unused_context)
        smtp_timeout_setup(state->stream, var_tmout);
        state->in_mail = 0;
        state->rcpts = 0;
+       state->delayed_response = 0;
+       state->delayed_args = 0;
        /* Initialize file capture attributes. */
 #ifdef AF_INET6
        if (sa.sa_family == AF_INET6)
@@ -1261,6 +1332,7 @@ int     main(int argc, char **argv)
 {
     int     backlog;
     int     ch;
+    int     delay;
     const char *protocols = INET_PROTO_NAME_ALL;
     const char *root_dir = 0;
     const char *user_privs = 0;
@@ -1283,7 +1355,7 @@ int     main(int argc, char **argv)
     /*
      * Parse JCL.
      */
-    while ((ch = GETOPT(argc, argv, "468aA:cCd:D:eEf:Fh:Ln:m:pPq:r:R:s:S:t:u:vw:")) > 0) {
+    while ((ch = GETOPT(argc, argv, "468aA:cCd:D:eEf:Fh:Ln:m:pPq:r:R:s:S:t:u:vw:W:")) > 0) {
        switch (ch) {
        case '4':
            protocols = INET_PROTO_NAME_IPV4;
@@ -1378,8 +1450,12 @@ int     main(int argc, char **argv)
            msg_verbose++;
            break;
        case 'w':
-           if ((fixed_delay = atoi(optarg)) <= 0)
+           if ((delay = atoi(optarg)) <= 0)
                usage(argv[0]);
+           set_cmd_delay("data", delay, 0);
+           break;
+       case 'W':
+           set_cmd_delay_arg(optarg);
            break;
        default:
            usage(argv[0]);
index 379dce7edda280af36c4776d96c78dcfe839ddfc..806220bc1b14796a17e4c65f522db908baa426cc 100644 (file)
@@ -346,8 +346,8 @@ int     attr_vscan0(VSTREAM *fp, int flags, va_list ap)
                    && strcmp(wanted_name, STR(name_buf)) == 0))
                break;
            if ((flags & ATTR_FLAG_EXTRA) != 0) {
-               msg_warn("unexpected attribute %s in input from %s",
-                        STR(name_buf), VSTREAM_PATH(fp));
+               msg_warn("unexpected attribute %s from %s (expecting: %s)",
+                        STR(name_buf), VSTREAM_PATH(fp), wanted_name);
                return (conversions);
            }
 
index 860f8b371ef914dd6cfca9d7d32056b30a11e3dc..645adec1628177b0e34be40d737ace40a19c41ed 100644 (file)
@@ -349,8 +349,8 @@ int     attr_vscan64(VSTREAM *fp, int flags, va_list ap)
                    && strcmp(wanted_name, STR(name_buf)) == 0))
                break;
            if ((flags & ATTR_FLAG_EXTRA) != 0) {
-               msg_warn("unexpected attribute %s in input from %s",
-                        STR(name_buf), VSTREAM_PATH(fp));
+               msg_warn("unexpected attribute %s from %s (expecting: %s)",
+                        STR(name_buf), VSTREAM_PATH(fp), wanted_name);
                return (conversions);
            }
 
index 619bfae64ac872d7ccba51428d4eb555cab8a507..6bfff01a5f35520c2a301cf725df428ea30bccfc 100644 (file)
@@ -362,8 +362,8 @@ int     attr_vscan_plain(VSTREAM *fp, int flags, va_list ap)
                    && strcmp(wanted_name, STR(name_buf)) == 0))
                break;
            if ((flags & ATTR_FLAG_EXTRA) != 0) {
-               msg_warn("unexpected attribute %s in input from %s",
-                        STR(name_buf), VSTREAM_PATH(fp));
+               msg_warn("unexpected attribute %s from %s (expecting: %s)",
+                        STR(name_buf), VSTREAM_PATH(fp), wanted_name);
                return (conversions);
            }
 
index 868064b79af1e4a1c8ba016193b719f24910e7a9..d0545aad19721ae4cbf323e7d214bc293228bc62 100644 (file)
@@ -622,7 +622,11 @@ void    event_drain(int time_limit)
     if (EVENT_INIT_NEEDED())
        return;
 
+#if (EVENTS_STYLE == EVENTS_STYLE_SELECT)
     EVENT_MASK_ZERO(&zero_mask);
+#else
+    EVENT_MASK_ALLOC(&zero_mask, event_fdslots);
+#endif
     (void) time(&event_present);
     max_time = event_present + time_limit;
     while (event_present < max_time
@@ -630,6 +634,9 @@ void    event_drain(int time_limit)
               || memcmp(&zero_mask, &event_xmask,
                         EVENT_MASK_BYTE_COUNT(&zero_mask)) != 0))
        event_loop(1);
+#if (EVENTS_STYLE != EVENTS_STYLE_SELECT)
+    EVENT_MASK_FREE(&zero_mask);
+#endif
 }
 
 /* event_enable_read - enable read events */