2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-29 13:18:12 +00:00

postfix-2.5-20071004

This commit is contained in:
Wietse Venema 2007-10-04 00:00:00 -05:00 committed by Viktor Dukhovni
parent b357c48245
commit 7c07e99edd
52 changed files with 491 additions and 131 deletions

View 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.

View File

@ -7,14 +7,15 @@ IInnttrroodduuccttiioonn
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 |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|{client_port} |Always |Client TCP port |
| |(Postfix >=2.5) | |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | |Client name from reverse |
|{client_ptr} |CONNECT, HELO, MAIL, DATA|lookup, "unknown" when |
| | |lookup fails |

View 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.
XXCCLLIIEENNTT SSeerrvveerr rreessppoonnssee
Upon receipt of a correctly formatted XCLIENT command, the server resets state

View 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.

View 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.

View File

@ -22,20 +22,20 @@
<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>

View 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>

View 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>

View 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.

View 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

View 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

View 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

View 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

View 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

View File

@ -22,20 +22,20 @@
<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>

View 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

View 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]

View File

@ -81,14 +81,14 @@
# .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

View 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;
}

View File

@ -149,6 +149,7 @@
#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.
*/

View 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);

View 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)

View 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 */

View 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 */

View File

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

View 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}"

View 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

View 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 */

View 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);

View 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);

View 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)

View File

@ -206,6 +206,10 @@
/* 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
@ -474,6 +478,7 @@
#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,

View 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 */

View 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);

View 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);

View 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)

View 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);
}

View 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)
/*

View 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);
}

View 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.

View 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

View 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();
}

View 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) ? \

View 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);

View 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);
}

View File

@ -178,6 +178,7 @@
#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,

View 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);

View File

@ -150,6 +150,13 @@
/* 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]);

View 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);
}

View 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);
}

View 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);
}

View 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 */