mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-22 09:57:34 +00:00
postfix-2.7-20091229
This commit is contained in:
parent
51826fc8f2
commit
2ccf57f4ac
1
postfix/.indent.pro
vendored
1
postfix/.indent.pro
vendored
@ -57,6 +57,7 @@
|
||||
-TDELIVER_REQUEST
|
||||
-TDELTA_TIME
|
||||
-TDICT
|
||||
-TDICT_CACHE
|
||||
-TDICT_CDBM
|
||||
-TDICT_CDBQ
|
||||
-TDICT_CIDR
|
||||
|
@ -15453,7 +15453,7 @@ Apologies for any names omitted.
|
||||
|
||||
20091023
|
||||
|
||||
Feature: specify "smtp_command_filter = pcre:/file/name"
|
||||
Feature: specify "smtpd_command_filter = pcre:/file/name"
|
||||
to replace remote SMTP client commands before they are
|
||||
executed by the Postfix SMTP server. This a last-resort
|
||||
tool to fix inter-operability problems. See examples in
|
||||
@ -15563,3 +15563,42 @@ Apologies for any names omitted.
|
||||
Cleanup: the postscreen daemon now applies the permanent
|
||||
whitelist first. It is a safety feature that prevents mail
|
||||
from being blocked. File: postscreeb/postscreen.c.
|
||||
|
||||
20091224
|
||||
|
||||
Bugfix (introduced 20041215): dict_dbm_sequence() did not
|
||||
release the shared lock when the end of the sequence was
|
||||
reached. File: util/dict_dbm.c.
|
||||
|
||||
20091227
|
||||
|
||||
Cleanup: postscreen and verify periodic cache cleanup
|
||||
(default: 12 hours after the previous cache cleanup run).
|
||||
This is based on a new dict_cache(3) module that implements
|
||||
a generalized version of the tlsmgr(8) cache maintenance
|
||||
code. Once the new dict_cache(3) code is burned in, the
|
||||
tlsmgr(8) will be migrated to it. See the RELEASE_NOTES for
|
||||
user interface details. Files: util/htable.[hc], util/dict_ht.c,
|
||||
util/dict_cache.[hc], postscreen/postscreen.c, verify/verify.c.
|
||||
|
||||
Bugfix: the event handler starved I/O events when a timer
|
||||
call-back routine scheduled a zero-delay timer request.
|
||||
This bug was exposed when adding the new dict_cache(3)
|
||||
module for cache expiration. File: util/events.c.
|
||||
|
||||
20091228
|
||||
|
||||
Cleanup: postscreen and verify periodic cache cleanup is
|
||||
now optional (specify a null time interval between cache
|
||||
cleanup runs).
|
||||
|
||||
20091229
|
||||
|
||||
Cleanup: the address_verify_poll_count default parameter
|
||||
value is now stress-dependent, so that the Postfix SMTP
|
||||
server will not wait (up to 6 seconds) for the address
|
||||
verification result. File: global/mail_params.h.
|
||||
|
||||
Final slution for the I/O event starvation problem when a
|
||||
timer call-back schedules a zero-delay timer request. File:
|
||||
util/events.c.
|
||||
|
@ -36,23 +36,28 @@ This document describes the following topics:
|
||||
|
||||
PPrriinncciipplleess ooff ooppeerraattiioonn
|
||||
|
||||
The before-filter Postfix SMTP server accepts connections from the Internet and
|
||||
does the usual relay access control, SASL authentication, TLS negotiation, RBL
|
||||
lookups, rejecting non-existent sender or recipient addresses, etc. The before-
|
||||
queue filter receives unfiltered mail content from Postfix and does one of the
|
||||
following:
|
||||
As shown in the diagram above, the before-queue filter sits between two Postfix
|
||||
SMTP server processes.
|
||||
|
||||
1. Re-inject the mail back into Postfix via SMTP, perhaps after changing its
|
||||
content and/or destination.
|
||||
* The before-filter Postfix SMTP server accepts connections from the Internet
|
||||
and does the usual relay access control, SASL authentication, TLS
|
||||
negotiation, RBL lookups, rejecting non-existent sender or recipient
|
||||
addresses, etc.
|
||||
|
||||
2. Discard or quarantine the mail.
|
||||
* The before-queue filter receives unfiltered mail content from Postfix and
|
||||
does one of the following:
|
||||
|
||||
3. Reject the mail by sending a suitable SMTP status code back to Postfix.
|
||||
Postfix passes the status back to the remote SMTP client. This way, Postfix
|
||||
does not have to send a bounce message.
|
||||
1. Re-inject the mail back into Postfix via SMTP, perhaps after changing
|
||||
its content and/or destination.
|
||||
|
||||
The after-filter Postfix SMTP server receives mail from the content filter.
|
||||
From then on Postfix processes the mail as usual.
|
||||
2. Discard or quarantine the mail.
|
||||
|
||||
3. Reject the mail by sending a suitable SMTP status code back to Postfix.
|
||||
Postfix passes the status back to the remote SMTP client. This way,
|
||||
Postfix does not have to send a bounce message.
|
||||
|
||||
* The after-filter Postfix SMTP server receives mail from the content filter.
|
||||
From then on Postfix processes the mail as usual.
|
||||
|
||||
The before-queue content filter described here works just like the after-queue
|
||||
content filter described in the FILTER_README document. In many cases you can
|
||||
|
@ -14,6 +14,33 @@ specifies the release date of a stable release or snapshot release.
|
||||
If you upgrade from Postfix 2.5 or earlier, read RELEASE_NOTES-2.6
|
||||
before proceeding.
|
||||
|
||||
Incompatibility with snapshot 20091229
|
||||
======================================
|
||||
|
||||
The verify(8) service now uses a persistent cache by default
|
||||
(address_verify_map = btree:$data_directory/verify_cache). To
|
||||
disable, specify "address_verify_map =" in main.cf.
|
||||
|
||||
When periodic cache cleanup is enabled (the default), the postscreen(8)
|
||||
and verify(8) servers now require that their cache databases support
|
||||
the "delete" and "sequence" operations. To disable periodic cache
|
||||
cleanup specify a zero xxx_cache_cleanup_interval.
|
||||
|
||||
Major changes with snapshot 20091229
|
||||
====================================
|
||||
|
||||
Periodic cache cleanup for the postscreen(8) and verify(8) cache
|
||||
databases. The time between cache cleanup runs is controlled with
|
||||
the address_verify_cache_cleanup_interval (default: 12h) and
|
||||
postscreen_cache_cleanup_interval (default: 12h) parameters. Cache
|
||||
cleanup increases the database access latency, so this should not
|
||||
be run more often than necessary.
|
||||
|
||||
In addition, the postscreen_cache_retention_time (default: 1d)
|
||||
parameter specifies how long to keep an expired entry in the cache.
|
||||
This prevents a client from being logged as "NEW" after its record
|
||||
expired only a little while ago.
|
||||
|
||||
Incompatibility with snapshot 20091209
|
||||
======================================
|
||||
|
||||
@ -112,11 +139,12 @@ without blocking mail:
|
||||
1 - Comment out the "smtp inet ... smtpd" service in master.cf,
|
||||
including any "-o parameter=value" entries that follow.
|
||||
|
||||
2 - Uncomment the new "smtpd pass ... smtpd" service in master.cf.
|
||||
2 - Uncomment the new "smtpd pass ... smtpd" service in master.cf,
|
||||
and duplicate any "-o parameter=value" entries from the smtpd
|
||||
service that was commented out in step 1.
|
||||
|
||||
3 - Uncomment the the new "smtp inet ... postscreen" service in
|
||||
master.cf, and duplicate any "-o parameter=value" entries from
|
||||
the smtpd service that was commented out in step 1.
|
||||
master.cf.
|
||||
|
||||
4 - Uncomment the new "dnsblog unix ... dnsblog" service in
|
||||
master.cf. This service does DNSBL lookups for postscreen(8)
|
||||
|
@ -2,11 +2,25 @@ Wish list:
|
||||
|
||||
Remove this file from the stable release.
|
||||
|
||||
It would be nice if the generic dict_cache(3) cache manager
|
||||
could postpone process suicide until cache cleanup is
|
||||
completed (but that is not possible when postscreen forks
|
||||
into the background to finish already-accepted connections).
|
||||
|
||||
When postscreen drops a connection, a 521 "greeting" should
|
||||
be of the form "521 servername..." and not have an enhanced
|
||||
status code. The "521 5.7.1" form can be used after EHLO.
|
||||
Of course no spammer is going to complain about Postfix
|
||||
SMTP compliance.
|
||||
|
||||
Find a place to document all the mail routing mechanisms
|
||||
in one place so people can figure out how Postfix works.
|
||||
|
||||
owner-listname does not work for shell commands.
|
||||
|
||||
Investigate viability of Sendmail socket maps (the moral
|
||||
equivalent of tcp_table(5)), and dns maps.
|
||||
|
||||
The BCC action is marked "not stable", perhaps because
|
||||
people would also expect BCC actions in header/body_checks.
|
||||
How much would it take to make the queue file editing code
|
||||
|
@ -108,11 +108,18 @@ filter</a>
|
||||
|
||||
<h2><a name="principles">Principles of operation</a></h2>
|
||||
|
||||
<p> The before-filter Postfix SMTP server accepts connections from the
|
||||
<p> As shown in the diagram above, the before-queue filter sits
|
||||
between two Postfix SMTP server processes. </p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li> <p> The before-filter Postfix SMTP server accepts connections from the
|
||||
Internet and does the usual relay access control, SASL authentication,
|
||||
TLS negotiation,
|
||||
RBL lookups, rejecting non-existent sender or recipient addresses,
|
||||
etc. The before-queue filter receives unfiltered mail content from
|
||||
etc. </p>
|
||||
|
||||
<li> <p> The before-queue filter receives unfiltered mail content from
|
||||
Postfix and does one of the following: </p>
|
||||
|
||||
<ol>
|
||||
@ -129,9 +136,11 @@ Postfix and does one of the following: </p>
|
||||
|
||||
</ol>
|
||||
|
||||
<p>The after-filter Postfix SMTP server receives mail from the
|
||||
<li> <p>The after-filter Postfix SMTP server receives mail from the
|
||||
content filter. From then on Postfix processes the mail as usual. </p>
|
||||
|
||||
</ul>
|
||||
|
||||
<p> The before-queue content filter described here works just like
|
||||
the after-queue content filter described in the <a href="FILTER_README.html">FILTER_README</a>
|
||||
document. In many cases you can use the same software, within the
|
||||
|
@ -58,8 +58,10 @@ CLEANUP(8) CLEANUP(8)
|
||||
<a href="http://tools.ietf.org/html/rfc822">RFC 822</a> (ARPA Internet Text Messages)
|
||||
<a href="http://tools.ietf.org/html/rfc2045">RFC 2045</a> (MIME: Format of Internet Message Bodies)
|
||||
<a href="http://tools.ietf.org/html/rfc2046">RFC 2046</a> (MIME: Media Types)
|
||||
<a href="http://tools.ietf.org/html/rfc2822">RFC 2822</a> (Internet Message Format)
|
||||
<a href="http://tools.ietf.org/html/rfc3463">RFC 3463</a> (Enhanced Status Codes)
|
||||
<a href="http://tools.ietf.org/html/rfc3464">RFC 3464</a> (Delivery status notifications)
|
||||
<a href="http://tools.ietf.org/html/rfc5322">RFC 5322</a> (Internet Message Format)
|
||||
|
||||
<b>DIAGNOSTICS</b>
|
||||
Problems and transactions are logged to <b>syslogd</b>(8).
|
||||
|
@ -119,6 +119,23 @@ Do not change this unless you have a complete understanding of <a href="http://t
|
||||
</p>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="address_verify_cache_cleanup_interval">address_verify_cache_cleanup_interval</a>
|
||||
(default: 12h)</b></DT><DD>
|
||||
|
||||
<p> The amount of time between <a href="verify.8.html">verify(8)</a> cache cleanup runs. Cache
|
||||
cleanup increases the load on the cache database and should therefore
|
||||
not be run frequently. This feature requires that the cache database
|
||||
supports the "delete" and "sequence" operators. Specify a zero
|
||||
interval to disable cache cleanup. </p>
|
||||
|
||||
<p> Time units: s (seconds), m (minutes), h (hours), d (days), w
|
||||
(weeks). </p>
|
||||
|
||||
<p> This feature is available in Postfix 2.7. </p>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="address_verify_default_transport">address_verify_default_transport</a>
|
||||
@ -249,7 +266,7 @@ This feature is available in Postfix 2.1 and later.
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="address_verify_poll_count">address_verify_poll_count</a>
|
||||
(default: 3)</b></DT><DD>
|
||||
(default: see "postconf -d" output)</b></DT><DD>
|
||||
|
||||
<p>
|
||||
How many times to query the <a href="verify.8.html">verify(8)</a> service for the completion
|
||||
@ -257,12 +274,16 @@ of an address verification request in progress.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The default poll count is 3.
|
||||
With Postfix version 2.7 and later, the SMTP server polls the
|
||||
<a href="verify.8.html">verify(8)</a> service up to three times under non-overload conditions,
|
||||
and only once when under overload. With earlier Postfix versions,
|
||||
the SMTP server always polls the <a href="verify.8.html">verify(8)</a> service up to three
|
||||
times.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Specify 1 to implement a crude form of greylisting, that is, always
|
||||
defer the first delivery request for a never seen before address.
|
||||
defer the first delivery request for a new address.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -6561,6 +6582,23 @@ never uses the remote SMTP client hostname. </p>
|
||||
<p> This feature is available in Postfix 2.7. </p>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a>
|
||||
(default: 12h)</b></DT><DD>
|
||||
|
||||
<p> The amount of time between <a href="postscreen.8.html">postscreen(8)</a> cache cleanup runs.
|
||||
Cache cleanup increases the load on the cache database and should
|
||||
therefore not be run frequently. This feature requires that the
|
||||
cache database supports the "delete" and "sequence" operators.
|
||||
Specify a zero interval to disable cache cleanup. </p>
|
||||
|
||||
<p> Time units: s (seconds), m (minutes), h (hours), d (days), w
|
||||
(weeks). </p>
|
||||
|
||||
<p> This feature is available in Postfix 2.7. </p>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="postscreen_cache_map">postscreen_cache_map</a>
|
||||
@ -6571,6 +6609,22 @@ never uses the remote SMTP client hostname. </p>
|
||||
<p> This feature is available in Postfix 2.7. </p>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="postscreen_cache_retention_time">postscreen_cache_retention_time</a>
|
||||
(default: 1d)</b></DT><DD>
|
||||
|
||||
<p> The amount of time that <a href="postscreen.8.html">postscreen(8)</a> will cache an expired
|
||||
temporary whitelist entry before it is removed. This prevents clients
|
||||
from being logged as "NEW" just because their cache entry expired
|
||||
an hour ago. </p>
|
||||
|
||||
<p> Time units: s (seconds), m (minutes), h (hours), d (days), w
|
||||
(weeks). </p>
|
||||
|
||||
<p> This feature is available in Postfix 2.7. </p>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="postscreen_cache_ttl">postscreen_cache_ttl</a>
|
||||
@ -6579,9 +6633,9 @@ never uses the remote SMTP client hostname. </p>
|
||||
<p> The amount of time that <a href="postscreen.8.html">postscreen(8)</a> will cache a decision for
|
||||
a specific SMTP client IP address. During this time, the client IP
|
||||
address is excluded from tests. If possible, expired decisions are
|
||||
renewed silently. Specify a non-zero time value (an integral value
|
||||
plus an optional one-letter suffix that specifies the time unit).
|
||||
</p>
|
||||
renewed automatically. Specify a non-zero time value (an integral
|
||||
value plus an optional one-letter suffix that specifies the time
|
||||
unit). </p>
|
||||
|
||||
<p> Time units: s (seconds), m (minutes), h (hours), d (days), w
|
||||
(weeks). </p>
|
||||
@ -6661,7 +6715,8 @@ IP address. </p>
|
||||
<DT><b><a name="postscreen_greet_banner">postscreen_greet_banner</a>
|
||||
(default: $<a href="postconf.5.html#smtpd_banner">smtpd_banner</a>)</b></DT><DD>
|
||||
|
||||
<p> The text in the optional "220-text..." server response that
|
||||
<p> The <i>text</i> in the optional "220-<i>text</i>..." server
|
||||
response that
|
||||
<a href="postscreen.8.html">postscreen(8)</a> sends ahead of the real Postfix SMTP server's "220
|
||||
text..." response, in an attempt to confuse bad SMTP clients so
|
||||
that they speak before their turn (pre-greet). Specify an empty
|
||||
@ -8905,7 +8960,7 @@ invalid responses. </p>
|
||||
<ul>
|
||||
|
||||
<li> <p> In the case of a multi-line reply, the Postfix SMTP client
|
||||
uses the last reply line's numerical SMTP reply code and enhanced
|
||||
uses the final reply line's numerical SMTP reply code and enhanced
|
||||
status code. </p>
|
||||
|
||||
<li> <p> The numerical SMTP reply code (XYZ) takes precedence over
|
||||
@ -8924,16 +8979,16 @@ server, except that the trailing <CR><LF> are removed. </p>
|
||||
|
||||
<pre>
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#smtp_reply_filter">smtp_reply_filter</a> = <a href="pcre_table.5.html">pcre</a>:/etc/postfix/command_filter
|
||||
<a href="postconf.5.html#smtp_reply_filter">smtp_reply_filter</a> = <a href="pcre_table.5.html">pcre</a>:/etc/postfix/reply_filter
|
||||
</pre>
|
||||
|
||||
<pre>
|
||||
/etc/postfix/reply_filter:
|
||||
# Transform garbage into part of a multi-line reply. Note
|
||||
# that the Postfix SMTP client uses only the last numerical
|
||||
# SMTP reply code and enhanced status code from a multi-line
|
||||
# reply, so it does not matter what we substitute here as
|
||||
# long as it has the right syntax.
|
||||
# Transform garbage into "250-filler..." so that it looks like
|
||||
# one line from a multi-line reply. It does not matter what we
|
||||
# substitute here as long it has the right syntax. The Postfix
|
||||
# SMTP client will use the final line's numerical SMTP reply
|
||||
# code and enhanced status code.
|
||||
!/^([2-5][0-9][0-9]($|[- ]))/ 250-filler for garbage
|
||||
</pre>
|
||||
|
||||
@ -11226,6 +11281,20 @@ except that initial whitespace and the trailing <CR><LF>
|
||||
are removed. The result value is executed by the Postfix SMTP
|
||||
server. </p>
|
||||
|
||||
<p> Postfix already implements a number of workarounds for malformed
|
||||
client commands. </p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li> <p> Use "<a href="postconf.5.html#resolve_numeric_domain">resolve_numeric_domain</a> = yes" to accept "<i>user@ipaddress</i>"
|
||||
Postfix already accepts the correct form "<i>user@[ipaddress]</i>".
|
||||
</p>
|
||||
|
||||
<li> <p> Use "<a href="postconf.5.html#strict_rfc821_envelopes">strict_rfc821_envelopes</a> = no" to accept "<i>User Name
|
||||
<user@example.com></i>". </p>
|
||||
|
||||
</ul>
|
||||
|
||||
<p> Examples: </p>
|
||||
|
||||
<pre>
|
||||
@ -11557,8 +11626,9 @@ it changes under overload to just 1 with Postfix 2.6 and later.
|
||||
(default: no)</b></DT><DD>
|
||||
|
||||
<p>
|
||||
Require that a remote SMTP client introduces itself at the beginning
|
||||
of an SMTP session with the HELO or EHLO command.
|
||||
Require that a remote SMTP client introduces itself with the HELO
|
||||
or EHLO command before sending the MAIL command or other commands
|
||||
that require EHLO negotiation.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -12800,12 +12870,12 @@ inside the chroot jail. </p>
|
||||
|
||||
<p> By default (see <a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a>), client certificates are
|
||||
not requested, and <a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a> should remain empty. In contrast
|
||||
to <a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a>, DNs of certificate authorities installed
|
||||
to <a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a>, DNs of certificate authorities installed
|
||||
in $<a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a> are not included in the client certificate
|
||||
request message. MUAs with multiple client certificates may use the
|
||||
list of preferred certificate authorities to select the correct
|
||||
client certificate. You may want to put your "preferred" CA or
|
||||
CAs in $<a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a>, and install the remaining trusted CAs in
|
||||
CAs in $<a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a>, and install the remaining trusted CAs in
|
||||
$<a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a>. </p>
|
||||
|
||||
<p> Example: </p>
|
||||
|
@ -14,26 +14,34 @@ POSTSCREEN(8) POSTSCREEN(8)
|
||||
|
||||
<b>DESCRIPTION</b>
|
||||
The Postfix <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server performs triage on multi-
|
||||
ple inbound SMTP connections in parallel. The program can
|
||||
run in two basic modes.
|
||||
ple inbound SMTP connections in parallel. By running
|
||||
time-consuming tests in parallel in <a href="postscreen.8.html"><b>postscreen</b>(8)</a>, zombies
|
||||
and other bogus clients can be kept away from Postfix SMTP
|
||||
server processes. Thus, more Postfix SMTP server processes
|
||||
remain available for legitimate clients.
|
||||
|
||||
The purpose of <b>observation mode</b> is to collect statistics
|
||||
without actually blocking mail. <a href="postscreen.8.html"><b>postscreen</b>(8)</a> runs a num-
|
||||
ber of tests before it forwards a connection to a real
|
||||
SMTP server process. These tests introduce a delay of a
|
||||
few seconds; once a client passes the tests as "clean",
|
||||
its IP address is temporarily whitelisted and subsequent
|
||||
connections incur no delays until the temporary whitelist
|
||||
entry expires.
|
||||
This triage process involves a number of tests, documented
|
||||
below. The tests introduce a delay of a few seconds; once
|
||||
a client passes the tests, its IP address is temporarily
|
||||
whitelisted, typically for 24 hours.
|
||||
|
||||
The purpose of <b>enforcement mode</b> is to block mail without
|
||||
using up one Postfix SMTP server process for every connec-
|
||||
tion. Here, <a href="postscreen.8.html"><b>postscreen</b>(8)</a> terminates connections from
|
||||
SMTP clients that fail the above tests, and forwards only
|
||||
the remaining connections to a real SMTP server process.
|
||||
By running time-consuming spam tests in parallel in
|
||||
<a href="postscreen.8.html"><b>postscreen</b>(8)</a>, more Postfix SMTP server processes remain
|
||||
available for legitimate clients.
|
||||
The program can run in two basic modes.
|
||||
|
||||
<b>Observation mode</b>
|
||||
<a href="postscreen.8.html"><b>postscreen</b>(8)</a> reports the results of the tests, and
|
||||
forwards all connections to a real Postfix SMTP
|
||||
server process.
|
||||
|
||||
<b>Enforcement mode</b>
|
||||
<a href="postscreen.8.html"><b>postscreen</b>(8)</a> reports the results of the tests, but
|
||||
forwards only connections to a real SMTP server
|
||||
process from clients that passed the tests.
|
||||
|
||||
<a href="postscreen.8.html"><b>postscreen</b>(8)</a> disconnects clients that fail the
|
||||
tests, after sending a 521 status message (a future
|
||||
version may pass the connection to a dummy SMTP
|
||||
protocol engine that logs sender and recipient
|
||||
information).
|
||||
|
||||
Note: <a href="postscreen.8.html"><b>postscreen</b>(8)</a> is not an SMTP proxy; this is inten-
|
||||
tional. The purpose is to prioritize legitimate clients
|
||||
@ -44,144 +52,145 @@ POSTSCREEN(8) POSTSCREEN(8)
|
||||
<b>1. PERMANENT WHITELIST TEST</b>
|
||||
The <a href="postconf.5.html#postscreen_whitelist_networks">postscreen_whitelist_networks</a> parameter (default:
|
||||
$<a href="postconf.5.html#mynetworks">mynetworks</a>) specifies a permanent whitelist for SMTP
|
||||
client IP addresses. This feature is not used for
|
||||
addresses that appear on the permanent blacklist.
|
||||
client IP addresses.
|
||||
|
||||
When the SMTP client address matches the permanent
|
||||
When the SMTP client address matches the permanent
|
||||
whitelist, this is logged as:
|
||||
|
||||
<b>WHITELISTED</b> <i>address</i>
|
||||
|
||||
The action is not configurable: immediately forward the
|
||||
The action is not configurable: immediately forward the
|
||||
connection to a real SMTP server process.
|
||||
|
||||
<b>2. PERMANENT BLACKLIST TEST</b>
|
||||
The <a href="postconf.5.html#postscreen_blacklist_networks">postscreen_blacklist_networks</a> parameter (default:
|
||||
empty) specifies a permanent blacklist for SMTP client IP
|
||||
The <a href="postconf.5.html#postscreen_blacklist_networks">postscreen_blacklist_networks</a> parameter (default:
|
||||
empty) specifies a permanent blacklist for SMTP client IP
|
||||
addresses. The address syntax is as with <a href="postconf.5.html#mynetworks">mynetworks</a>.
|
||||
|
||||
When the SMTP client address matches the permanent black-
|
||||
When the SMTP client address matches the permanent black-
|
||||
list, this is logged as:
|
||||
|
||||
<b>BLACKLISTED</b> <i>address</i>
|
||||
|
||||
The <a href="postconf.5.html#postscreen_blacklist_action">postscreen_blacklist_action</a> parameter specifies the
|
||||
The <a href="postconf.5.html#postscreen_blacklist_action">postscreen_blacklist_action</a> parameter specifies the
|
||||
action that is taken next:
|
||||
|
||||
<b>continue</b> (default, observation mode)
|
||||
Continue with the SMTP GREETING PHASE TESTS below.
|
||||
Continue with the SMTP GREETING PHASE TESTS below.
|
||||
|
||||
<b>drop</b> (enforcement mode)
|
||||
Drop the connection immediately with a 521 SMTP
|
||||
reply. In a future implementation, the connection
|
||||
may instead be passed to a dummy SMTP protocol
|
||||
engine that logs sender and recipient information.
|
||||
Drop the connection immediately with a 521 SMTP
|
||||
reply. In a future implementation, the connection
|
||||
may instead be passed to a dummy SMTP protocol
|
||||
engine that logs sender and recipient information.
|
||||
|
||||
<b>3. TEMPORARY WHITELIST TEST</b>
|
||||
The <a href="postscreen.8.html"><b>postscreen</b>(8)</a> daemon maintains a <i>temporary</i> whitelist
|
||||
for SMTP client IP addresses that have passed all the
|
||||
tests described below. The <a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> parameter
|
||||
specifies the location of the temporary whitelist. The
|
||||
temporary whitelist is not used for SMTP client addresses
|
||||
The <a href="postscreen.8.html"><b>postscreen</b>(8)</a> daemon maintains a <i>temporary</i> whitelist
|
||||
for SMTP client IP addresses that have passed all the
|
||||
tests described below. The <a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> parameter
|
||||
specifies the location of the temporary whitelist. The
|
||||
temporary whitelist is not used for SMTP client addresses
|
||||
that appear on the <i>permanent</i> blacklist or whitelist.
|
||||
|
||||
When the SMTP client address appears on the temporary
|
||||
When the SMTP client address appears on the temporary
|
||||
whitelist, this is logged as:
|
||||
|
||||
<b>PASS OLD</b> <i>address</i>
|
||||
|
||||
The action is not configurable: immediately forward the
|
||||
connection to a real SMTP server process. The client is
|
||||
excluded from further tests until its temporary whitelist
|
||||
The action is not configurable: immediately forward the
|
||||
connection to a real SMTP server process. The client is
|
||||
excluded from further tests until its temporary whitelist
|
||||
entry expires, as controlled with the <a href="postconf.5.html#postscreen_cache_ttl">postscreen_cache_ttl</a>
|
||||
parameter. Expired entries are silently renewed if possi-
|
||||
ble.
|
||||
|
||||
<b>4. SMTP GREETING PHASE TESTS</b>
|
||||
The <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> parameter specifies a time
|
||||
The <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> parameter specifies a time
|
||||
interval during which <a href="postscreen.8.html"><b>postscreen</b>(8)</a> runs a number of tests
|
||||
as described below. These tests run before the client may
|
||||
see the real SMTP server's "220 text..." server greeting.
|
||||
in parallel. These tests are described below, and are run
|
||||
before the client may see the real SMTP server's "220
|
||||
text..." server greeting.
|
||||
|
||||
When the SMTP client passes all the tests, this is logged
|
||||
as:
|
||||
When the SMTP client passes all greeting-phase tests, this
|
||||
is logged as:
|
||||
|
||||
<b>PASS NEW</b> <i>address</i>
|
||||
|
||||
The action is to forward the connection to a real SMTP
|
||||
server process and to create a temporary whitelist entry
|
||||
that excludes the client IP address from further tests
|
||||
The action is to forward the connection to a real SMTP
|
||||
server process and to create a temporary whitelist entry
|
||||
that excludes the client IP address from further tests
|
||||
until the temporary whitelist entry expires, as controlled
|
||||
with the <a href="postconf.5.html#postscreen_cache_ttl">postscreen_cache_ttl</a> parameter.
|
||||
|
||||
In a future implementation, the connection may first be
|
||||
passed to a dummy SMTP protocol engine that implements
|
||||
more protocol tests including greylisting, before the
|
||||
In a future implementation, the connection may first be
|
||||
passed to a dummy SMTP protocol engine that implements
|
||||
more protocol tests including greylisting, before the
|
||||
client is allowed to talk to a real SMTP server process.
|
||||
|
||||
<b>4A. PREGREET TEST</b>
|
||||
The <a href="postconf.5.html#postscreen_greet_banner">postscreen_greet_banner</a> parameter specifies the text
|
||||
for a "220-text..." teaser banner (default: $<a href="postconf.5.html#smtpd_banner">smtpd_ban</a>-
|
||||
<a href="postconf.5.html#smtpd_banner">ner</a>). The <a href="postscreen.8.html"><b>postscreen</b>(8)</a> daemon sends this before the
|
||||
<a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> timer is started. The purpose of
|
||||
the teaser banner is to confuse SPAM clients so that they
|
||||
speak before their turn. It has no effect on SMTP clients
|
||||
that correctly implement the protocol.
|
||||
The <a href="postconf.5.html#postscreen_greet_banner">postscreen_greet_banner</a> parameter specifies the <i>text</i>
|
||||
portion of a "220-<i>text</i>..." teaser banner (default:
|
||||
$<a href="postconf.5.html#smtpd_banner">smtpd_banner</a>). The <a href="postscreen.8.html"><b>postscreen</b>(8)</a> daemon sends this
|
||||
before the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> timer is started. The
|
||||
purpose of the teaser banner is to confuse SPAM clients so
|
||||
that they speak before their turn. It has no effect on
|
||||
SMTP clients that correctly implement the protocol.
|
||||
|
||||
To avoid problems with broken SMTP engines in network
|
||||
appliances, either exclude them from all tests with the
|
||||
<a href="postconf.5.html#postscreen_whitelist_networks">postscreen_whitelist_networks</a> feature or else specify an
|
||||
empty <a href="postconf.5.html#postscreen_greet_banner">postscreen_greet_banner</a> value to disable the
|
||||
To avoid problems with broken SMTP engines in network
|
||||
appliances, either exclude them from all tests with the
|
||||
<a href="postconf.5.html#postscreen_whitelist_networks">postscreen_whitelist_networks</a> feature or else specify an
|
||||
empty <a href="postconf.5.html#postscreen_greet_banner">postscreen_greet_banner</a> value to disable the
|
||||
"220-text..." teaser banner.
|
||||
|
||||
When an SMTP client sends a command before the
|
||||
When an SMTP client sends a command before the
|
||||
<a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> time has elapsed, this is logged as:
|
||||
|
||||
<b>PREGREET</b> <i>count</i> <b>after</b> <i>time</i> <b>from</b> <i>address text...</i>
|
||||
|
||||
Translation: the client at <i>address</i> sent <i>count</i> bytes before
|
||||
its turn to speak, and this happened <i>time</i> seconds after
|
||||
the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> timer was started. The <i>text</i> is
|
||||
what the client sent (truncated to 100 bytes, and with
|
||||
its turn to speak, and this happened <i>time</i> seconds after
|
||||
the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> timer was started. The <i>text</i> is
|
||||
what the client sent (truncated to 100 bytes, and with
|
||||
non-printable characters replaced with "?").
|
||||
|
||||
The <a href="postconf.5.html#postscreen_greet_action">postscreen_greet_action</a> parameter specifies the action
|
||||
that is taken next:
|
||||
|
||||
<b>continue</b> (default, observation mode)
|
||||
Wait until the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> time has
|
||||
Wait until the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> time has
|
||||
elapsed, then report DNSBL lookup results if appli-
|
||||
cable. Either perform DNSBL-related actions or for-
|
||||
ward the connection to a real SMTP server process.
|
||||
ward the connection to a real SMTP server process.
|
||||
|
||||
<b>drop</b> (enforcement mode)
|
||||
Drop the connection immediately with a 521 SMTP
|
||||
reply. In a future implementation, the connection
|
||||
may instead be passed to a dummy SMTP protocol
|
||||
engine that logs sender and recipient information.
|
||||
Drop the connection immediately with a 521 SMTP
|
||||
reply. In a future implementation, the connection
|
||||
may instead be passed to a dummy SMTP protocol
|
||||
engine that logs sender and recipient information.
|
||||
|
||||
<b>4B. HANGUP TEST</b>
|
||||
When the SMTP client hangs up without sending any data
|
||||
When the SMTP client hangs up without sending any data
|
||||
before the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> time has elapsed, this is
|
||||
logged as:
|
||||
|
||||
<b>HANGUP after</b> <i>time</i> <b>from</b> <i>address</i>
|
||||
|
||||
The <a href="postconf.5.html#postscreen_hangup_action">postscreen_hangup_action</a> specifies the action that is
|
||||
The <a href="postconf.5.html#postscreen_hangup_action">postscreen_hangup_action</a> specifies the action that is
|
||||
taken next:
|
||||
|
||||
<b>continue</b> (default, observation mode)
|
||||
Wait until the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> time has
|
||||
Wait until the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> time has
|
||||
elapsed, then report DNSBL lookup results if appli-
|
||||
cable. Do not forward the broken connection to a
|
||||
cable. Do not forward the broken connection to a
|
||||
real SMTP server process.
|
||||
|
||||
<b>drop</b> (enforcement mode)
|
||||
Drop the connection immediately.
|
||||
|
||||
<b>4C. DNS BLOCKLIST TEST</b>
|
||||
The <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> parameter (default: empty)
|
||||
specifies a list of DNS blocklist servers.
|
||||
The <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> parameter (default: empty)
|
||||
specifies a list of DNS blocklist servers. These lookups
|
||||
are made in parallel.
|
||||
|
||||
When the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> time has elapsed, and the
|
||||
SMTP client address is listed with at least one of these
|
||||
@ -237,14 +246,6 @@ POSTSCREEN(8) POSTSCREEN(8)
|
||||
see the <a href="postconf.5.html#postscreen_blacklist_action">postscreen_blacklist_action</a> parameter for
|
||||
possible actions.
|
||||
|
||||
<b><a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> (btree:$<a href="postconf.5.html#data_directory">data_directory</a>/ps_whitelist)</b>
|
||||
Persistent storage for the <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server
|
||||
decisions.
|
||||
|
||||
<b><a href="postconf.5.html#postscreen_cache_ttl">postscreen_cache_ttl</a> (1d)</b>
|
||||
The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will cache a
|
||||
decision for a specific SMTP client IP address.
|
||||
|
||||
<b><a href="postconf.5.html#postscreen_dnsbl_action">postscreen_dnsbl_action</a> (continue)</b>
|
||||
The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
|
||||
client is listed at the DNS blocklist domains spec-
|
||||
@ -259,7 +260,7 @@ POSTSCREEN(8) POSTSCREEN(8)
|
||||
ified with the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> parameter.
|
||||
|
||||
<b><a href="postconf.5.html#postscreen_greet_banner">postscreen_greet_banner</a> ($<a href="postconf.5.html#smtpd_banner">smtpd_banner</a>)</b>
|
||||
The text in the optional "220-text..." server
|
||||
The <i>text</i> in the optional "220-<i>text</i>..." server
|
||||
response that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> sends ahead of the real
|
||||
Postfix SMTP server's "220 text..." response, in an
|
||||
attempt to confuse bad SMTP clients so that they
|
||||
@ -294,22 +295,40 @@ POSTSCREEN(8) POSTSCREEN(8)
|
||||
The internal service that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> forwards
|
||||
allowed connections to.
|
||||
|
||||
<b>CACHE CONTROLS</b>
|
||||
<b><a href="postconf.5.html#postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a> (12h)</b>
|
||||
The amount of time between <a href="postscreen.8.html"><b>postscreen</b>(8)</a> cache
|
||||
cleanup runs.
|
||||
|
||||
<b><a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> (btree:$<a href="postconf.5.html#data_directory">data_directory</a>/ps_whitelist)</b>
|
||||
Persistent storage for the <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server
|
||||
decisions.
|
||||
|
||||
<b><a href="postconf.5.html#postscreen_cache_retention_time">postscreen_cache_retention_time</a> (1d)</b>
|
||||
The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will cache an
|
||||
expired temporary whitelist entry before it is
|
||||
removed.
|
||||
|
||||
<b><a href="postconf.5.html#postscreen_cache_ttl">postscreen_cache_ttl</a> (1d)</b>
|
||||
The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will cache a
|
||||
decision for a specific SMTP client IP address.
|
||||
|
||||
<b>MISCELLANEOUS CONTROLS</b>
|
||||
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
|
||||
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
|
||||
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
|
||||
<a href="master.5.html">master.cf</a> configuration files.
|
||||
|
||||
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
|
||||
How much time a Postfix daemon process may take to
|
||||
handle a request before it is terminated by a
|
||||
How much time a Postfix daemon process may take to
|
||||
handle a request before it is terminated by a
|
||||
built-in watchdog timer.
|
||||
|
||||
<b><a href="postconf.5.html#delay_logging_resolution_limit">delay_logging_resolution_limit</a> (2)</b>
|
||||
The maximal number of digits after the decimal
|
||||
The maximal number of digits after the decimal
|
||||
point when logging sub-second delay values.
|
||||
|
||||
<b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b>
|
||||
The location of all postfix administrative com-
|
||||
The location of all postfix administrative com-
|
||||
mands.
|
||||
|
||||
<b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
|
||||
@ -317,24 +336,24 @@ POSTSCREEN(8) POSTSCREEN(8)
|
||||
over an internal communication channel.
|
||||
|
||||
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
|
||||
The maximum amount of time that an idle Postfix
|
||||
daemon process waits for an incoming connection
|
||||
The maximum amount of time that an idle Postfix
|
||||
daemon process waits for an incoming connection
|
||||
before terminating voluntarily.
|
||||
|
||||
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
|
||||
The process ID of a Postfix command or daemon
|
||||
The process ID of a Postfix command or daemon
|
||||
process.
|
||||
|
||||
<b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
|
||||
The process name of a Postfix command or daemon
|
||||
The process name of a Postfix command or daemon
|
||||
process.
|
||||
|
||||
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
|
||||
The syslog facility of Postfix logging.
|
||||
|
||||
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
|
||||
The mail system name that is prepended to the
|
||||
process name in syslog records, so that "smtpd"
|
||||
The mail system name that is prepended to the
|
||||
process name in syslog records, so that "smtpd"
|
||||
becomes, for example, "postfix/smtpd".
|
||||
|
||||
<b>SEE ALSO</b>
|
||||
@ -343,7 +362,7 @@ POSTSCREEN(8) POSTSCREEN(8)
|
||||
syslogd(8), system logging
|
||||
|
||||
<b>LICENSE</b>
|
||||
The Secure Mailer license must be distributed with this
|
||||
The Secure Mailer license must be distributed with this
|
||||
software.
|
||||
|
||||
<b>AUTHOR(S)</b>
|
||||
|
@ -906,123 +906,124 @@ SMTPD(8) SMTPD(8)
|
||||
|
||||
<b><a href="postconf.5.html#smtpd_helo_required">smtpd_helo_required</a> (no)</b>
|
||||
Require that a remote SMTP client introduces itself
|
||||
at the beginning of an SMTP session with the HELO
|
||||
or EHLO command.
|
||||
with the HELO or EHLO command before sending the
|
||||
MAIL command or other commands that require EHLO
|
||||
negotiation.
|
||||
|
||||
<b><a href="postconf.5.html#smtpd_helo_restrictions">smtpd_helo_restrictions</a> (empty)</b>
|
||||
Optional restrictions that the Postfix SMTP server
|
||||
Optional restrictions that the Postfix SMTP server
|
||||
applies in the context of the SMTP HELO command.
|
||||
|
||||
<b><a href="postconf.5.html#smtpd_sender_restrictions">smtpd_sender_restrictions</a> (empty)</b>
|
||||
Optional restrictions that the Postfix SMTP server
|
||||
Optional restrictions that the Postfix SMTP server
|
||||
applies in the context of the MAIL FROM command.
|
||||
|
||||
<b><a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> (<a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>,</b>
|
||||
<b><a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a>)</b>
|
||||
The access restrictions that the Postfix SMTP
|
||||
server applies in the context of the RCPT TO com-
|
||||
server applies in the context of the RCPT TO com-
|
||||
mand.
|
||||
|
||||
<b><a href="postconf.5.html#smtpd_etrn_restrictions">smtpd_etrn_restrictions</a> (empty)</b>
|
||||
Optional SMTP server access restrictions in the
|
||||
Optional SMTP server access restrictions in the
|
||||
context of a client ETRN request.
|
||||
|
||||
<b><a href="postconf.5.html#allow_untrusted_routing">allow_untrusted_routing</a> (no)</b>
|
||||
Forward mail with sender-specified routing
|
||||
(user[@%!]remote[@%!]site) from untrusted clients
|
||||
Forward mail with sender-specified routing
|
||||
(user[@%!]remote[@%!]site) from untrusted clients
|
||||
to destinations matching $<a href="postconf.5.html#relay_domains">relay_domains</a>.
|
||||
|
||||
<b><a href="postconf.5.html#smtpd_restriction_classes">smtpd_restriction_classes</a> (empty)</b>
|
||||
User-defined aliases for groups of access restric-
|
||||
User-defined aliases for groups of access restric-
|
||||
tions.
|
||||
|
||||
<b><a href="postconf.5.html#smtpd_null_access_lookup_key">smtpd_null_access_lookup_key</a> (</b><><b>)</b>
|
||||
The lookup key to be used in SMTP <a href="access.5.html"><b>access</b>(5)</a> tables
|
||||
The lookup key to be used in SMTP <a href="access.5.html"><b>access</b>(5)</a> tables
|
||||
instead of the null sender address.
|
||||
|
||||
<b><a href="postconf.5.html#permit_mx_backup_networks">permit_mx_backup_networks</a> (empty)</b>
|
||||
Restrict the use of the <a href="postconf.5.html#permit_mx_backup">permit_mx_backup</a> SMTP
|
||||
access feature to only domains whose primary MX
|
||||
access feature to only domains whose primary MX
|
||||
hosts match the listed networks.
|
||||
|
||||
Available in Postfix version 2.0 and later:
|
||||
|
||||
<b><a href="postconf.5.html#smtpd_data_restrictions">smtpd_data_restrictions</a> (empty)</b>
|
||||
Optional access restrictions that the Postfix SMTP
|
||||
Optional access restrictions that the Postfix SMTP
|
||||
server applies in the context of the SMTP DATA com-
|
||||
mand.
|
||||
|
||||
<b><a href="postconf.5.html#smtpd_expansion_filter">smtpd_expansion_filter</a> (see 'postconf -d' output)</b>
|
||||
What characters are allowed in $name expansions of
|
||||
What characters are allowed in $name expansions of
|
||||
RBL reply templates.
|
||||
|
||||
Available in Postfix version 2.1 and later:
|
||||
|
||||
<b><a href="postconf.5.html#smtpd_reject_unlisted_sender">smtpd_reject_unlisted_sender</a> (no)</b>
|
||||
Request that the Postfix SMTP server rejects mail
|
||||
from unknown sender addresses, even when no
|
||||
explicit <a href="postconf.5.html#reject_unlisted_sender">reject_unlisted_sender</a> access restriction
|
||||
Request that the Postfix SMTP server rejects mail
|
||||
from unknown sender addresses, even when no
|
||||
explicit <a href="postconf.5.html#reject_unlisted_sender">reject_unlisted_sender</a> access restriction
|
||||
is specified.
|
||||
|
||||
<b><a href="postconf.5.html#smtpd_reject_unlisted_recipient">smtpd_reject_unlisted_recipient</a> (yes)</b>
|
||||
Request that the Postfix SMTP server rejects mail
|
||||
Request that the Postfix SMTP server rejects mail
|
||||
for unknown recipient addresses, even when no
|
||||
explicit <a href="postconf.5.html#reject_unlisted_recipient">reject_unlisted_recipient</a> access restric-
|
||||
explicit <a href="postconf.5.html#reject_unlisted_recipient">reject_unlisted_recipient</a> access restric-
|
||||
tion is specified.
|
||||
|
||||
Available in Postfix version 2.2 and later:
|
||||
|
||||
<b><a href="postconf.5.html#smtpd_end_of_data_restrictions">smtpd_end_of_data_restrictions</a> (empty)</b>
|
||||
Optional access restrictions that the Postfix SMTP
|
||||
server applies in the context of the SMTP END-OF-
|
||||
Optional access restrictions that the Postfix SMTP
|
||||
server applies in the context of the SMTP END-OF-
|
||||
DATA command.
|
||||
|
||||
<b>SENDER AND RECIPIENT ADDRESS VERIFICATION CONTROLS</b>
|
||||
Postfix version 2.1 introduces sender and recipient
|
||||
address verification. This feature is implemented by
|
||||
sending probe email messages that are not actually deliv-
|
||||
ered. This feature is requested via the reject_unveri-
|
||||
fied_sender and <a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipient</a> access
|
||||
restrictions. The status of verification probes is main-
|
||||
Postfix version 2.1 introduces sender and recipient
|
||||
address verification. This feature is implemented by
|
||||
sending probe email messages that are not actually deliv-
|
||||
ered. This feature is requested via the reject_unveri-
|
||||
fied_sender and <a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipient</a> access
|
||||
restrictions. The status of verification probes is main-
|
||||
tained by the <a href="verify.8.html"><b>verify</b>(8)</a> server. See the file <a href="ADDRESS_VERIFICATION_README.html">ADDRESS_VER</a>-
|
||||
<a href="ADDRESS_VERIFICATION_README.html">IFICATION_README</a> for information about how to configure
|
||||
<a href="ADDRESS_VERIFICATION_README.html">IFICATION_README</a> for information about how to configure
|
||||
and operate the Postfix sender/recipient address verifica-
|
||||
tion service.
|
||||
|
||||
<b><a href="postconf.5.html#address_verify_poll_count">address_verify_poll_count</a> (3)</b>
|
||||
How many times to query the <a href="verify.8.html"><b>verify</b>(8)</a> service for
|
||||
the completion of an address verification request
|
||||
<b><a href="postconf.5.html#address_verify_poll_count">address_verify_poll_count</a> (see 'postconf -d' output)</b>
|
||||
How many times to query the <a href="verify.8.html"><b>verify</b>(8)</a> service for
|
||||
the completion of an address verification request
|
||||
in progress.
|
||||
|
||||
<b><a href="postconf.5.html#address_verify_poll_delay">address_verify_poll_delay</a> (3s)</b>
|
||||
The delay between queries for the completion of an
|
||||
The delay between queries for the completion of an
|
||||
address verification request in progress.
|
||||
|
||||
<b><a href="postconf.5.html#address_verify_sender">address_verify_sender</a> ($<a href="postconf.5.html#double_bounce_sender">double_bounce_sender</a>)</b>
|
||||
The sender address to use in address verification
|
||||
The sender address to use in address verification
|
||||
probes; prior to Postfix 2.5 the default was "post-
|
||||
master".
|
||||
|
||||
<b><a href="postconf.5.html#unverified_sender_reject_code">unverified_sender_reject_code</a> (450)</b>
|
||||
The numerical Postfix SMTP server response code
|
||||
when a recipient address is rejected by the
|
||||
The numerical Postfix SMTP server response code
|
||||
when a recipient address is rejected by the
|
||||
<a href="postconf.5.html#reject_unverified_sender">reject_unverified_sender</a> restriction.
|
||||
|
||||
<b><a href="postconf.5.html#unverified_recipient_reject_code">unverified_recipient_reject_code</a> (450)</b>
|
||||
The numerical Postfix SMTP server response when a
|
||||
The numerical Postfix SMTP server response when a
|
||||
recipient address is rejected by the reject_unveri-
|
||||
fied_recipient restriction.
|
||||
|
||||
Available in Postfix version 2.6 and later:
|
||||
|
||||
<b><a href="postconf.5.html#unverified_sender_defer_code">unverified_sender_defer_code</a> (450)</b>
|
||||
The numerical Postfix SMTP server response code
|
||||
when a sender address probe fails due to a tempo-
|
||||
The numerical Postfix SMTP server response code
|
||||
when a sender address probe fails due to a tempo-
|
||||
rary error condition.
|
||||
|
||||
<b><a href="postconf.5.html#unverified_recipient_defer_code">unverified_recipient_defer_code</a> (450)</b>
|
||||
The numerical Postfix SMTP server response when a
|
||||
recipient address probe fails due to a temporary
|
||||
The numerical Postfix SMTP server response when a
|
||||
recipient address probe fails due to a temporary
|
||||
error condition.
|
||||
|
||||
<b><a href="postconf.5.html#unverified_sender_reject_reason">unverified_sender_reject_reason</a> (empty)</b>
|
||||
@ -1036,7 +1037,7 @@ SMTPD(8) SMTPD(8)
|
||||
<b><a href="postconf.5.html#unverified_sender_tempfail_action">unverified_sender_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_temp</a>-</b>
|
||||
<b><a href="postconf.5.html#reject_tempfail_action">fail_action</a>)</b>
|
||||
The Postfix SMTP server's action when <a href="postconf.5.html#reject_unverified_sender">reject_unver</a>-
|
||||
<a href="postconf.5.html#reject_unverified_sender">ified_sender</a> fails due to a temporary error condi-
|
||||
<a href="postconf.5.html#reject_unverified_sender">ified_sender</a> fails due to a temporary error condi-
|
||||
tion.
|
||||
|
||||
<b><a href="postconf.5.html#unverified_recipient_tempfail_action">unverified_recipient_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_temp</a>-</b>
|
||||
@ -1046,7 +1047,7 @@ SMTPD(8) SMTPD(8)
|
||||
dition.
|
||||
|
||||
<b>ACCESS CONTROL RESPONSES</b>
|
||||
The following parameters control numerical SMTP reply
|
||||
The following parameters control numerical SMTP reply
|
||||
codes and/or text responses.
|
||||
|
||||
<b><a href="postconf.5.html#access_map_reject_code">access_map_reject_code</a> (554)</b>
|
||||
@ -1054,18 +1055,18 @@ SMTPD(8) SMTPD(8)
|
||||
an <a href="access.5.html"><b>access</b>(5)</a> map "reject" action.
|
||||
|
||||
<b><a href="postconf.5.html#defer_code">defer_code</a> (450)</b>
|
||||
The numerical Postfix SMTP server response code
|
||||
when a remote SMTP client request is rejected by
|
||||
The numerical Postfix SMTP server response code
|
||||
when a remote SMTP client request is rejected by
|
||||
the "defer" restriction.
|
||||
|
||||
<b><a href="postconf.5.html#invalid_hostname_reject_code">invalid_hostname_reject_code</a> (501)</b>
|
||||
The numerical Postfix SMTP server response code
|
||||
when the client HELO or EHLO command parameter is
|
||||
rejected by the <a href="postconf.5.html#reject_invalid_helo_hostname">reject_invalid_helo_hostname</a>
|
||||
The numerical Postfix SMTP server response code
|
||||
when the client HELO or EHLO command parameter is
|
||||
rejected by the <a href="postconf.5.html#reject_invalid_helo_hostname">reject_invalid_helo_hostname</a>
|
||||
restriction.
|
||||
|
||||
<b><a href="postconf.5.html#maps_rbl_reject_code">maps_rbl_reject_code</a> (554)</b>
|
||||
The numerical Postfix SMTP server response code
|
||||
The numerical Postfix SMTP server response code
|
||||
when a remote SMTP client request is blocked by the
|
||||
<a href="postconf.5.html#reject_rbl_client">reject_rbl_client</a>, <a href="postconf.5.html#reject_rhsbl_client">reject_rhsbl_client</a>,
|
||||
<a href="postconf.5.html#reject_rhsbl_sender">reject_rhsbl_sender</a> or <a href="postconf.5.html#reject_rhsbl_recipient">reject_rhsbl_recipient</a>
|
||||
@ -1073,53 +1074,53 @@ SMTPD(8) SMTPD(8)
|
||||
|
||||
<b><a href="postconf.5.html#non_fqdn_reject_code">non_fqdn_reject_code</a> (504)</b>
|
||||
The numerical Postfix SMTP server reply code when a
|
||||
client request is rejected by the
|
||||
client request is rejected by the
|
||||
<a href="postconf.5.html#reject_non_fqdn_helo_hostname">reject_non_fqdn_helo_hostname</a>,
|
||||
<a href="postconf.5.html#reject_non_fqdn_sender">reject_non_fqdn_sender</a> or <a href="postconf.5.html#reject_non_fqdn_recipient">reject_non_fqdn_recipient</a>
|
||||
restriction.
|
||||
|
||||
<b><a href="postconf.5.html#plaintext_reject_code">plaintext_reject_code</a> (450)</b>
|
||||
The numerical Postfix SMTP server response code
|
||||
when a request is rejected by the <b>reject_plain-</b>
|
||||
The numerical Postfix SMTP server response code
|
||||
when a request is rejected by the <b>reject_plain-</b>
|
||||
<b>text_session</b> restriction.
|
||||
|
||||
<b><a href="postconf.5.html#reject_code">reject_code</a> (554)</b>
|
||||
The numerical Postfix SMTP server response code
|
||||
when a remote SMTP client request is rejected by
|
||||
The numerical Postfix SMTP server response code
|
||||
when a remote SMTP client request is rejected by
|
||||
the "reject" restriction.
|
||||
|
||||
<b><a href="postconf.5.html#relay_domains_reject_code">relay_domains_reject_code</a> (554)</b>
|
||||
The numerical Postfix SMTP server response code
|
||||
when a client request is rejected by the
|
||||
The numerical Postfix SMTP server response code
|
||||
when a client request is rejected by the
|
||||
<a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a> recipient restriction.
|
||||
|
||||
<b><a href="postconf.5.html#unknown_address_reject_code">unknown_address_reject_code</a> (450)</b>
|
||||
The numerical Postfix SMTP server response code
|
||||
when a sender or recipient address is rejected by
|
||||
The numerical Postfix SMTP server response code
|
||||
when a sender or recipient address is rejected by
|
||||
the <a href="postconf.5.html#reject_unknown_sender_domain">reject_unknown_sender_domain</a> or
|
||||
<a href="postconf.5.html#reject_unknown_recipient_domain">reject_unknown_recipient_domain</a> restriction.
|
||||
|
||||
<b><a href="postconf.5.html#unknown_client_reject_code">unknown_client_reject_code</a> (450)</b>
|
||||
The numerical Postfix SMTP server response code
|
||||
when a client without valid address <=> name map-
|
||||
The numerical Postfix SMTP server response code
|
||||
when a client without valid address <=> name map-
|
||||
ping is rejected by the reject_unknown_client_host-
|
||||
name restriction.
|
||||
|
||||
<b><a href="postconf.5.html#unknown_hostname_reject_code">unknown_hostname_reject_code</a> (450)</b>
|
||||
The numerical Postfix SMTP server response code
|
||||
when the hostname specified with the HELO or EHLO
|
||||
command is rejected by the
|
||||
The numerical Postfix SMTP server response code
|
||||
when the hostname specified with the HELO or EHLO
|
||||
command is rejected by the
|
||||
<a href="postconf.5.html#reject_unknown_helo_hostname">reject_unknown_helo_hostname</a> restriction.
|
||||
|
||||
Available in Postfix version 2.0 and later:
|
||||
|
||||
<b><a href="postconf.5.html#default_rbl_reply">default_rbl_reply</a> (see 'postconf -d' output)</b>
|
||||
The default SMTP server response template for a
|
||||
request that is rejected by an RBL-based restric-
|
||||
The default SMTP server response template for a
|
||||
request that is rejected by an RBL-based restric-
|
||||
tion.
|
||||
|
||||
<b><a href="postconf.5.html#multi_recipient_bounce_reject_code">multi_recipient_bounce_reject_code</a> (550)</b>
|
||||
The numerical Postfix SMTP server response code
|
||||
The numerical Postfix SMTP server response code
|
||||
when a remote SMTP client request is blocked by the
|
||||
<a href="postconf.5.html#reject_multi_recipient_bounce">reject_multi_recipient_bounce</a> restriction.
|
||||
|
||||
@ -1130,38 +1131,38 @@ SMTPD(8) SMTPD(8)
|
||||
|
||||
<b><a href="postconf.5.html#access_map_defer_code">access_map_defer_code</a> (450)</b>
|
||||
The numerical Postfix SMTP server response code for
|
||||
an <a href="access.5.html"><b>access</b>(5)</a> map "defer" action, including
|
||||
an <a href="access.5.html"><b>access</b>(5)</a> map "defer" action, including
|
||||
"<a href="postconf.5.html#defer_if_permit">defer_if_permit</a>" or "<a href="postconf.5.html#defer_if_reject">defer_if_reject</a>".
|
||||
|
||||
<b><a href="postconf.5.html#reject_tempfail_action">reject_tempfail_action</a> (<a href="postconf.5.html#defer_if_permit">defer_if_permit</a>)</b>
|
||||
The Postfix SMTP server's action when a reject-type
|
||||
restriction fails due to a temporary error condi-
|
||||
restriction fails due to a temporary error condi-
|
||||
tion.
|
||||
|
||||
<b><a href="postconf.5.html#unknown_helo_hostname_tempfail_action">unknown_helo_hostname_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_temp</a>-</b>
|
||||
<b><a href="postconf.5.html#reject_tempfail_action">fail_action</a>)</b>
|
||||
The Postfix SMTP server's action when
|
||||
The Postfix SMTP server's action when
|
||||
<a href="postconf.5.html#reject_unknown_helo_hostname">reject_unknown_helo_hostname</a> fails due to an tempo-
|
||||
rary error condition.
|
||||
|
||||
<b><a href="postconf.5.html#unknown_address_tempfail_action">unknown_address_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_tempfail_action</a>)</b>
|
||||
The Postfix SMTP server's action when
|
||||
The Postfix SMTP server's action when
|
||||
<a href="postconf.5.html#reject_unknown_sender_domain">reject_unknown_sender_domain</a> or
|
||||
<a href="postconf.5.html#reject_unknown_recipient_domain">reject_unknown_recipient_domain</a> fail due to a tem-
|
||||
<a href="postconf.5.html#reject_unknown_recipient_domain">reject_unknown_recipient_domain</a> fail due to a tem-
|
||||
porary error condition.
|
||||
|
||||
<b>MISCELLANEOUS CONTROLS</b>
|
||||
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
|
||||
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
|
||||
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
|
||||
<a href="master.5.html">master.cf</a> configuration files.
|
||||
|
||||
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
|
||||
How much time a Postfix daemon process may take to
|
||||
handle a request before it is terminated by a
|
||||
How much time a Postfix daemon process may take to
|
||||
handle a request before it is terminated by a
|
||||
built-in watchdog timer.
|
||||
|
||||
<b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b>
|
||||
The location of all postfix administrative com-
|
||||
The location of all postfix administrative com-
|
||||
mands.
|
||||
|
||||
<b><a href="postconf.5.html#double_bounce_sender">double_bounce_sender</a> (double-bounce)</b>
|
||||
@ -1182,37 +1183,37 @@ SMTPD(8) SMTPD(8)
|
||||
and most Postfix daemon processes.
|
||||
|
||||
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
|
||||
The maximum amount of time that an idle Postfix
|
||||
daemon process waits for an incoming connection
|
||||
The maximum amount of time that an idle Postfix
|
||||
daemon process waits for an incoming connection
|
||||
before terminating voluntarily.
|
||||
|
||||
<b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
|
||||
The maximal number of incoming connections that a
|
||||
Postfix daemon process will service before termi-
|
||||
The maximal number of incoming connections that a
|
||||
Postfix daemon process will service before termi-
|
||||
nating voluntarily.
|
||||
|
||||
<b><a href="postconf.5.html#myhostname">myhostname</a> (see 'postconf -d' output)</b>
|
||||
The internet hostname of this mail system.
|
||||
|
||||
<b><a href="postconf.5.html#mynetworks">mynetworks</a> (see 'postconf -d' output)</b>
|
||||
The list of "trusted" SMTP clients that have more
|
||||
The list of "trusted" SMTP clients that have more
|
||||
privileges than "strangers".
|
||||
|
||||
<b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
|
||||
The domain name that locally-posted mail appears to
|
||||
come from, and that locally posted mail is deliv-
|
||||
come from, and that locally posted mail is deliv-
|
||||
ered to.
|
||||
|
||||
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
|
||||
The process ID of a Postfix command or daemon
|
||||
The process ID of a Postfix command or daemon
|
||||
process.
|
||||
|
||||
<b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
|
||||
The process name of a Postfix command or daemon
|
||||
The process name of a Postfix command or daemon
|
||||
process.
|
||||
|
||||
<b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
|
||||
The location of the Postfix top-level queue direc-
|
||||
The location of the Postfix top-level queue direc-
|
||||
tory.
|
||||
|
||||
<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
|
||||
@ -1220,28 +1221,28 @@ SMTPD(8) SMTPD(8)
|
||||
sions (user+foo).
|
||||
|
||||
<b><a href="postconf.5.html#smtpd_banner">smtpd_banner</a> ($<a href="postconf.5.html#myhostname">myhostname</a> ESMTP $<a href="postconf.5.html#mail_name">mail_name</a>)</b>
|
||||
The text that follows the 220 status code in the
|
||||
The text that follows the 220 status code in the
|
||||
SMTP greeting banner.
|
||||
|
||||
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
|
||||
The syslog facility of Postfix logging.
|
||||
|
||||
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
|
||||
The mail system name that is prepended to the
|
||||
process name in syslog records, so that "smtpd"
|
||||
The mail system name that is prepended to the
|
||||
process name in syslog records, so that "smtpd"
|
||||
becomes, for example, "postfix/smtpd".
|
||||
|
||||
Available in Postfix version 2.2 and later:
|
||||
|
||||
<b><a href="postconf.5.html#smtpd_forbidden_commands">smtpd_forbidden_commands</a> (CONNECT, GET, POST)</b>
|
||||
List of commands that causes the Postfix SMTP
|
||||
server to immediately terminate the session with a
|
||||
List of commands that causes the Postfix SMTP
|
||||
server to immediately terminate the session with a
|
||||
221 code.
|
||||
|
||||
Available in Postfix version 2.5 and later:
|
||||
|
||||
<b><a href="postconf.5.html#smtpd_client_port_logging">smtpd_client_port_logging</a> (no)</b>
|
||||
Enable logging of the remote SMTP client port in
|
||||
Enable logging of the remote SMTP client port in
|
||||
addition to the hostname and IP address.
|
||||
|
||||
<b>SEE ALSO</b>
|
||||
@ -1271,7 +1272,7 @@ SMTPD(8) SMTPD(8)
|
||||
<a href="XFORWARD_README.html">XFORWARD_README</a>, Postfix XFORWARD extension
|
||||
|
||||
<b>LICENSE</b>
|
||||
The Secure Mailer license must be distributed with this
|
||||
The Secure Mailer license must be distributed with this
|
||||
software.
|
||||
|
||||
<b>AUTHOR(S)</b>
|
||||
|
@ -115,17 +115,23 @@ VERIFY(8) VERIFY(8)
|
||||
The time after which a failed address verification
|
||||
probe needs to be refreshed.
|
||||
|
||||
Available with Postfix 2.7 and later:
|
||||
|
||||
<b><a href="postconf.5.html#address_verify_cache_cleanup_interval">address_verify_cache_cleanup_interval</a> (12h)</b>
|
||||
The amount of time between <a href="verify.8.html"><b>verify</b>(8)</a> cache cleanup
|
||||
runs.
|
||||
|
||||
<b>PROBE MESSAGE ROUTING CONTROLS</b>
|
||||
By default, probe messages are delivered via the same
|
||||
route as regular messages. The following parameters can
|
||||
By default, probe messages are delivered via the same
|
||||
route as regular messages. The following parameters can
|
||||
be used to override specific message routing mechanisms.
|
||||
|
||||
<b><a href="postconf.5.html#address_verify_relayhost">address_verify_relayhost</a> ($<a href="postconf.5.html#relayhost">relayhost</a>)</b>
|
||||
Overrides the <a href="postconf.5.html#relayhost">relayhost</a> parameter setting for
|
||||
Overrides the <a href="postconf.5.html#relayhost">relayhost</a> parameter setting for
|
||||
address verification probes.
|
||||
|
||||
<b><a href="postconf.5.html#address_verify_transport_maps">address_verify_transport_maps</a> ($<a href="postconf.5.html#transport_maps">transport_maps</a>)</b>
|
||||
Overrides the <a href="postconf.5.html#transport_maps">transport_maps</a> parameter setting for
|
||||
Overrides the <a href="postconf.5.html#transport_maps">transport_maps</a> parameter setting for
|
||||
address verification probes.
|
||||
|
||||
<b><a href="postconf.5.html#address_verify_local_transport">address_verify_local_transport</a> ($<a href="postconf.5.html#local_transport">local_transport</a>)</b>
|
||||
@ -133,7 +139,7 @@ VERIFY(8) VERIFY(8)
|
||||
address verification probes.
|
||||
|
||||
<b><a href="postconf.5.html#address_verify_virtual_transport">address_verify_virtual_transport</a> ($<a href="postconf.5.html#virtual_transport">virtual_transport</a>)</b>
|
||||
Overrides the <a href="postconf.5.html#virtual_transport">virtual_transport</a> parameter setting
|
||||
Overrides the <a href="postconf.5.html#virtual_transport">virtual_transport</a> parameter setting
|
||||
for address verification probes.
|
||||
|
||||
<b><a href="postconf.5.html#address_verify_relay_transport">address_verify_relay_transport</a> ($<a href="postconf.5.html#relay_transport">relay_transport</a>)</b>
|
||||
@ -141,17 +147,32 @@ VERIFY(8) VERIFY(8)
|
||||
address verification probes.
|
||||
|
||||
<b><a href="postconf.5.html#address_verify_default_transport">address_verify_default_transport</a> ($<a href="postconf.5.html#default_transport">default_transport</a>)</b>
|
||||
Overrides the <a href="postconf.5.html#default_transport">default_transport</a> parameter setting
|
||||
Overrides the <a href="postconf.5.html#default_transport">default_transport</a> parameter setting
|
||||
for address verification probes.
|
||||
|
||||
Available in Postfix 2.3 and later:
|
||||
|
||||
<b><a href="postconf.5.html#address_verify_sender_dependent_relayhost_maps">address_verify_sender_dependent_relayhost_maps</a></b>
|
||||
<b>($<a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a>)</b>
|
||||
Overrides the <a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a>
|
||||
parameter setting for address verification probes.
|
||||
|
||||
Available in Postfix 2.7 and later:
|
||||
|
||||
<b><a href="postconf.5.html#address_verify_sender_dependent_default_transport_maps">address_verify_sender_dependent_default_transport_maps</a></b>
|
||||
<b>($<a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a>)</b>
|
||||
Overrides the <a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_trans</a>-
|
||||
<a href="postconf.5.html#sender_dependent_default_transport_maps">port_maps</a> parameter setting for address verifica-
|
||||
tion probes.
|
||||
|
||||
<b>MISCELLANEOUS CONTROLS</b>
|
||||
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
|
||||
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
|
||||
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
|
||||
<a href="master.5.html">master.cf</a> configuration files.
|
||||
|
||||
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
|
||||
How much time a Postfix daemon process may take to
|
||||
handle a request before it is terminated by a
|
||||
How much time a Postfix daemon process may take to
|
||||
handle a request before it is terminated by a
|
||||
built-in watchdog timer.
|
||||
|
||||
<b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
|
||||
@ -159,23 +180,23 @@ VERIFY(8) VERIFY(8)
|
||||
over an internal communication channel.
|
||||
|
||||
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
|
||||
The process ID of a Postfix command or daemon
|
||||
The process ID of a Postfix command or daemon
|
||||
process.
|
||||
|
||||
<b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
|
||||
The process name of a Postfix command or daemon
|
||||
The process name of a Postfix command or daemon
|
||||
process.
|
||||
|
||||
<b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
|
||||
The location of the Postfix top-level queue direc-
|
||||
The location of the Postfix top-level queue direc-
|
||||
tory.
|
||||
|
||||
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
|
||||
The syslog facility of Postfix logging.
|
||||
|
||||
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
|
||||
The mail system name that is prepended to the
|
||||
process name in syslog records, so that "smtpd"
|
||||
The mail system name that is prepended to the
|
||||
process name in syslog records, so that "smtpd"
|
||||
becomes, for example, "postfix/smtpd".
|
||||
|
||||
<b>SEE ALSO</b>
|
||||
@ -188,7 +209,7 @@ VERIFY(8) VERIFY(8)
|
||||
<a href="ADDRESS_VERIFICATION_README.html">ADDRESS_VERIFICATION_README</a>, address verification howto
|
||||
|
||||
<b>LICENSE</b>
|
||||
The Secure Mailer license must be distributed with this
|
||||
The Secure Mailer license must be distributed with this
|
||||
software.
|
||||
|
||||
<b>HISTORY</b>
|
||||
|
@ -77,6 +77,17 @@ The numerical Postfix SMTP server response code for
|
||||
an \fBaccess\fR(5) map "reject" action.
|
||||
.PP
|
||||
Do not change this unless you have a complete understanding of RFC 2821.
|
||||
.SH address_verify_cache_cleanup_interval (default: 12h)
|
||||
The amount of time between \fBverify\fR(8) cache cleanup runs. Cache
|
||||
cleanup increases the load on the cache database and should therefore
|
||||
not be run frequently. This feature requires that the cache database
|
||||
supports the "delete" and "sequence" operators. Specify a zero
|
||||
interval to disable cache cleanup.
|
||||
.PP
|
||||
Time units: s (seconds), m (minutes), h (hours), d (days), w
|
||||
(weeks).
|
||||
.PP
|
||||
This feature is available in Postfix 2.7.
|
||||
.SH address_verify_default_transport (default: $default_transport)
|
||||
Overrides the default_transport parameter setting for address
|
||||
verification probes.
|
||||
@ -138,14 +149,18 @@ be refreshed.
|
||||
Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
|
||||
.PP
|
||||
This feature is available in Postfix 2.1 and later.
|
||||
.SH address_verify_poll_count (default: 3)
|
||||
.SH address_verify_poll_count (default: see "postconf -d" output)
|
||||
How many times to query the \fBverify\fR(8) service for the completion
|
||||
of an address verification request in progress.
|
||||
.PP
|
||||
The default poll count is 3.
|
||||
With Postfix version 2.7 and later, the SMTP server polls the
|
||||
\fBverify\fR(8) service up to three times under non-overload conditions,
|
||||
and only once when under overload. With earlier Postfix versions,
|
||||
the SMTP server always polls the \fBverify\fR(8) service up to three
|
||||
times.
|
||||
.PP
|
||||
Specify 1 to implement a crude form of greylisting, that is, always
|
||||
defer the first delivery request for a never seen before address.
|
||||
defer the first delivery request for a new address.
|
||||
.PP
|
||||
Example:
|
||||
.PP
|
||||
@ -3673,16 +3688,38 @@ The blacklist has higher precedence than whitelists. This feature
|
||||
never uses the remote SMTP client hostname.
|
||||
.PP
|
||||
This feature is available in Postfix 2.7.
|
||||
.SH postscreen_cache_cleanup_interval (default: 12h)
|
||||
The amount of time between \fBpostscreen\fR(8) cache cleanup runs.
|
||||
Cache cleanup increases the load on the cache database and should
|
||||
therefore not be run frequently. This feature requires that the
|
||||
cache database supports the "delete" and "sequence" operators.
|
||||
Specify a zero interval to disable cache cleanup.
|
||||
.PP
|
||||
Time units: s (seconds), m (minutes), h (hours), d (days), w
|
||||
(weeks).
|
||||
.PP
|
||||
This feature is available in Postfix 2.7.
|
||||
.SH postscreen_cache_map (default: btree:$data_directory/ps_whitelist)
|
||||
Persistent storage for the \fBpostscreen\fR(8) server decisions.
|
||||
.PP
|
||||
This feature is available in Postfix 2.7.
|
||||
.SH postscreen_cache_retention_time (default: 1d)
|
||||
The amount of time that \fBpostscreen\fR(8) will cache an expired
|
||||
temporary whitelist entry before it is removed. This prevents clients
|
||||
from being logged as "NEW" just because their cache entry expired
|
||||
an hour ago.
|
||||
.PP
|
||||
Time units: s (seconds), m (minutes), h (hours), d (days), w
|
||||
(weeks).
|
||||
.PP
|
||||
This feature is available in Postfix 2.7.
|
||||
.SH postscreen_cache_ttl (default: 1d)
|
||||
The amount of time that \fBpostscreen\fR(8) will cache a decision for
|
||||
a specific SMTP client IP address. During this time, the client IP
|
||||
address is excluded from tests. If possible, expired decisions are
|
||||
renewed silently. Specify a non-zero time value (an integral value
|
||||
plus an optional one-letter suffix that specifies the time unit).
|
||||
renewed automatically. Specify a non-zero time value (an integral
|
||||
value plus an optional one-letter suffix that specifies the time
|
||||
unit).
|
||||
.PP
|
||||
Time units: s (seconds), m (minutes), h (hours), d (days), w
|
||||
(weeks).
|
||||
@ -3722,7 +3759,8 @@ IP address.
|
||||
.PP
|
||||
This feature is available in Postfix 2.7.
|
||||
.SH postscreen_greet_banner (default: $smtpd_banner)
|
||||
The text in the optional "220-text..." server response that
|
||||
The \fItext\fR in the optional "220-\fItext\fR..." server
|
||||
response that
|
||||
\fBpostscreen\fR(8) sends ahead of the real Postfix SMTP server's "220
|
||||
text..." response, in an attempt to confuse bad SMTP clients so
|
||||
that they speak before their turn (pre-greet). Specify an empty
|
||||
@ -5028,7 +5066,7 @@ invalid responses.
|
||||
Notes:
|
||||
.IP \(bu
|
||||
In the case of a multi-line reply, the Postfix SMTP client
|
||||
uses the last reply line's numerical SMTP reply code and enhanced
|
||||
uses the final reply line's numerical SMTP reply code and enhanced
|
||||
status code.
|
||||
.IP \(bu
|
||||
The numerical SMTP reply code (XYZ) takes precedence over
|
||||
@ -5047,7 +5085,7 @@ Examples:
|
||||
.na
|
||||
.ft C
|
||||
/etc/postfix/main.cf:
|
||||
smtp_reply_filter = pcre:/etc/postfix/command_filter
|
||||
smtp_reply_filter = pcre:/etc/postfix/reply_filter
|
||||
.fi
|
||||
.ad
|
||||
.ft R
|
||||
@ -5056,11 +5094,11 @@ Examples:
|
||||
.na
|
||||
.ft C
|
||||
/etc/postfix/reply_filter:
|
||||
# Transform garbage into part of a multi-line reply. Note
|
||||
# that the Postfix SMTP client uses only the last numerical
|
||||
# SMTP reply code and enhanced status code from a multi-line
|
||||
# reply, so it does not matter what we substitute here as
|
||||
# long as it has the right syntax.
|
||||
# Transform garbage into "250-filler..." so that it looks like
|
||||
# one line from a multi-line reply. It does not matter what we
|
||||
# substitute here as long it has the right syntax. The Postfix
|
||||
# SMTP client will use the final line's numerical SMTP reply
|
||||
# code and enhanced status code.
|
||||
!/^([2-5][0-9][0-9]($|[- ]))/ 250-filler for garbage
|
||||
.fi
|
||||
.ad
|
||||
@ -6890,6 +6928,15 @@ except that initial whitespace and the trailing <CR><LF>
|
||||
are removed. The result value is executed by the Postfix SMTP
|
||||
server.
|
||||
.PP
|
||||
Postfix already implements a number of workarounds for malformed
|
||||
client commands.
|
||||
.IP \(bu
|
||||
Use "resolve_numeric_domain = yes" to accept "\fIuser@ipaddress\fR"
|
||||
Postfix already accepts the correct form "\fIuser@[ipaddress]\fR".
|
||||
.IP \(bu
|
||||
Use "strict_rfc821_envelopes = no" to accept "\fIUser Name
|
||||
<user@example.com>\fR".
|
||||
.PP
|
||||
Examples:
|
||||
.PP
|
||||
.nf
|
||||
@ -7104,8 +7151,9 @@ make without delivering mail. The Postfix SMTP server disconnects
|
||||
when the limit is exceeded. Normally the default limit is 20, but
|
||||
it changes under overload to just 1 with Postfix 2.6 and later.
|
||||
.SH smtpd_helo_required (default: no)
|
||||
Require that a remote SMTP client introduces itself at the beginning
|
||||
of an SMTP session with the HELO or EHLO command.
|
||||
Require that a remote SMTP client introduces itself with the HELO
|
||||
or EHLO command before sending the MAIL command or other commands
|
||||
that require EHLO negotiation.
|
||||
.PP
|
||||
Example:
|
||||
.PP
|
||||
@ -7927,12 +7975,12 @@ inside the chroot jail.
|
||||
.PP
|
||||
By default (see smtpd_tls_ask_ccert), client certificates are
|
||||
not requested, and smtpd_tls_CApath should remain empty. In contrast
|
||||
to smtp_tls_CAfile, DNs of certificate authorities installed
|
||||
to smtpd_tls_CAfile, DNs of certificate authorities installed
|
||||
in $smtpd_tls_CApath are not included in the client certificate
|
||||
request message. MUAs with multiple client certificates may use the
|
||||
list of preferred certificate authorities to select the correct
|
||||
client certificate. You may want to put your "preferred" CA or
|
||||
CAs in $smtp_tls_CAfile, and install the remaining trusted CAs in
|
||||
CAs in $smtpd_tls_CAfile, and install the remaining trusted CAs in
|
||||
$smtpd_tls_CApath.
|
||||
.PP
|
||||
Example:
|
||||
|
@ -54,8 +54,10 @@ in case of trouble.
|
||||
RFC 822 (ARPA Internet Text Messages)
|
||||
RFC 2045 (MIME: Format of Internet Message Bodies)
|
||||
RFC 2046 (MIME: Media Types)
|
||||
RFC 2822 (Internet Message Format)
|
||||
RFC 3463 (Enhanced Status Codes)
|
||||
RFC 3464 (Delivery status notifications)
|
||||
RFC 5322 (Internet Message Format)
|
||||
.SH DIAGNOSTICS
|
||||
.ad
|
||||
.fi
|
||||
|
@ -13,26 +13,31 @@ Postfix SMTP triage server
|
||||
.ad
|
||||
.fi
|
||||
The Postfix \fBpostscreen\fR(8) server performs triage on
|
||||
multiple inbound SMTP connections in parallel. The program
|
||||
can run in two basic modes.
|
||||
multiple inbound SMTP connections in parallel. By running
|
||||
time-consuming tests in parallel in \fBpostscreen\fR(8),
|
||||
zombies and other bogus clients can be kept away from Postfix
|
||||
SMTP server processes. Thus, more Postfix SMTP server
|
||||
processes remain available for legitimate clients.
|
||||
|
||||
The purpose of \fBobservation mode\fR is to collect statistics
|
||||
without actually blocking mail. \fBpostscreen\fR(8) runs a
|
||||
number of tests before it forwards a connection to a real
|
||||
SMTP server process. These tests introduce a delay of a
|
||||
few seconds; once a client passes the tests as "clean", its
|
||||
IP address is temporarily whitelisted and subsequent
|
||||
connections incur no delays until the temporary whitelist
|
||||
entry expires.
|
||||
This triage process involves a number of tests, documented
|
||||
below. The tests introduce a delay of a few seconds; once
|
||||
a client passes the tests, its IP address is temporarily
|
||||
whitelisted, typically for 24 hours.
|
||||
|
||||
The purpose of \fBenforcement mode\fR is to block mail
|
||||
without using up one Postfix SMTP server process for every
|
||||
connection. Here, \fBpostscreen\fR(8) terminates connections
|
||||
from SMTP clients that fail the above tests, and forwards
|
||||
only the remaining connections to a real SMTP server process.
|
||||
By running time-consuming spam tests in parallel in
|
||||
\fBpostscreen\fR(8), more Postfix SMTP server processes
|
||||
remain available for legitimate clients.
|
||||
The program can run in two basic modes.
|
||||
.IP "\fBObservation mode\fR"
|
||||
\fBpostscreen\fR(8) reports the results of the tests, and
|
||||
forwards all connections to a real Postfix SMTP server
|
||||
process.
|
||||
.IP "\fBEnforcement mode\fR"
|
||||
\fBpostscreen\fR(8) reports the results of the tests, but
|
||||
forwards only connections to a real SMTP server process
|
||||
from clients that passed the tests.
|
||||
.sp
|
||||
\fBpostscreen\fR(8) disconnects clients that fail the tests,
|
||||
after sending a 521 status message (a future version may
|
||||
pass the connection to a dummy SMTP protocol engine that
|
||||
logs sender and recipient information).
|
||||
.PP
|
||||
Note: \fBpostscreen\fR(8) is not an SMTP proxy; this is
|
||||
intentional. The purpose is to prioritize legitimate clients
|
||||
@ -44,8 +49,7 @@ with as little overhead as possible.
|
||||
.fi
|
||||
The postscreen_whitelist_networks parameter (default:
|
||||
$mynetworks) specifies a permanent whitelist for SMTP client
|
||||
IP addresses. This feature is not used for addresses that
|
||||
appear on the permanent blacklist.
|
||||
IP addresses.
|
||||
|
||||
When the SMTP client address matches the permanent whitelist,
|
||||
this is logged as:
|
||||
@ -105,12 +109,13 @@ parameter. Expired entries are silently renewed if possible.
|
||||
.ad
|
||||
.fi
|
||||
The postscreen_greet_wait parameter specifies a time interval
|
||||
during which \fBpostscreen\fR(8) runs a number of tests as
|
||||
described below. These tests run before the client may
|
||||
see the real SMTP server's "220 text..." server greeting.
|
||||
during which \fBpostscreen\fR(8) runs a number of tests in
|
||||
parallel. These tests are described below, and are run
|
||||
before the client may see the real SMTP server's "220
|
||||
text..." server greeting.
|
||||
|
||||
When the SMTP client passes all the tests, this is logged
|
||||
as:
|
||||
When the SMTP client passes all greeting-phase tests, this
|
||||
is logged as:
|
||||
.sp
|
||||
.nf
|
||||
\fBPASS NEW \fIaddress\fR
|
||||
@ -129,8 +134,9 @@ to talk to a real SMTP server process.
|
||||
.SH 4A. PREGREET TEST
|
||||
.ad
|
||||
.fi
|
||||
The postscreen_greet_banner parameter specifies the text
|
||||
for a "220-text..." teaser banner (default: $smtpd_banner).
|
||||
The postscreen_greet_banner parameter specifies the \fItext\fR
|
||||
portion of a "220-\fItext\fR..." teaser banner (default:
|
||||
$smtpd_banner).
|
||||
The \fBpostscreen\fR(8) daemon sends this before the
|
||||
postscreen_greet_wait timer is started. The purpose of the
|
||||
teaser banner is to confuse SPAM clients so that they speak
|
||||
@ -191,7 +197,8 @@ Drop the connection immediately.
|
||||
.ad
|
||||
.fi
|
||||
The postscreen_dnsbl_sites parameter (default: empty)
|
||||
specifies a list of DNS blocklist servers.
|
||||
specifies a list of DNS blocklist servers. These lookups
|
||||
are made in parallel.
|
||||
|
||||
When the postscreen_greet_wait time has elapsed, and the
|
||||
SMTP client address is listed with at least one of these
|
||||
@ -256,11 +263,6 @@ parameter.
|
||||
.IP "\fBpostscreen_blacklist_networks (empty)\fR"
|
||||
Network addresses that are permanently blacklisted; see the
|
||||
postscreen_blacklist_action parameter for possible actions.
|
||||
.IP "\fBpostscreen_cache_map (btree:$data_directory/ps_whitelist)\fR"
|
||||
Persistent storage for the \fBpostscreen\fR(8) server decisions.
|
||||
.IP "\fBpostscreen_cache_ttl (1d)\fR"
|
||||
The amount of time that \fBpostscreen\fR(8) will cache a decision for
|
||||
a specific SMTP client IP address.
|
||||
.IP "\fBpostscreen_dnsbl_action (continue)\fR"
|
||||
The action that \fBpostscreen\fR(8) takes when an SMTP client is listed
|
||||
at the DNS blocklist domains specified with the postscreen_dnsbl_sites
|
||||
@ -272,7 +274,8 @@ The action that \fBpostscreen\fR(8) takes when an SMTP client speaks
|
||||
before its turn within the time specified with the postscreen_greet_wait
|
||||
parameter.
|
||||
.IP "\fBpostscreen_greet_banner ($smtpd_banner)\fR"
|
||||
The text in the optional "220-text..." server response that
|
||||
The \fItext\fR in the optional "220-\fItext\fR..." server
|
||||
response that
|
||||
\fBpostscreen\fR(8) sends ahead of the real Postfix SMTP server's "220
|
||||
text..." response, in an attempt to confuse bad SMTP clients so
|
||||
that they speak before their turn (pre-greet).
|
||||
@ -297,6 +300,21 @@ will not be subjected to \fBpostscreen\fR(8) checks.
|
||||
.IP "\fBsmtpd_service (smtpd)\fR"
|
||||
The internal service that \fBpostscreen\fR(8) forwards allowed
|
||||
connections to.
|
||||
.SH "CACHE CONTROLS"
|
||||
.na
|
||||
.nf
|
||||
.ad
|
||||
.fi
|
||||
.IP "\fBpostscreen_cache_cleanup_interval (12h)\fR"
|
||||
The amount of time between \fBpostscreen\fR(8) cache cleanup runs.
|
||||
.IP "\fBpostscreen_cache_map (btree:$data_directory/ps_whitelist)\fR"
|
||||
Persistent storage for the \fBpostscreen\fR(8) server decisions.
|
||||
.IP "\fBpostscreen_cache_retention_time (1d)\fR"
|
||||
The amount of time that \fBpostscreen\fR(8) will cache an expired
|
||||
temporary whitelist entry before it is removed.
|
||||
.IP "\fBpostscreen_cache_ttl (1d)\fR"
|
||||
The amount of time that \fBpostscreen\fR(8) will cache a decision for
|
||||
a specific SMTP client IP address.
|
||||
.SH "MISCELLANEOUS CONTROLS"
|
||||
.na
|
||||
.nf
|
||||
|
@ -729,8 +729,9 @@ instead of requiring an explicit ".domain.tld" pattern.
|
||||
Optional SMTP server access restrictions in the context of a client
|
||||
SMTP connection request.
|
||||
.IP "\fBsmtpd_helo_required (no)\fR"
|
||||
Require that a remote SMTP client introduces itself at the beginning
|
||||
of an SMTP session with the HELO or EHLO command.
|
||||
Require that a remote SMTP client introduces itself with the HELO
|
||||
or EHLO command before sending the MAIL command or other commands
|
||||
that require EHLO negotiation.
|
||||
.IP "\fBsmtpd_helo_restrictions (empty)\fR"
|
||||
Optional restrictions that the Postfix SMTP server applies in the
|
||||
context of the SMTP HELO command.
|
||||
@ -791,7 +792,7 @@ verification probes is maintained by the \fBverify\fR(8) server.
|
||||
See the file ADDRESS_VERIFICATION_README for information
|
||||
about how to configure and operate the Postfix sender/recipient
|
||||
address verification service.
|
||||
.IP "\fBaddress_verify_poll_count (3)\fR"
|
||||
.IP "\fBaddress_verify_poll_count (see 'postconf -d' output)\fR"
|
||||
How many times to query the \fBverify\fR(8) service for the completion
|
||||
of an address verification request in progress.
|
||||
.IP "\fBaddress_verify_poll_delay (3s)\fR"
|
||||
|
@ -113,6 +113,10 @@ verification cache.
|
||||
.IP "\fBaddress_verify_negative_refresh_time (3h)\fR"
|
||||
The time after which a failed address verification probe needs to
|
||||
be refreshed.
|
||||
.PP
|
||||
Available with Postfix 2.7 and later:
|
||||
.IP "\fBaddress_verify_cache_cleanup_interval (12h)\fR"
|
||||
The amount of time between \fBverify\fR(8) cache cleanup runs.
|
||||
.SH "PROBE MESSAGE ROUTING CONTROLS"
|
||||
.na
|
||||
.nf
|
||||
@ -139,6 +143,16 @@ verification probes.
|
||||
.IP "\fBaddress_verify_default_transport ($default_transport)\fR"
|
||||
Overrides the default_transport parameter setting for address
|
||||
verification probes.
|
||||
.PP
|
||||
Available in Postfix 2.3 and later:
|
||||
.IP "\fBaddress_verify_sender_dependent_relayhost_maps ($sender_dependent_relayhost_maps)\fR"
|
||||
Overrides the sender_dependent_relayhost_maps parameter setting for address
|
||||
verification probes.
|
||||
.PP
|
||||
Available in Postfix 2.7 and later:
|
||||
.IP "\fBaddress_verify_sender_dependent_default_transport_maps ($sender_dependent_default_transport_maps)\fR"
|
||||
Overrides the sender_dependent_default_transport_maps parameter
|
||||
setting for address verification probes.
|
||||
.SH "MISCELLANEOUS CONTROLS"
|
||||
.na
|
||||
.nf
|
||||
|
@ -76,6 +76,7 @@ while (<>) {
|
||||
s;\baddress_verify_negative_cache\b;<a href="postconf.5.html#address_verify_negative_cache">$&</a>;g;
|
||||
s;\baddress_verify_negative_expire_time\b;<a href="postconf.5.html#address_verify_negative_expire_time">$&</a>;g;
|
||||
s;\baddress_verify_negative_refresh_time\b;<a href="postconf.5.html#address_verify_negative_refresh_time">$&</a>;g;
|
||||
s;\baddress_verify_cache_cleanup_interval\b;<a href="postconf.5.html#address_verify_cache_cleanup_interval">$&</a>;g;
|
||||
s;\baddress_verify_poll_count\b;<a href="postconf.5.html#address_verify_poll_count">$&</a>;g;
|
||||
s;\baddress_verify_poll_delay\b;<a href="postconf.5.html#address_verify_poll_delay">$&</a>;g;
|
||||
s;\baddress_verify_positive_expire_time\b;<a href="postconf.5.html#address_verify_positive_expire_time">$&</a>;g;
|
||||
@ -899,6 +900,8 @@ while (<>) {
|
||||
# postscreen
|
||||
s;\bpostscreen_cache_map\b;<a href="postconf.5.html#postscreen_cache_map">$&</a>;g;
|
||||
s;\bpostscreen_cache_ttl\b;<a href="postconf.5.html#postscreen_cache_ttl">$&</a>;g;
|
||||
s;\bpostscreen_cache_cleanup_interval\b;<a href="postconf.5.html#postscreen_cache_cleanup_interval">$&</a>;g;
|
||||
s;\bpostscreen_cache_retention_time\b;<a href="postconf.5.html#postscreen_cache_retention_time">$&</a>;g;
|
||||
s;\bsmtpd_service\b;<a href="postconf.5.html#smtpd_service">$&</a>;g;
|
||||
s;\bpostscreen_post_queue_limit\b;<a href="postconf.5.html#postscreen_post_queue_limit">$&</a>;g;
|
||||
s;\bpostscreen_pre_queue_limit\b;<a href="postconf.5.html#postscreen_pre_queue_limit">$&</a>;g;
|
||||
|
@ -108,11 +108,18 @@ filter</a>
|
||||
|
||||
<h2><a name="principles">Principles of operation</a></h2>
|
||||
|
||||
<p> The before-filter Postfix SMTP server accepts connections from the
|
||||
<p> As shown in the diagram above, the before-queue filter sits
|
||||
between two Postfix SMTP server processes. </p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li> <p> The before-filter Postfix SMTP server accepts connections from the
|
||||
Internet and does the usual relay access control, SASL authentication,
|
||||
TLS negotiation,
|
||||
RBL lookups, rejecting non-existent sender or recipient addresses,
|
||||
etc. The before-queue filter receives unfiltered mail content from
|
||||
etc. </p>
|
||||
|
||||
<li> <p> The before-queue filter receives unfiltered mail content from
|
||||
Postfix and does one of the following: </p>
|
||||
|
||||
<ol>
|
||||
@ -129,9 +136,11 @@ Postfix and does one of the following: </p>
|
||||
|
||||
</ol>
|
||||
|
||||
<p>The after-filter Postfix SMTP server receives mail from the
|
||||
<li> <p>The after-filter Postfix SMTP server receives mail from the
|
||||
content filter. From then on Postfix processes the mail as usual. </p>
|
||||
|
||||
</ul>
|
||||
|
||||
<p> The before-queue content filter described here works just like
|
||||
the after-queue content filter described in the FILTER_README
|
||||
document. In many cases you can use the same software, within the
|
||||
|
@ -199,7 +199,7 @@ verification probes.
|
||||
This feature is available in Postfix 2.1 and later.
|
||||
</p>
|
||||
|
||||
%PARAM address_verify_map
|
||||
%PARAM address_verify_map
|
||||
|
||||
<p>
|
||||
Optional lookup table for persistent address verification status
|
||||
@ -280,7 +280,20 @@ Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
|
||||
This feature is available in Postfix 2.1 and later.
|
||||
</p>
|
||||
|
||||
%PARAM address_verify_poll_count 3
|
||||
%PARAM address_verify_cache_cleanup_interval 12h
|
||||
|
||||
<p> The amount of time between verify(8) cache cleanup runs. Cache
|
||||
cleanup increases the load on the cache database and should therefore
|
||||
not be run frequently. This feature requires that the cache database
|
||||
supports the "delete" and "sequence" operators. Specify a zero
|
||||
interval to disable cache cleanup. </p>
|
||||
|
||||
<p> Time units: s (seconds), m (minutes), h (hours), d (days), w
|
||||
(weeks). </p>
|
||||
|
||||
<p> This feature is available in Postfix 2.7. </p>
|
||||
|
||||
%PARAM address_verify_poll_count see "postconf -d" output
|
||||
|
||||
<p>
|
||||
How many times to query the verify(8) service for the completion
|
||||
@ -288,12 +301,16 @@ of an address verification request in progress.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The default poll count is 3.
|
||||
With Postfix version 2.7 and later, the SMTP server polls the
|
||||
verify(8) service up to three times under non-overload conditions,
|
||||
and only once when under overload. With earlier Postfix versions,
|
||||
the SMTP server always polls the verify(8) service up to three
|
||||
times.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Specify 1 to implement a crude form of greylisting, that is, always
|
||||
defer the first delivery request for a never seen before address.
|
||||
defer the first delivery request for a new address.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -5215,8 +5232,9 @@ This feature is available in Postfix 2.2 and later.
|
||||
%PARAM smtpd_helo_required no
|
||||
|
||||
<p>
|
||||
Require that a remote SMTP client introduces itself at the beginning
|
||||
of an SMTP session with the HELO or EHLO command.
|
||||
Require that a remote SMTP client introduces itself with the HELO
|
||||
or EHLO command before sending the MAIL command or other commands
|
||||
that require EHLO negotiation.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -8631,12 +8649,12 @@ inside the chroot jail. </p>
|
||||
|
||||
<p> By default (see smtpd_tls_ask_ccert), client certificates are
|
||||
not requested, and smtpd_tls_CApath should remain empty. In contrast
|
||||
to smtp_tls_CAfile, DNs of certificate authorities installed
|
||||
to smtpd_tls_CAfile, DNs of certificate authorities installed
|
||||
in $smtpd_tls_CApath are not included in the client certificate
|
||||
request message. MUAs with multiple client certificates may use the
|
||||
list of preferred certificate authorities to select the correct
|
||||
client certificate. You may want to put your "preferred" CA or
|
||||
CAs in $smtp_tls_CAfile, and install the remaining trusted CAs in
|
||||
CAs in $smtpd_tls_CAfile, and install the remaining trusted CAs in
|
||||
$smtpd_tls_CApath. </p>
|
||||
|
||||
<p> Example: </p>
|
||||
@ -12436,9 +12454,34 @@ receive a 421 reponse. </p>
|
||||
<p> The amount of time that postscreen(8) will cache a decision for
|
||||
a specific SMTP client IP address. During this time, the client IP
|
||||
address is excluded from tests. If possible, expired decisions are
|
||||
renewed silently. Specify a non-zero time value (an integral value
|
||||
plus an optional one-letter suffix that specifies the time unit).
|
||||
</p>
|
||||
renewed automatically. Specify a non-zero time value (an integral
|
||||
value plus an optional one-letter suffix that specifies the time
|
||||
unit). </p>
|
||||
|
||||
<p> Time units: s (seconds), m (minutes), h (hours), d (days), w
|
||||
(weeks). </p>
|
||||
|
||||
<p> This feature is available in Postfix 2.7. </p>
|
||||
|
||||
%PARAM postscreen_cache_retention_time 1d
|
||||
|
||||
<p> The amount of time that postscreen(8) will cache an expired
|
||||
temporary whitelist entry before it is removed. This prevents clients
|
||||
from being logged as "NEW" just because their cache entry expired
|
||||
an hour ago. </p>
|
||||
|
||||
<p> Time units: s (seconds), m (minutes), h (hours), d (days), w
|
||||
(weeks). </p>
|
||||
|
||||
<p> This feature is available in Postfix 2.7. </p>
|
||||
|
||||
%PARAM postscreen_cache_cleanup_interval 12h
|
||||
|
||||
<p> The amount of time between postscreen(8) cache cleanup runs.
|
||||
Cache cleanup increases the load on the cache database and should
|
||||
therefore not be run frequently. This feature requires that the
|
||||
cache database supports the "delete" and "sequence" operators.
|
||||
Specify a zero interval to disable cache cleanup. </p>
|
||||
|
||||
<p> Time units: s (seconds), m (minutes), h (hours), d (days), w
|
||||
(weeks). </p>
|
||||
@ -12560,7 +12603,8 @@ never uses the remote SMTP client hostname. </p>
|
||||
|
||||
%PARAM postscreen_greet_banner $smtpd_banner
|
||||
|
||||
<p> The text in the optional "220-text..." server response that
|
||||
<p> The <i>text</i> in the optional "220-<i>text</i>..." server
|
||||
response that
|
||||
postscreen(8) sends ahead of the real Postfix SMTP server's "220
|
||||
text..." response, in an attempt to confuse bad SMTP clients so
|
||||
that they speak before their turn (pre-greet). Specify an empty
|
||||
@ -12608,6 +12652,20 @@ except that initial whitespace and the trailing <CR><LF>
|
||||
are removed. The result value is executed by the Postfix SMTP
|
||||
server. </p>
|
||||
|
||||
<p> Postfix already implements a number of workarounds for malformed
|
||||
client commands. </p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li> <p> Use "resolve_numeric_domain = yes" to accept "<i>user@ipaddress</i>"
|
||||
Postfix already accepts the correct form "<i>user@[ipaddress]</i>".
|
||||
</p>
|
||||
|
||||
<li> <p> Use "strict_rfc821_envelopes = no" to accept "<i>User Name
|
||||
<user@example.com></i>". </p>
|
||||
|
||||
</ul>
|
||||
|
||||
<p> Examples: </p>
|
||||
|
||||
<pre>
|
||||
@ -12647,7 +12705,7 @@ invalid responses. </p>
|
||||
<ul>
|
||||
|
||||
<li> <p> In the case of a multi-line reply, the Postfix SMTP client
|
||||
uses the last reply line's numerical SMTP reply code and enhanced
|
||||
uses the final reply line's numerical SMTP reply code and enhanced
|
||||
status code. </p>
|
||||
|
||||
<li> <p> The numerical SMTP reply code (XYZ) takes precedence over
|
||||
@ -12666,16 +12724,16 @@ server, except that the trailing <CR><LF> are removed. </p>
|
||||
|
||||
<pre>
|
||||
/etc/postfix/main.cf:
|
||||
smtp_reply_filter = pcre:/etc/postfix/command_filter
|
||||
smtp_reply_filter = pcre:/etc/postfix/reply_filter
|
||||
</pre>
|
||||
|
||||
<pre>
|
||||
/etc/postfix/reply_filter:
|
||||
# Transform garbage into part of a multi-line reply. Note
|
||||
# that the Postfix SMTP client uses only the last numerical
|
||||
# SMTP reply code and enhanced status code from a multi-line
|
||||
# reply, so it does not matter what we substitute here as
|
||||
# long as it has the right syntax.
|
||||
# Transform garbage into "250-filler..." so that it looks like
|
||||
# one line from a multi-line reply. It does not matter what we
|
||||
# substitute here as long it has the right syntax. The Postfix
|
||||
# SMTP client will use the final line's numerical SMTP reply
|
||||
# code and enhanced status code.
|
||||
!/^([2-5][0-9][0-9]($|[- ]))/ 250-filler for garbage
|
||||
</pre>
|
||||
|
||||
|
@ -46,8 +46,10 @@
|
||||
/* RFC 822 (ARPA Internet Text Messages)
|
||||
/* RFC 2045 (MIME: Format of Internet Message Bodies)
|
||||
/* RFC 2046 (MIME: Media Types)
|
||||
/* RFC 2822 (Internet Message Format)
|
||||
/* RFC 3463 (Enhanced Status Codes)
|
||||
/* RFC 3464 (Delivery status notifications)
|
||||
/* RFC 5322 (Internet Message Format)
|
||||
/* DIAGNOSTICS
|
||||
/* Problems and transactions are logged to \fBsyslogd\fR(8).
|
||||
/* BUGS
|
||||
|
@ -2552,7 +2552,7 @@ extern int var_scache_stat_time;
|
||||
extern char *var_verify_service;
|
||||
|
||||
#define VAR_VERIFY_MAP "address_verify_map"
|
||||
#define DEF_VERIFY_MAP ""
|
||||
#define DEF_VERIFY_MAP "btree:$data_directory/verify_cache"
|
||||
extern char *var_verify_map;
|
||||
|
||||
#define VAR_VERIFY_POS_EXP "address_verify_positive_expire_time"
|
||||
@ -2575,12 +2575,16 @@ extern int var_verify_neg_try;
|
||||
#define DEF_VERIFY_NEG_CACHE 1
|
||||
extern bool var_verify_neg_cache;
|
||||
|
||||
#define VAR_VERIFY_SCAN_CACHE "address_verify_cache_cleanup_interval"
|
||||
#define DEF_VERIFY_SCAN_CACHE "12h"
|
||||
extern int var_verify_scan_cache;
|
||||
|
||||
#define VAR_VERIFY_SENDER "address_verify_sender"
|
||||
#define DEF_VERIFY_SENDER "$" VAR_DOUBLE_BOUNCE
|
||||
extern char *var_verify_sender;
|
||||
|
||||
#define VAR_VERIFY_POLL_COUNT "address_verify_poll_count"
|
||||
#define DEF_VERIFY_POLL_COUNT 3
|
||||
#define DEF_VERIFY_POLL_COUNT "${stress?1}${stress:3}"
|
||||
extern int var_verify_poll_count;
|
||||
|
||||
#define VAR_VERIFY_POLL_DELAY "address_verify_poll_delay"
|
||||
@ -3186,6 +3190,14 @@ extern int var_ps_pre_queue_limit;
|
||||
#define DEF_PS_CACHE_TTL "1d"
|
||||
extern int var_ps_cache_ttl;
|
||||
|
||||
#define VAR_PS_CACHE_RET "postscreen_cache_retention_time"
|
||||
#define DEF_PS_CACHE_RET "1d"
|
||||
extern int var_ps_cache_ret;
|
||||
|
||||
#define VAR_PS_CACHE_SCAN "postscreen_cache_cleanup_interval"
|
||||
#define DEF_PS_CACHE_SCAN "12h"
|
||||
extern int var_ps_cache_scan;
|
||||
|
||||
#define VAR_PS_GREET_WAIT "postscreen_greet_wait"
|
||||
#define DEF_PS_GREET_WAIT "4s"
|
||||
extern int var_ps_greet_wait;
|
||||
|
@ -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 "20091209"
|
||||
#define MAIL_RELEASE_DATE "20091229"
|
||||
#define MAIL_VERSION_NUMBER "2.7"
|
||||
|
||||
#ifdef SNAPSHOT
|
||||
|
@ -61,7 +61,9 @@ postscreen.o: ../../include/addr_match_list.h
|
||||
postscreen.o: ../../include/argv.h
|
||||
postscreen.o: ../../include/attr.h
|
||||
postscreen.o: ../../include/connect.h
|
||||
postscreen.o: ../../include/data_redirect.h
|
||||
postscreen.o: ../../include/dict.h
|
||||
postscreen.o: ../../include/dict_cache.h
|
||||
postscreen.o: ../../include/events.h
|
||||
postscreen.o: ../../include/format_tv.h
|
||||
postscreen.o: ../../include/htable.h
|
||||
|
@ -7,26 +7,31 @@
|
||||
/* \fBpostscreen\fR [generic Postfix daemon options]
|
||||
/* DESCRIPTION
|
||||
/* The Postfix \fBpostscreen\fR(8) server performs triage on
|
||||
/* multiple inbound SMTP connections in parallel. The program
|
||||
/* can run in two basic modes.
|
||||
/* multiple inbound SMTP connections in parallel. By running
|
||||
/* time-consuming tests in parallel in \fBpostscreen\fR(8),
|
||||
/* zombies and other bogus clients can be kept away from Postfix
|
||||
/* SMTP server processes. Thus, more Postfix SMTP server
|
||||
/* processes remain available for legitimate clients.
|
||||
/*
|
||||
/* The purpose of \fBobservation mode\fR is to collect statistics
|
||||
/* without actually blocking mail. \fBpostscreen\fR(8) runs a
|
||||
/* number of tests before it forwards a connection to a real
|
||||
/* SMTP server process. These tests introduce a delay of a
|
||||
/* few seconds; once a client passes the tests as "clean", its
|
||||
/* IP address is temporarily whitelisted and subsequent
|
||||
/* connections incur no delays until the temporary whitelist
|
||||
/* entry expires.
|
||||
/* This triage process involves a number of tests, documented
|
||||
/* below. The tests introduce a delay of a few seconds; once
|
||||
/* a client passes the tests, its IP address is temporarily
|
||||
/* whitelisted, typically for 24 hours.
|
||||
/*
|
||||
/* The purpose of \fBenforcement mode\fR is to block mail
|
||||
/* without using up one Postfix SMTP server process for every
|
||||
/* connection. Here, \fBpostscreen\fR(8) terminates connections
|
||||
/* from SMTP clients that fail the above tests, and forwards
|
||||
/* only the remaining connections to a real SMTP server process.
|
||||
/* By running time-consuming spam tests in parallel in
|
||||
/* \fBpostscreen\fR(8), more Postfix SMTP server processes
|
||||
/* remain available for legitimate clients.
|
||||
/* The program can run in two basic modes.
|
||||
/* .IP "\fBObservation mode\fR"
|
||||
/* \fBpostscreen\fR(8) reports the results of the tests, and
|
||||
/* forwards all connections to a real Postfix SMTP server
|
||||
/* process.
|
||||
/* .IP "\fBEnforcement mode\fR"
|
||||
/* \fBpostscreen\fR(8) reports the results of the tests, but
|
||||
/* forwards only connections to a real SMTP server process
|
||||
/* from clients that passed the tests.
|
||||
/* .sp
|
||||
/* \fBpostscreen\fR(8) disconnects clients that fail the tests,
|
||||
/* after sending a 521 status message (a future version may
|
||||
/* pass the connection to a dummy SMTP protocol engine that
|
||||
/* logs sender and recipient information).
|
||||
/* .PP
|
||||
/* Note: \fBpostscreen\fR(8) is not an SMTP proxy; this is
|
||||
/* intentional. The purpose is to prioritize legitimate clients
|
||||
@ -38,8 +43,7 @@
|
||||
/* .fi
|
||||
/* The postscreen_whitelist_networks parameter (default:
|
||||
/* $mynetworks) specifies a permanent whitelist for SMTP client
|
||||
/* IP addresses. This feature is not used for addresses that
|
||||
/* appear on the permanent blacklist.
|
||||
/* IP addresses.
|
||||
/*
|
||||
/* When the SMTP client address matches the permanent whitelist,
|
||||
/* this is logged as:
|
||||
@ -99,12 +103,13 @@
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The postscreen_greet_wait parameter specifies a time interval
|
||||
/* during which \fBpostscreen\fR(8) runs a number of tests as
|
||||
/* described below. These tests run before the client may
|
||||
/* see the real SMTP server's "220 text..." server greeting.
|
||||
/* during which \fBpostscreen\fR(8) runs a number of tests in
|
||||
/* parallel. These tests are described below, and are run
|
||||
/* before the client may see the real SMTP server's "220
|
||||
/* text..." server greeting.
|
||||
/*
|
||||
/* When the SMTP client passes all the tests, this is logged
|
||||
/* as:
|
||||
/* When the SMTP client passes all greeting-phase tests, this
|
||||
/* is logged as:
|
||||
/* .sp
|
||||
/* .nf
|
||||
/* \fBPASS NEW \fIaddress\fR
|
||||
@ -123,8 +128,9 @@
|
||||
/* .SH 4A. PREGREET TEST
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The postscreen_greet_banner parameter specifies the text
|
||||
/* for a "220-text..." teaser banner (default: $smtpd_banner).
|
||||
/* The postscreen_greet_banner parameter specifies the \fItext\fR
|
||||
/* portion of a "220-\fItext\fR..." teaser banner (default:
|
||||
/* $smtpd_banner).
|
||||
/* The \fBpostscreen\fR(8) daemon sends this before the
|
||||
/* postscreen_greet_wait timer is started. The purpose of the
|
||||
/* teaser banner is to confuse SPAM clients so that they speak
|
||||
@ -185,7 +191,8 @@
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The postscreen_dnsbl_sites parameter (default: empty)
|
||||
/* specifies a list of DNS blocklist servers.
|
||||
/* specifies a list of DNS blocklist servers. These lookups
|
||||
/* are made in parallel.
|
||||
/*
|
||||
/* When the postscreen_greet_wait time has elapsed, and the
|
||||
/* SMTP client address is listed with at least one of these
|
||||
@ -240,11 +247,6 @@
|
||||
/* .IP "\fBpostscreen_blacklist_networks (empty)\fR"
|
||||
/* Network addresses that are permanently blacklisted; see the
|
||||
/* postscreen_blacklist_action parameter for possible actions.
|
||||
/* .IP "\fBpostscreen_cache_map (btree:$data_directory/ps_whitelist)\fR"
|
||||
/* Persistent storage for the \fBpostscreen\fR(8) server decisions.
|
||||
/* .IP "\fBpostscreen_cache_ttl (1d)\fR"
|
||||
/* The amount of time that \fBpostscreen\fR(8) will cache a decision for
|
||||
/* a specific SMTP client IP address.
|
||||
/* .IP "\fBpostscreen_dnsbl_action (continue)\fR"
|
||||
/* The action that \fBpostscreen\fR(8) takes when an SMTP client is listed
|
||||
/* at the DNS blocklist domains specified with the postscreen_dnsbl_sites
|
||||
@ -256,7 +258,8 @@
|
||||
/* before its turn within the time specified with the postscreen_greet_wait
|
||||
/* parameter.
|
||||
/* .IP "\fBpostscreen_greet_banner ($smtpd_banner)\fR"
|
||||
/* The text in the optional "220-text..." server response that
|
||||
/* The \fItext\fR in the optional "220-\fItext\fR..." server
|
||||
/* response that
|
||||
/* \fBpostscreen\fR(8) sends ahead of the real Postfix SMTP server's "220
|
||||
/* text..." response, in an attempt to confuse bad SMTP clients so
|
||||
/* that they speak before their turn (pre-greet).
|
||||
@ -281,6 +284,19 @@
|
||||
/* .IP "\fBsmtpd_service (smtpd)\fR"
|
||||
/* The internal service that \fBpostscreen\fR(8) forwards allowed
|
||||
/* connections to.
|
||||
/* CACHE CONTROLS
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* .IP "\fBpostscreen_cache_cleanup_interval (12h)\fR"
|
||||
/* The amount of time between \fBpostscreen\fR(8) cache cleanup runs.
|
||||
/* .IP "\fBpostscreen_cache_map (btree:$data_directory/ps_whitelist)\fR"
|
||||
/* Persistent storage for the \fBpostscreen\fR(8) server decisions.
|
||||
/* .IP "\fBpostscreen_cache_retention_time (1d)\fR"
|
||||
/* The amount of time that \fBpostscreen\fR(8) will cache an expired
|
||||
/* temporary whitelist entry before it is removed.
|
||||
/* .IP "\fBpostscreen_cache_ttl (1d)\fR"
|
||||
/* The amount of time that \fBpostscreen\fR(8) will cache a decision for
|
||||
/* a specific SMTP client IP address.
|
||||
/* MISCELLANEOUS CONTROLS
|
||||
/* .ad
|
||||
/* .fi
|
||||
@ -347,7 +363,7 @@
|
||||
#include <events.h>
|
||||
#include <mymalloc.h>
|
||||
#include <myaddrinfo.h>
|
||||
#include <dict.h>
|
||||
#include <dict_cache.h>
|
||||
#include <sane_accept.h>
|
||||
#include <stringops.h>
|
||||
#include <set_eugid.h>
|
||||
@ -363,6 +379,7 @@
|
||||
#include <mail_version.h>
|
||||
#include <mail_proto.h>
|
||||
#include <addr_match_list.h>
|
||||
#include <data_redirect.h>
|
||||
|
||||
/* Master server protocols. */
|
||||
|
||||
@ -378,6 +395,8 @@ int var_ps_post_queue_limit;
|
||||
int var_ps_pre_queue_limit;
|
||||
int var_proc_limit;
|
||||
int var_ps_cache_ttl;
|
||||
int var_ps_cache_ret;
|
||||
int var_ps_cache_scan;
|
||||
int var_ps_greet_wait;
|
||||
char *var_ps_dnsbl_sites;
|
||||
char *var_ps_dnsbl_action;
|
||||
@ -425,7 +444,7 @@ typedef struct {
|
||||
|
||||
static int check_queue_length; /* connections being checked */
|
||||
static int post_queue_length; /* being sent to real SMTPD */
|
||||
static DICT *cache_map; /* cache table handle */
|
||||
static DICT_CACHE *cache_map; /* cache table handle */
|
||||
static VSTRING *temp; /* scratchpad */
|
||||
static char *smtp_service_name; /* path to real SMTPD */
|
||||
static char *teaser_greeting; /* spamware teaser banner */
|
||||
@ -520,26 +539,26 @@ static int ps_addr_match_list_match(ADDR_MATCH_LIST *addr_list,
|
||||
|
||||
/* ps_dict_get - time-critical table lookup */
|
||||
|
||||
static const char *ps_dict_get(DICT *dict, const char *key)
|
||||
static const char *ps_dict_get(DICT_CACHE *cache, const char *key)
|
||||
{
|
||||
const char *myname = "ps_dict_get";
|
||||
const char *result;
|
||||
|
||||
PS_GET_TIME_BEFORE_LOOKUP;
|
||||
result = dict_get(dict, key);
|
||||
PS_CHECK_TIME_AFTER_LOOKUP(dict->name, "lookup");
|
||||
result = dict_cache_lookup(cache, key);
|
||||
PS_CHECK_TIME_AFTER_LOOKUP(dict_cache_name(cache), "lookup");
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* ps_dict_put - table dictionary update */
|
||||
|
||||
static void ps_dict_put(DICT *dict, const char *key, const char *value)
|
||||
static void ps_dict_put(DICT_CACHE *cache, const char *key, const char *value)
|
||||
{
|
||||
const char *myname = "ps_dict_put";
|
||||
|
||||
PS_GET_TIME_BEFORE_LOOKUP;
|
||||
dict_put(dict, key, value);
|
||||
PS_CHECK_TIME_AFTER_LOOKUP(dict->name, "update");
|
||||
dict_cache_update(cache, key, value);
|
||||
PS_CHECK_TIME_AFTER_LOOKUP(dict_cache_name(cache), "update");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -965,6 +984,23 @@ static void smtp_read_event(int event, char *context)
|
||||
}
|
||||
}
|
||||
|
||||
/* postscreen_dump - dump some statistics before exit */
|
||||
|
||||
static void postscreen_dump(void)
|
||||
{
|
||||
|
||||
/*
|
||||
* Dump preliminary cache cleanup statistics when the process commits
|
||||
* suicide while a cache cleanup run is in progress. We can't currently
|
||||
* distinguish between "postfix reload" (we should restart) or "maximal
|
||||
* idle time reached" (we could finish the cache cleanup first).
|
||||
*/
|
||||
if (cache_map) {
|
||||
dict_cache_close(cache_map);
|
||||
cache_map = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* postscreen_drain - delayed exit after "postfix reload" */
|
||||
|
||||
static void postscreen_drain(char *unused_service, char **unused_argv)
|
||||
@ -989,7 +1025,7 @@ static void postscreen_drain(char *unused_service, char **unused_argv)
|
||||
* version is an improvement over its predecessor.
|
||||
*/
|
||||
if (cache_map != 0) {
|
||||
dict_close(cache_map);
|
||||
dict_cache_close(cache_map);
|
||||
cache_map = 0;
|
||||
}
|
||||
for (count = 0; /* see below */ ; count++) {
|
||||
@ -1181,10 +1217,31 @@ static void postscreen_service(VSTREAM *smtp_client_stream,
|
||||
postscreen_dnsbl_query(smtp_client_addr.buf);
|
||||
}
|
||||
|
||||
/* postscreen_cache_validator - validate one cache entry */
|
||||
|
||||
static int postscreen_cache_validator(const char *client_addr,
|
||||
const char *stamp_str,
|
||||
char *unused_context)
|
||||
{
|
||||
time_t stamp_time;
|
||||
|
||||
/*
|
||||
* This function is called by the cache cleanup pseudo thread.
|
||||
*
|
||||
* XX Eliminate code duplication and abstract the parser into a separate
|
||||
* routine.
|
||||
*
|
||||
* Don't report a client as "NEW" just because their cache entry expired.
|
||||
*/
|
||||
stamp_time = strtoul(stamp_str, 0, 10);
|
||||
return (event_time() < stamp_time + var_ps_cache_ttl + var_ps_cache_ret);
|
||||
}
|
||||
|
||||
/* pre_jail_init - pre-jail initialization */
|
||||
|
||||
static void pre_jail_init(char *unused_name, char **unused_argv)
|
||||
{
|
||||
VSTRING *redirect;
|
||||
|
||||
/*
|
||||
* Open read-only maps as before dropping privilege, for consistency with
|
||||
@ -1192,7 +1249,7 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
|
||||
*/
|
||||
if (*var_ps_wlist_nets)
|
||||
wlist_nets =
|
||||
addr_match_list_init(MATCH_FLAG_NONE, var_ps_wlist_nets);
|
||||
addr_match_list_init(MATCH_FLAG_NONE, var_ps_wlist_nets);
|
||||
|
||||
if (*var_ps_blist_nets)
|
||||
blist_nets =
|
||||
@ -1213,22 +1270,26 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
|
||||
* to jail, temporarily drop root privileges.
|
||||
*/
|
||||
SAVE_AND_SET_EUGID(var_owner_uid, var_owner_gid);
|
||||
redirect = vstring_alloc(100);
|
||||
|
||||
/*
|
||||
* Keep state in persistent external map. As a safety measure we sync the
|
||||
* database on each update. This hurts on LINUX systems that sync all
|
||||
* their dirty disk blocks whenever any application invokes fsync().
|
||||
*
|
||||
* Start the cache maintenance pseudo thread after dropping privileges.
|
||||
*/
|
||||
#define PS_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE)
|
||||
|
||||
if (*var_ps_cache_map)
|
||||
cache_map = dict_open(var_ps_cache_map,
|
||||
O_CREAT | O_RDWR,
|
||||
PS_DICT_OPEN_FLAGS);
|
||||
cache_map =
|
||||
dict_cache_open(data_redirect_map(redirect, var_ps_cache_map),
|
||||
O_CREAT | O_RDWR, PS_DICT_OPEN_FLAGS);
|
||||
|
||||
/*
|
||||
* Clean up and restore privilege.
|
||||
*/
|
||||
vstring_free(redirect);
|
||||
RESTORE_SAVED_EUGID();
|
||||
}
|
||||
|
||||
@ -1241,6 +1302,7 @@ static void post_jail_init(char *unused_name, char **unused_argv)
|
||||
"continue", PS_ACT_CONT,
|
||||
0, -1,
|
||||
};
|
||||
int expire_flags;
|
||||
|
||||
/*
|
||||
* This routine runs after the skeleton code has entered the chroot jail.
|
||||
@ -1275,6 +1337,18 @@ static void post_jail_init(char *unused_name, char **unused_argv)
|
||||
if ((hangup_action = name_code(actions, NAME_CODE_FLAG_NONE,
|
||||
var_ps_hangup_action)) < 0)
|
||||
msg_fatal("bad %s value: %s", VAR_PS_HUP_ACTION, var_ps_hangup_action);
|
||||
|
||||
/*
|
||||
* Start the cache maintenance pseudo thread last. Early cleanup makes
|
||||
* verbose logging more informative (we get positive confirmation that
|
||||
* the cleanup thread runs).
|
||||
*/
|
||||
expire_flags = DICT_CACHE_FLAG_EXP_SUMMARY;
|
||||
if (msg_verbose)
|
||||
expire_flags |= DICT_CACHE_FLAG_EXP_VERBOSE;
|
||||
if (cache_map != 0 && var_ps_cache_scan > 0)
|
||||
dict_cache_expire(cache_map, expire_flags, var_ps_cache_scan,
|
||||
postscreen_cache_validator, (char *) 0);
|
||||
}
|
||||
|
||||
MAIL_VERSION_STAMP_DECLARE;
|
||||
@ -1309,6 +1383,8 @@ int main(int argc, char **argv)
|
||||
static const CONFIG_TIME_TABLE time_table[] = {
|
||||
VAR_PS_CACHE_TTL, DEF_PS_CACHE_TTL, &var_ps_cache_ttl, 1, 0,
|
||||
VAR_PS_GREET_WAIT, DEF_PS_GREET_WAIT, &var_ps_greet_wait, 1, 0,
|
||||
VAR_PS_CACHE_RET, DEF_PS_CACHE_RET, &var_ps_cache_ret, 0, 0,
|
||||
VAR_PS_CACHE_SCAN, DEF_PS_CACHE_SCAN, &var_ps_cache_scan, 0, 0,
|
||||
0,
|
||||
};
|
||||
|
||||
@ -1326,5 +1402,6 @@ int main(int argc, char **argv)
|
||||
MAIL_SERVER_POST_INIT, post_jail_init,
|
||||
MAIL_SERVER_SOLITARY,
|
||||
MAIL_SERVER_SLOW_EXIT, postscreen_drain,
|
||||
MAIL_SERVER_EXIT, postscreen_dump,
|
||||
0);
|
||||
}
|
||||
|
@ -681,8 +681,9 @@
|
||||
/* Optional SMTP server access restrictions in the context of a client
|
||||
/* SMTP connection request.
|
||||
/* .IP "\fBsmtpd_helo_required (no)\fR"
|
||||
/* Require that a remote SMTP client introduces itself at the beginning
|
||||
/* of an SMTP session with the HELO or EHLO command.
|
||||
/* Require that a remote SMTP client introduces itself with the HELO
|
||||
/* or EHLO command before sending the MAIL command or other commands
|
||||
/* that require EHLO negotiation.
|
||||
/* .IP "\fBsmtpd_helo_restrictions (empty)\fR"
|
||||
/* Optional restrictions that the Postfix SMTP server applies in the
|
||||
/* context of the SMTP HELO command.
|
||||
@ -741,7 +742,7 @@
|
||||
/* See the file ADDRESS_VERIFICATION_README for information
|
||||
/* about how to configure and operate the Postfix sender/recipient
|
||||
/* address verification service.
|
||||
/* .IP "\fBaddress_verify_poll_count (3)\fR"
|
||||
/* .IP "\fBaddress_verify_poll_count (see 'postconf -d' output)\fR"
|
||||
/* How many times to query the \fBverify\fR(8) service for the completion
|
||||
/* of an address verification request in progress.
|
||||
/* .IP "\fBaddress_verify_poll_delay (3s)\fR"
|
||||
@ -4942,6 +4943,7 @@ int main(int argc, char **argv)
|
||||
VAR_SMTPD_SOFT_ERLIM, DEF_SMTPD_SOFT_ERLIM, &var_smtpd_soft_erlim, 1, 0,
|
||||
VAR_SMTPD_HARD_ERLIM, DEF_SMTPD_HARD_ERLIM, &var_smtpd_hard_erlim, 1, 0,
|
||||
VAR_SMTPD_JUNK_CMD, DEF_SMTPD_JUNK_CMD, &var_smtpd_junk_cmd_limit, 1, 0,
|
||||
VAR_VERIFY_POLL_COUNT, DEF_VERIFY_POLL_COUNT, &var_verify_poll_count, 1, 0,
|
||||
0,
|
||||
};
|
||||
static const CONFIG_INT_TABLE int_table[] = {
|
||||
@ -4970,7 +4972,6 @@ int main(int argc, char **argv)
|
||||
VAR_VIRT_MAILBOX_CODE, DEF_VIRT_MAILBOX_CODE, &var_virt_mailbox_code, 0, 0,
|
||||
VAR_RELAY_RCPT_CODE, DEF_RELAY_RCPT_CODE, &var_relay_rcpt_code, 0, 0,
|
||||
VAR_PLAINTEXT_CODE, DEF_PLAINTEXT_CODE, &var_plaintext_code, 0, 0,
|
||||
VAR_VERIFY_POLL_COUNT, DEF_VERIFY_POLL_COUNT, &var_verify_poll_count, 1, 0,
|
||||
VAR_SMTPD_CRATE_LIMIT, DEF_SMTPD_CRATE_LIMIT, &var_smtpd_crate_limit, 0, 0,
|
||||
VAR_SMTPD_CCONN_LIMIT, DEF_SMTPD_CCONN_LIMIT, &var_smtpd_cconn_limit, 0, 0,
|
||||
VAR_SMTPD_CMAIL_LIMIT, DEF_SMTPD_CMAIL_LIMIT, &var_smtpd_cmail_limit, 0, 0,
|
||||
|
@ -32,7 +32,7 @@ SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \
|
||||
write_buf.c write_wait.c sane_basename.c format_tv.c allspace.c \
|
||||
allascii.c load_file.c killme_after.c vstream_tweak.c upass_connect.c \
|
||||
upass_listen.c upass_trigger.c edit_file.c inet_windowsize.c \
|
||||
unix_pass_fd_fix.c
|
||||
unix_pass_fd_fix.c dict_cache.c
|
||||
OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
|
||||
attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
|
||||
attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
|
||||
@ -66,7 +66,7 @@ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
|
||||
write_buf.o write_wait.o sane_basename.o format_tv.o allspace.o \
|
||||
allascii.o load_file.o killme_after.o vstream_tweak.o upass_connect.o \
|
||||
upass_listen.o upass_trigger.o edit_file.o inet_windowsize.o \
|
||||
unix_pass_fd_fix.o
|
||||
unix_pass_fd_fix.o dict_cache.o
|
||||
HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
|
||||
chroot_uid.h cidr_match.h clean_env.h connect.h ctable.h dict.h \
|
||||
dict_cdb.h dict_cidr.h dict_db.h dict_dbm.h dict_env.h dict_ht.h \
|
||||
@ -86,7 +86,7 @@ HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
|
||||
stringops.h sys_defs.h timed_connect.h timed_wait.h trigger.h \
|
||||
username.h valid_hostname.h vbuf.h vbuf_print.h vstream.h vstring.h \
|
||||
vstring_vstream.h watchdog.h format_tv.h load_file.h killme_after.h \
|
||||
edit_file.h
|
||||
edit_file.h dict_cache.h
|
||||
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
|
||||
stream_test.c dup2_pass_on_exec.c test_send_fd test_recv_fd
|
||||
DEFS = -I. -D$(SYSTYPE)
|
||||
@ -740,6 +740,17 @@ dict_alloc.o: sys_defs.h
|
||||
dict_alloc.o: vbuf.h
|
||||
dict_alloc.o: vstream.h
|
||||
dict_alloc.o: vstring.h
|
||||
dict_cache.o: argv.h
|
||||
dict_cache.o: dict.h
|
||||
dict_cache.o: dict_cache.c
|
||||
dict_cache.o: dict_cache.h
|
||||
dict_cache.o: events.h
|
||||
dict_cache.o: msg.h
|
||||
dict_cache.o: mymalloc.h
|
||||
dict_cache.o: sys_defs.h
|
||||
dict_cache.o: vbuf.h
|
||||
dict_cache.o: vstream.h
|
||||
dict_cache.o: vstring.h
|
||||
dict_cdb.o: argv.h
|
||||
dict_cdb.o: dict.h
|
||||
dict_cdb.o: dict_cdb.c
|
||||
@ -1505,7 +1516,6 @@ stream_trigger.o: mymalloc.h
|
||||
stream_trigger.o: stream_trigger.c
|
||||
stream_trigger.o: sys_defs.h
|
||||
stream_trigger.o: trigger.h
|
||||
sys_compat.o: iostuff.h
|
||||
sys_compat.o: sys_compat.c
|
||||
sys_compat.o: sys_defs.h
|
||||
timed_connect.o: iostuff.h
|
||||
|
@ -107,15 +107,16 @@
|
||||
/* modified, or if the result is to survive multiple dict_lookup() calls.
|
||||
/*
|
||||
/* dict_delete() removes the named member from the named dictionary.
|
||||
/* The result is non-zero when the member does not exist.
|
||||
/* The result value is zero when the member was found.
|
||||
/*
|
||||
/* dict_sequence() steps throuh the named dictionary and returns
|
||||
/* dict_sequence() steps through the named dictionary and returns
|
||||
/* keys and values in some implementation-defined order. The func
|
||||
/* argument is DICT_SEQ_FUN_FIRST to set the cursor to the first
|
||||
/* entry or DICT_SEQ_FUN_NEXT to select the next entry. The result
|
||||
/* is owned by the underlying dictionary method. Make a copy if the
|
||||
/* result is to be modified, or if the result is to survive multiple
|
||||
/* dict_sequence() calls.
|
||||
/* dict_sequence() calls. The result value is zero when a member
|
||||
/* was found.
|
||||
/*
|
||||
/* dict_eval() expands macro references in the specified string.
|
||||
/* The result is owned by the dictionary manager. Make a copy if the
|
||||
|
577
postfix/src/util/dict_cache.c
Normal file
577
postfix/src/util/dict_cache.c
Normal file
@ -0,0 +1,577 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* dict_cache 3
|
||||
/* SUMMARY
|
||||
/* External cache manager
|
||||
/* SYNOPSIS
|
||||
/* #include <dict_cache.h>
|
||||
/*
|
||||
/* DICT_CACHE *dict_cache_open(dbname, open_flags, dict_flags)
|
||||
/* const char *dbname;
|
||||
/* int open_flags;
|
||||
/* int dict_flags;
|
||||
/*
|
||||
/* void dict_cache_close(cache)
|
||||
/* DICT_CACHE *cache;
|
||||
/*
|
||||
/* const char *dict_cache_lookup(cache, cache_key)
|
||||
/* DICT_CACHE *cache;
|
||||
/* const char *cache_key;
|
||||
/*
|
||||
/* int dict_cache_update(cache, cache_key, cache_val)
|
||||
/* DICT_CACHE *cache;
|
||||
/* const char *cache_key;
|
||||
/* const char *cache_val;
|
||||
/*
|
||||
/* int dict_cache_delete(cache, cache_key)
|
||||
/* DICT_CACHE *cache;
|
||||
/* const char *cache_key;
|
||||
/*
|
||||
/* int dict_cache_sequence(cache, first_next, cache_key, cache_val)
|
||||
/* DICT_CACHE *cache;
|
||||
/* int first_next;
|
||||
/* const char **cache_key;
|
||||
/* const char **cache_val;
|
||||
/*
|
||||
/* void dict_cache_expire(cache, flags, interval, validator, context)
|
||||
/* DICT_CACHE *cache;
|
||||
/* int flags;
|
||||
/* int interval;
|
||||
/* int (*validator)(const char *cache_key, const char *cache_val,
|
||||
/* char *context);
|
||||
/* char *context;
|
||||
/* AUXILIARY FUNCTIONS
|
||||
/* const char *dict_cache_name(cache)
|
||||
/* DICT_CACHE *cache;
|
||||
/*
|
||||
/* DICT_CACHE *dict_cache_import(table)
|
||||
/* DICT *table;
|
||||
/* DESCRIPTION
|
||||
/* This module maintains external cache files with support
|
||||
/* for expiration. The underlying table must implement the
|
||||
/* "lookup", "update", "delete" and "sequence" operations.
|
||||
/*
|
||||
/* Although this API is similar to the one documented in
|
||||
/* dict_open(3), there are subtle differences in the interaction
|
||||
/* between the iterators that access all cache elements, and
|
||||
/* other operations that access individual cache elements.
|
||||
/*
|
||||
/* In particular, when a "sequence" or "expire" operation is
|
||||
/* in progress the cache intercepts requests to delete the
|
||||
/* "current" entry, as this would cause some databases to
|
||||
/* mis-behave. Instead, the cache implements a "delete behind"
|
||||
/* strategy, and deletes such an entry after the "sequence"
|
||||
/* or "expire" operation moves on to the next cache element.
|
||||
/* The "delete behind" strategy also affects the cache lookup
|
||||
/* and update operations as detailed below.
|
||||
/*
|
||||
/* dict_cache_open() opens the specified cache and returns a
|
||||
/* handle that must be used for subsequent access. This function
|
||||
/* does not return in case of error.
|
||||
/*
|
||||
/* dict_cache_close() closes the specified cache and releases
|
||||
/* memory that was allocated by dict_cache_open(), and terminates
|
||||
/* any thread that was started with dict_cache_expire().
|
||||
/*
|
||||
/* dict_cache_lookup() looks up the specified cache entry.
|
||||
/* The result value is a null pointer when the cache entry was
|
||||
/* not found, or when the entry is scheduled for "delete
|
||||
/* behind".
|
||||
/*
|
||||
/* dict_cache_update() updates the specified cache entry. If
|
||||
/* the entry is scheduled for "delete behind", the delete
|
||||
/* operation is canceled (meaning that the cache must be opened
|
||||
/* with DICT_FLAG_DUP_REPLACE). This function does not return
|
||||
/* in case of error.
|
||||
/*
|
||||
/* dict_cache_delete() removes the specified cache entry. If
|
||||
/* this is the "current" entry of a "sequence" operation, the
|
||||
/* entry is scheduled for "delete behind". The result value
|
||||
/* is zero when the entry was found.
|
||||
/*
|
||||
/* dict_cache_sequence() iterates over the specified cache and
|
||||
/* returns each entry in an implementation-defined order. The
|
||||
/* result value is zero when a cache entry was found. Programs
|
||||
/* must not use both dict_cache_sequence() and dict_cache_expire().
|
||||
/*
|
||||
/* dict_cache_expire() schedules a thread that expires cache
|
||||
/* entries periodically. Specify a null validator argument to
|
||||
/* cancel the thread. It is an error to schedule a cache
|
||||
/* cleanup thread when one already exists. Programs must not
|
||||
/* use both dict_cache_sequence() and dict_cache_expire().
|
||||
/*
|
||||
/* dict_cache_name() returns the name of the specified cache.
|
||||
/*
|
||||
/* dict_cache_import() encapsulates a pre-opened database
|
||||
/* handle and adds the above features.
|
||||
/*
|
||||
/* Arguments:
|
||||
/* .IP "dbname, open_flags, dict_flags"
|
||||
/* These are passed unchanged to dict_open().
|
||||
/* .IP cache
|
||||
/* Cache handle created with dict_cache_open()or dict_cache_import().
|
||||
/* .IP cache_key
|
||||
/* Cache lookup key.
|
||||
/* .IP cache_val
|
||||
/* Information that is stored under a cache lookup key.
|
||||
/* .IP first_next
|
||||
/* One of DICT_SEQ_FUN_FIRST (first cache element) or
|
||||
/* DICT_SEQ_FUN_NEXT (next cache element).
|
||||
/* .sp
|
||||
/* Note: there is no "stop" request. To ensure that the "delete
|
||||
/* behind" strategy does not interfere with database access,
|
||||
/* allow dict_cache_sequence() to run to completion.
|
||||
/* .IP flags
|
||||
/* Bit-wise OR of zero or more of the following:
|
||||
/* .RS
|
||||
/* .IP DICT_CACHE_FLAG_EXP_VERBOSE
|
||||
/* Log each cache entry's status during a cache cleanup run.
|
||||
/* .IP DICT_CACHE_FLAG_EXP_SUMMARY
|
||||
/* Log the number of cache entries retained and dropped after
|
||||
/* a cache cleaning run.
|
||||
/* .RE
|
||||
/* .IP interval
|
||||
/* The non-zero time between scans for expired cache entries.
|
||||
/* The interval timer starts after a scan completes.
|
||||
/* .IP validator
|
||||
/* Application call-back routine that returns non-zero when a
|
||||
/* cache entry should be kept. The validator must not modify
|
||||
/* or close the cache.
|
||||
/* .IP context
|
||||
/* Application-specific context.
|
||||
/* .IP table
|
||||
/* A bare dictonary handle.
|
||||
/* DIAGNOSTICS
|
||||
/* These routines terminate with a fatal run-time error
|
||||
/* for unrecoverable database errors. This allows the
|
||||
/* program to restart and reset the database to an
|
||||
/* empty initial state.
|
||||
/* BUGS
|
||||
/* There should be a way to suspend automatic program suicide
|
||||
/* until a cache cleanup run is completed. Some entries may
|
||||
/* never be removed when the process max_idle time is less
|
||||
/* than the time needed to make a full pass over the cache.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* HISTORY
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* A predecessor of this code was written first for the Postfix
|
||||
/* tlsmgr(8) daemon.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include <sys_defs.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <msg.h>
|
||||
#include <dict.h>
|
||||
#include <mymalloc.h>
|
||||
#include <events.h>
|
||||
#include <dict_cache.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
/*
|
||||
* XXX Deleting entries while enumerating a map can he tricky. Some map
|
||||
* types have a concept of cursor and support a "delete the current element"
|
||||
* operation. Some map types without cursors don't behave well when the
|
||||
* current first/next entry is deleted (example: with Berkeley DB < 2, the
|
||||
* "next" operation produces garbage). To avoid trouble, we delete an entry
|
||||
* after advancing the current first/next position beyond it; we use the
|
||||
* same strategy with application requests to delete the current entry.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Opaque data structure. Use dict_cache_name() to access the name of the
|
||||
* underlying database.
|
||||
*/
|
||||
struct DICT_CACHE {
|
||||
int flags; /* see below */
|
||||
DICT *db; /* database handle */
|
||||
|
||||
/* Iterator support. */
|
||||
char *saved_curr_key; /* "current" cache lookup key */
|
||||
char *saved_curr_val; /* "current" cache lookup result */
|
||||
|
||||
/* Cleanup support. */
|
||||
int exp_flags; /* logging */
|
||||
int exp_interval; /* time between cleanup runs */
|
||||
DICT_CACHE_VALIDATOR_FN exp_validator; /* expiration call-back */
|
||||
char *exp_context; /* call-back context */
|
||||
int retained; /* entries retained in cleanup run */
|
||||
int dropped; /* entries removed in cleanup run */
|
||||
};
|
||||
|
||||
#define DC_FLAG_DEL_SAVED_CURRENT_KEY (1<<0) /* delete-behind is scheduled */
|
||||
|
||||
/*
|
||||
* Macros to make obscure code more readable.
|
||||
*/
|
||||
#define DC_SCHEDULE_FOR_DELETE_BEHIND(cp) \
|
||||
((cp)->flags |= DC_FLAG_DEL_SAVED_CURRENT_KEY)
|
||||
|
||||
#define DC_MATCH_SAVED_CURRENT_KEY(cp, cache_key) \
|
||||
((cp)->saved_curr_key && strcmp((cp)->saved_curr_key, (cache_key)) == 0)
|
||||
|
||||
#define DC_IS_SCHEDULED_FOR_DELETE_BEHIND(cp) \
|
||||
(/* NOT: (cp)->saved_curr_key && */ \
|
||||
((cp)->flags & DC_FLAG_DEL_SAVED_CURRENT_KEY) != 0)
|
||||
|
||||
#define DC_CANCEL_DELETE_BEHIND(cp) \
|
||||
((cp)->flags &= ~DC_FLAG_DEL_SAVED_CURRENT_KEY)
|
||||
|
||||
/*
|
||||
* Special key to store the time of last cache cleanup run completion.
|
||||
*/
|
||||
#define DC_LAST_CACHE_CLEANUP_COMPLETED "_LAST_CACHE_CLEANUP_COMPLETED_"
|
||||
|
||||
/* dict_cache_lookup - load entry from cache */
|
||||
|
||||
const char *dict_cache_lookup(DICT_CACHE *cp, const char *cache_key)
|
||||
{
|
||||
|
||||
/*
|
||||
* Search for the cache entry. Don't return an entry that was scheduled
|
||||
* for deletion.
|
||||
*/
|
||||
if (DC_IS_SCHEDULED_FOR_DELETE_BEHIND(cp)
|
||||
&& DC_MATCH_SAVED_CURRENT_KEY(cp, cache_key)) {
|
||||
return (0);
|
||||
} else {
|
||||
return (dict_get(cp->db, cache_key));
|
||||
}
|
||||
}
|
||||
|
||||
/* dict_cache_update - save entry to cache */
|
||||
|
||||
void dict_cache_update(DICT_CACHE *cp, const char *cache_key,
|
||||
const char *cache_val)
|
||||
{
|
||||
|
||||
/*
|
||||
* Store the cache entry and cancel a scheduled delete-behind operation.
|
||||
*/
|
||||
if (DC_IS_SCHEDULED_FOR_DELETE_BEHIND(cp)
|
||||
&& DC_MATCH_SAVED_CURRENT_KEY(cp, cache_key))
|
||||
DC_CANCEL_DELETE_BEHIND(cp);
|
||||
dict_put(cp->db, cache_key, cache_val);
|
||||
}
|
||||
|
||||
/* dict_cache_delete - delete entry from cache */
|
||||
|
||||
int dict_cache_delete(DICT_CACHE *cp, const char *cache_key)
|
||||
{
|
||||
int zero_means_found;
|
||||
|
||||
/*
|
||||
* Delete the entry, unless we would delete the current first/next entry.
|
||||
* Instead, schedule the "current" entry for delete-behind to avoid
|
||||
* mis-behavior by some databases.
|
||||
*/
|
||||
if (DC_MATCH_SAVED_CURRENT_KEY(cp, cache_key)) {
|
||||
DC_SCHEDULE_FOR_DELETE_BEHIND(cp);
|
||||
zero_means_found = 0;
|
||||
} else {
|
||||
zero_means_found = dict_del(cp->db, cache_key);
|
||||
}
|
||||
return (zero_means_found);
|
||||
}
|
||||
|
||||
/* dict_cache_sequence - look up the first/next cache entry */
|
||||
|
||||
int dict_cache_sequence(DICT_CACHE *cp, int first_next,
|
||||
const char **cache_key,
|
||||
const char **cache_val)
|
||||
{
|
||||
int zero_means_found;
|
||||
const char *raw_cache_key;
|
||||
const char *raw_cache_val;
|
||||
char *previous_curr_key;
|
||||
char *previous_curr_val;
|
||||
|
||||
/*
|
||||
* Find the first or next database entry. Hide the record with the cache
|
||||
* cleanup completion time stamp.
|
||||
*/
|
||||
zero_means_found =
|
||||
dict_seq(cp->db, first_next, &raw_cache_key, &raw_cache_val);
|
||||
if (zero_means_found == 0
|
||||
&& strcmp(raw_cache_key, DC_LAST_CACHE_CLEANUP_COMPLETED) == 0)
|
||||
zero_means_found =
|
||||
dict_seq(cp->db, DICT_SEQ_FUN_NEXT, &raw_cache_key, &raw_cache_val);
|
||||
|
||||
/*
|
||||
* Save the current cache_key and cache_val before they are clobbered by
|
||||
* our own delete operation below. This also prevents surprises when the
|
||||
* application accesses the database after this function returns.
|
||||
*
|
||||
* We also use the saved cache_key to protect the current entry against
|
||||
* application delete requests.
|
||||
*/
|
||||
previous_curr_key = cp->saved_curr_key;
|
||||
previous_curr_val = cp->saved_curr_val;
|
||||
if (zero_means_found == 0) {
|
||||
cp->saved_curr_key = mystrdup(raw_cache_key);
|
||||
cp->saved_curr_val = mystrdup(raw_cache_val);
|
||||
} else {
|
||||
cp->saved_curr_key = 0;
|
||||
cp->saved_curr_val = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete behind.
|
||||
*/
|
||||
if (DC_IS_SCHEDULED_FOR_DELETE_BEHIND(cp)) {
|
||||
DC_CANCEL_DELETE_BEHIND(cp);
|
||||
if (dict_del(cp->db, previous_curr_key) != 0)
|
||||
msg_warn("database %s: could not delete entry for %s",
|
||||
cp->db->name, previous_curr_key);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up previous iteration key and value.
|
||||
*/
|
||||
if (previous_curr_key)
|
||||
myfree(previous_curr_key);
|
||||
if (previous_curr_val)
|
||||
myfree(previous_curr_val);
|
||||
|
||||
/*
|
||||
* Return the result.
|
||||
*/
|
||||
*cache_key = (cp)->saved_curr_key;
|
||||
*cache_val = (cp)->saved_curr_val;
|
||||
return (zero_means_found);
|
||||
}
|
||||
|
||||
/* dict_cache_delete_behind_reset - reset "delete behind" state */
|
||||
|
||||
static void dict_cache_delete_behind_reset(DICT_CACHE *cp)
|
||||
{
|
||||
#define FREE_AND_WIPE(s) do { if (s) { myfree(s); (s) = 0; } } while (0)
|
||||
|
||||
DC_CANCEL_DELETE_BEHIND(cp);
|
||||
FREE_AND_WIPE(cp->saved_curr_key);
|
||||
FREE_AND_WIPE(cp->saved_curr_val);
|
||||
}
|
||||
|
||||
/* dict_cache_clean_stat_log_reset - log and reset cache cleanup statistics */
|
||||
|
||||
static void dict_cache_clean_stat_log_reset(DICT_CACHE *cp,
|
||||
const char *full_partial)
|
||||
{
|
||||
if (cp->flags & DICT_CACHE_FLAG_EXP_SUMMARY)
|
||||
msg_info("cache %s %s cleanup: retained=%d dropped=%d entries",
|
||||
cp->db->name, full_partial, cp->retained, cp->dropped);
|
||||
cp->retained = cp->dropped = 0;
|
||||
}
|
||||
|
||||
/* dict_cache_expire_event - examine one cache entry */
|
||||
|
||||
static void dict_cache_expire_event(int unused_event, char *cache_context)
|
||||
{
|
||||
DICT_CACHE *cp = (DICT_CACHE *) cache_context;
|
||||
const char *cache_key;
|
||||
const char *cache_val;
|
||||
int next_interval;
|
||||
VSTRING *stamp_buf;
|
||||
int first_next;
|
||||
|
||||
/*
|
||||
* We interleave cache cleanup with other processing, so that the
|
||||
* application's service remains available, with perhaps increased
|
||||
* latency.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Start a new cache cleanup run.
|
||||
*/
|
||||
if (cp->saved_curr_key == 0) {
|
||||
cp->retained = cp->dropped = 0;
|
||||
first_next = DICT_SEQ_FUN_FIRST;
|
||||
if (cp->exp_flags & DICT_CACHE_FLAG_EXP_VERBOSE)
|
||||
msg_info("start %s cache cleanup", cp->db->name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Continue a cache cleanup run in progress.
|
||||
*/
|
||||
else {
|
||||
first_next = DICT_SEQ_FUN_NEXT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Examine one cache entry.
|
||||
*/
|
||||
if (dict_cache_sequence(cp, first_next, &cache_key, &cache_val) == 0) {
|
||||
if (cp->exp_validator(cache_key, cache_val, cp->exp_context) == 0) {
|
||||
DC_SCHEDULE_FOR_DELETE_BEHIND(cp);
|
||||
cp->dropped++;
|
||||
if (cp->exp_flags & DICT_CACHE_FLAG_EXP_VERBOSE)
|
||||
msg_info("drop %s cache entry for %s", cp->db->name, cache_key);
|
||||
} else {
|
||||
cp->retained++;
|
||||
if (cp->exp_flags & DICT_CACHE_FLAG_EXP_VERBOSE)
|
||||
msg_info("keep %s cache entry for %s", cp->db->name, cache_key);
|
||||
}
|
||||
next_interval = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cache cleanup completed. Report vital statistics.
|
||||
*/
|
||||
else {
|
||||
if (cp->exp_flags & DICT_CACHE_FLAG_EXP_VERBOSE)
|
||||
msg_info("done %s cache cleanup scan", cp->db->name);
|
||||
dict_cache_clean_stat_log_reset(cp, "full");
|
||||
stamp_buf = vstring_alloc(100);
|
||||
vstring_sprintf(stamp_buf, "%ld", (long) event_time());
|
||||
dict_put(cp->db, DC_LAST_CACHE_CLEANUP_COMPLETED,
|
||||
vstring_str(stamp_buf));
|
||||
vstring_free(stamp_buf);
|
||||
next_interval = cp->exp_interval;
|
||||
}
|
||||
event_request_timer(dict_cache_expire_event, cache_context, next_interval);
|
||||
}
|
||||
|
||||
/* dict_cache_expire - schedule or stop the cache cleanup thread */
|
||||
|
||||
void dict_cache_expire(DICT_CACHE *cp, int flags, int interval,
|
||||
DICT_CACHE_VALIDATOR_FN validator,
|
||||
char *context)
|
||||
{
|
||||
const char *myname = "dict_cache_expire";
|
||||
const char *last_done;
|
||||
time_t next_interval;
|
||||
|
||||
/*
|
||||
* Schedule the cache cleanup thread.
|
||||
*/
|
||||
if (validator != 0) {
|
||||
|
||||
/*
|
||||
* Sanity checks.
|
||||
*/
|
||||
if (cp->exp_validator != 0)
|
||||
msg_panic("%s: %s cache cleanup is already scheduled",
|
||||
myname, cp->db->name);
|
||||
if (interval <= 0)
|
||||
msg_panic("%s: bad %s cache cleanup interval %d",
|
||||
myname, cp->db->name, interval);
|
||||
cp->exp_flags = flags;
|
||||
cp->exp_interval = interval;
|
||||
cp->exp_validator = validator;
|
||||
cp->exp_context = context;
|
||||
|
||||
/*
|
||||
* The next start time depends on the last completion time.
|
||||
*/
|
||||
#define NEXT_START(last, delta) ((delta) + (unsigned long) atol(last))
|
||||
#define NOW (time((time_t *) 0)) /* NOT: event_time() */
|
||||
|
||||
if ((last_done = dict_get(cp->db, DC_LAST_CACHE_CLEANUP_COMPLETED)) == 0
|
||||
|| (next_interval = (NEXT_START(last_done, interval) - NOW)) < 0)
|
||||
next_interval = 0;
|
||||
if (next_interval > interval)
|
||||
next_interval = interval;
|
||||
if ((cp->exp_flags & DICT_CACHE_FLAG_EXP_VERBOSE) && next_interval > 0)
|
||||
msg_info("%s cache cleanup will start after %ds",
|
||||
cp->db->name, (int) next_interval);
|
||||
event_request_timer(dict_cache_expire_event, (char *) cp,
|
||||
(int) next_interval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cancel the cache cleanup thread.
|
||||
*/
|
||||
else if (cp->exp_validator) {
|
||||
if (cp->retained || cp->dropped)
|
||||
dict_cache_clean_stat_log_reset(cp, "partial");
|
||||
dict_cache_delete_behind_reset(cp);
|
||||
cp->exp_interval = 0;
|
||||
cp->exp_validator = 0;
|
||||
cp->exp_context = 0;
|
||||
event_cancel_timer(dict_cache_expire_event, (char *) cp);
|
||||
}
|
||||
}
|
||||
|
||||
/* dict_cache_open - open cache file */
|
||||
|
||||
DICT_CACHE *dict_cache_open(const char *dbname, int open_flags, int dict_flags)
|
||||
{
|
||||
DICT *dict;
|
||||
|
||||
/*
|
||||
* Open the database as requested. Don't attempt to second-guess the
|
||||
* application.
|
||||
*/
|
||||
dict = dict_open(dbname, open_flags, dict_flags);
|
||||
return (dict_cache_import(dict));
|
||||
}
|
||||
|
||||
/* dict_cache_import - encapsulate pre-opened database */
|
||||
|
||||
DICT_CACHE *dict_cache_import(DICT *dict)
|
||||
{
|
||||
DICT_CACHE *cp;
|
||||
|
||||
/*
|
||||
* Create the DICT_CACHE object.
|
||||
*/
|
||||
cp = (DICT_CACHE *) mymalloc(sizeof(*cp));
|
||||
cp->flags = 0;
|
||||
cp->db = dict;
|
||||
cp->saved_curr_key = 0;
|
||||
cp->saved_curr_val = 0;
|
||||
cp->exp_interval = 0;
|
||||
cp->exp_validator = 0;
|
||||
cp->exp_context = 0;
|
||||
cp->retained = 0;
|
||||
cp->dropped = 0;
|
||||
|
||||
return (cp);
|
||||
}
|
||||
|
||||
/* dict_cache_close - close cache file */
|
||||
|
||||
void dict_cache_close(DICT_CACHE *cp)
|
||||
{
|
||||
|
||||
/*
|
||||
* Destroy the DICT_CACHE object.
|
||||
*/
|
||||
if (cp->exp_validator)
|
||||
dict_cache_expire(cp, 0, 0, (DICT_CACHE_VALIDATOR_FN) 0, (char *) 0);
|
||||
dict_close(cp->db);
|
||||
if (cp->saved_curr_key)
|
||||
myfree(cp->saved_curr_key);
|
||||
if (cp->saved_curr_val)
|
||||
myfree(cp->saved_curr_val);
|
||||
myfree((char *) cp);
|
||||
}
|
||||
|
||||
/* dict_cache_name - get the cache name */
|
||||
|
||||
const char *dict_cache_name(DICT_CACHE *cp)
|
||||
{
|
||||
|
||||
/*
|
||||
* This is used for verbose logging or warning messages, so the cost of
|
||||
* call is only made where needed (well sort off - code that does not
|
||||
* execute still presents overhead for the processor pipeline, processor
|
||||
* cache, etc).
|
||||
*/
|
||||
return (cp->db->name);
|
||||
}
|
49
postfix/src/util/dict_cache.h
Normal file
49
postfix/src/util/dict_cache.h
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef _DICT_CACHE_H_INCLUDED_
|
||||
#define _DICT_CACHE_H_INCLUDED_
|
||||
|
||||
/*++
|
||||
/* NAME
|
||||
/* dict_cache 3h
|
||||
/* SUMMARY
|
||||
/* External cache manager
|
||||
/* SYNOPSIS
|
||||
/* #include <dict_cache.h>
|
||||
/* DESCRIPTION
|
||||
/* .nf
|
||||
|
||||
/*
|
||||
* Utility library.
|
||||
*/
|
||||
#include <dict.h>
|
||||
|
||||
/*
|
||||
* External interface.
|
||||
*/
|
||||
typedef struct DICT_CACHE DICT_CACHE;
|
||||
typedef int (*DICT_CACHE_VALIDATOR_FN) (const char *, const char *, char *);
|
||||
|
||||
extern DICT_CACHE *dict_cache_open(const char *, int, int);
|
||||
extern void dict_cache_close(DICT_CACHE *);
|
||||
extern const char *dict_cache_lookup(DICT_CACHE *, const char *);
|
||||
extern void dict_cache_update(DICT_CACHE *, const char *, const char *);
|
||||
extern int dict_cache_delete(DICT_CACHE *, const char *);
|
||||
extern int dict_cache_sequence(DICT_CACHE *, int, const char **, const char **);
|
||||
extern void dict_cache_expire(DICT_CACHE *, int, int, DICT_CACHE_VALIDATOR_FN, char *);
|
||||
extern const char *dict_cache_name(DICT_CACHE *);
|
||||
extern DICT_CACHE *dict_cache_import(DICT *);
|
||||
|
||||
#define DICT_CACHE_FLAG_EXP_VERBOSE (1<<0)
|
||||
#define DICT_CACHE_FLAG_EXP_SUMMARY (1<<1)
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
#endif
|
@ -310,6 +310,7 @@ static int dict_dbm_sequence(DICT *dict, int function,
|
||||
DICT_DBM *dict_dbm = (DICT_DBM *) dict;
|
||||
datum dbm_key;
|
||||
datum dbm_value;
|
||||
int status;
|
||||
|
||||
/*
|
||||
* Acquire a shared lock.
|
||||
@ -350,6 +351,7 @@ static int dict_dbm_sequence(DICT *dict, int function,
|
||||
* Copy the value so that it is guaranteed null terminated.
|
||||
*/
|
||||
*value = SCOPY(dict_dbm->val_buf, dbm_value.dptr, dbm_value.dsize);
|
||||
status = 0;
|
||||
} else {
|
||||
|
||||
/*
|
||||
@ -358,7 +360,7 @@ static int dict_dbm_sequence(DICT *dict, int function,
|
||||
*/
|
||||
if (dbm_error(dict_dbm->dbm))
|
||||
msg_fatal("error seeking %s: %m", dict_dbm->dict.name);
|
||||
return (1); /* no error: eof/not found
|
||||
status = 1; /* no error: eof/not found
|
||||
* (should not happen!) */
|
||||
}
|
||||
} else {
|
||||
@ -368,7 +370,7 @@ static int dict_dbm_sequence(DICT *dict, int function,
|
||||
*/
|
||||
if (dbm_error(dict_dbm->dbm))
|
||||
msg_fatal("error seeking %s: %m", dict_dbm->dict.name);
|
||||
return (1); /* no error: eof/not found */
|
||||
status = 1; /* no error: eof/not found */
|
||||
}
|
||||
|
||||
/*
|
||||
@ -378,7 +380,7 @@ static int dict_dbm_sequence(DICT *dict, int function,
|
||||
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
|
||||
msg_fatal("%s: unlock dictionary: %m", dict_dbm->dict.name);
|
||||
|
||||
return (0);
|
||||
return (status);
|
||||
}
|
||||
|
||||
/* dict_dbm_close - disassociate from data base */
|
||||
|
@ -75,6 +75,29 @@ static void dict_ht_update(DICT *dict, const char *name, const char *value)
|
||||
ht->value = mystrdup(value);
|
||||
}
|
||||
|
||||
/* dict_ht_sequence - first/next iterator */
|
||||
|
||||
static int dict_ht_sequence(DICT *dict, int how, const char **name,
|
||||
const char **value)
|
||||
{
|
||||
DICT_HT *dict_ht = (DICT_HT *) dict;
|
||||
HTABLE_INFO *ht;
|
||||
|
||||
ht = htable_sequence(dict_ht->table,
|
||||
how == DICT_SEQ_FUN_FIRST ? HTABLE_SEQ_FIRST :
|
||||
how == DICT_SEQ_FUN_NEXT ? HTABLE_SEQ_NEXT :
|
||||
HTABLE_SEQ_STOP);
|
||||
if (ht != 0) {
|
||||
*name = ht->key;
|
||||
*value = ht->value;
|
||||
return (0);
|
||||
} else {
|
||||
*name = 0;
|
||||
*value = 0;
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
/* dict_ht_close - disassociate from hash table */
|
||||
|
||||
static void dict_ht_close(DICT *dict)
|
||||
@ -95,6 +118,7 @@ DICT *dict_ht_open(const char *name, HTABLE *table, void (*remove) (char *))
|
||||
dict_ht = (DICT_HT *) dict_alloc(DICT_TYPE_HT, name, sizeof(*dict_ht));
|
||||
dict_ht->dict.lookup = dict_ht_lookup;
|
||||
dict_ht->dict.update = dict_ht_update;
|
||||
dict_ht->dict.sequence = dict_ht_sequence;
|
||||
dict_ht->dict.close = dict_ht_close;
|
||||
dict_ht->table = table;
|
||||
dict_ht->remove = remove;
|
||||
|
@ -144,13 +144,13 @@
|
||||
/* dict_put() stores the specified key and value into the named
|
||||
/* dictionary.
|
||||
/*
|
||||
/* dict_del() removes a dictionary entry, and returns non-zero
|
||||
/* dict_del() removes a dictionary entry, and returns zero
|
||||
/* in case of success.
|
||||
/*
|
||||
/* dict_seq() iterates over all members in the named dictionary.
|
||||
/* func is define DICT_SEQ_FUN_FIRST (select first member) or
|
||||
/* DICT_SEQ_FUN_NEXT (select next member). A null result means
|
||||
/* there is more.
|
||||
/* DICT_SEQ_FUN_NEXT (select next member). A zero result means
|
||||
/* that an entry was found.
|
||||
/*
|
||||
/* dict_close() closes the specified dictionary and cleans up the
|
||||
/* associated data structures.
|
||||
|
@ -496,6 +496,11 @@ typedef struct epoll_event EVENT_BUFFER;
|
||||
/*
|
||||
* Timer events. Timer requests are kept sorted, in a circular list. We use
|
||||
* the RING abstraction, so we get to use a couple ugly macros.
|
||||
*
|
||||
* When a call-back function adds a timer request, we label the request with
|
||||
* the event_loop() call instance that invoked the call-back. We use this to
|
||||
* prevent zero-delay timer requests from running in a tight loop and
|
||||
* starving I/O events.
|
||||
*/
|
||||
typedef struct EVENT_TIMER EVENT_TIMER;
|
||||
|
||||
@ -503,10 +508,12 @@ struct EVENT_TIMER {
|
||||
time_t when; /* when event is wanted */
|
||||
EVENT_NOTIFY_TIME callback; /* callback function */
|
||||
char *context; /* callback context */
|
||||
long loop_instance; /* event_loop() call instance */
|
||||
RING ring; /* linkage */
|
||||
};
|
||||
|
||||
static RING event_timer_head; /* timer queue head */
|
||||
static long event_loop_instance; /* event_loop() call instance */
|
||||
|
||||
#define RING_TO_TIMER(r) \
|
||||
((EVENT_TIMER *) ((char *) (r) - offsetof(EVENT_TIMER, ring)))
|
||||
@ -921,18 +928,24 @@ time_t event_request_timer(EVENT_NOTIFY_TIME callback, char *context, int delay
|
||||
timer->when = event_present + delay;
|
||||
timer->callback = callback;
|
||||
timer->context = context;
|
||||
timer->loop_instance = event_loop_instance;
|
||||
if (msg_verbose > 2)
|
||||
msg_info("%s: set 0x%lx 0x%lx %d", myname,
|
||||
(long) callback, (long) context, delay);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert the request at the right place. Timer requests are kept sorted
|
||||
* to reduce lookup overhead in the event loop.
|
||||
* Timer requests are kept sorted to reduce lookup overhead in the event
|
||||
* loop.
|
||||
*
|
||||
* XXX Append the new request after existing requests for the same time
|
||||
* slot. The event_loop() routine depends on this to avoid starving I/O
|
||||
* events when a call-back function schedules a zero-delay timer request.
|
||||
*/
|
||||
FOREACH_QUEUE_ENTRY(ring, &event_timer_head)
|
||||
FOREACH_QUEUE_ENTRY(ring, &event_timer_head) {
|
||||
if (timer->when < RING_TO_TIMER(ring)->when)
|
||||
break;
|
||||
break;
|
||||
}
|
||||
ring_prepend(ring, &timer->ring);
|
||||
|
||||
return (timer->when);
|
||||
@ -1079,17 +1092,35 @@ void event_loop(int delay)
|
||||
msg_panic("event_loop: recursive call");
|
||||
|
||||
/*
|
||||
* Deliver timer events. Requests are sorted: we can stop when we reach
|
||||
* the future or the list end. Allow the application to update the timer
|
||||
* queue while it is being called back. To this end, we repeatedly pop
|
||||
* the first request off the timer queue before delivering the event to
|
||||
* the application.
|
||||
* Deliver timer events. Allow the application to add/delete timer queue
|
||||
* requests while it is being called back. Requests are sorted: we keep
|
||||
* running over the timer request queue from the start, and stop when we
|
||||
* reach the future or the list end. We also stop when we reach a timer
|
||||
* request that was added by a call-back that was invoked from this
|
||||
* event_loop() call instance, for reasons that are explained below.
|
||||
*
|
||||
* To avoid dangling pointer problems 1) we must remove a request from the
|
||||
* timer queue before delivering its event to the application and 2) we
|
||||
* must look up the next timer request *after* calling the application.
|
||||
* The latter complicates the handling of zero-delay timer requests that
|
||||
* are added by event_loop() call-back functions.
|
||||
*
|
||||
* XXX When a timer event call-back function adds a new timer request,
|
||||
* event_request_timer() labels the request with the event_loop() call
|
||||
* instance that invoked the timer event call-back. We use this instance
|
||||
* label here to prevent zero-delay timer requests from running in a
|
||||
* tight loop and starving I/O events. To make this solution work,
|
||||
* event_request_timer() appends a new request after existing requests
|
||||
* for the same time slot.
|
||||
*/
|
||||
event_present = time((time_t *) 0);
|
||||
event_loop_instance += 1;
|
||||
|
||||
while ((timer = FIRST_TIMER(&event_timer_head)) != 0) {
|
||||
if (timer->when > event_present)
|
||||
break;
|
||||
if (timer->loop_instance == event_loop_instance)
|
||||
break;
|
||||
ring_detach(&timer->ring); /* first this */
|
||||
if (msg_verbose > 2)
|
||||
msg_info("%s: timer 0x%lx 0x%lx", myname,
|
||||
@ -1192,10 +1223,10 @@ static void echo(int unused_event, char *unused_context)
|
||||
printf("Result: %s", buf);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
/* request - request a bunch of timer events */
|
||||
|
||||
static void request(int unused_event, char *unused_context)
|
||||
{
|
||||
if (argv[1])
|
||||
msg_verbose = atoi(argv[1]);
|
||||
event_request_timer(timer_event, "3 first", 3);
|
||||
event_request_timer(timer_event, "3 second", 3);
|
||||
event_request_timer(timer_event, "4 first", 4);
|
||||
@ -1206,6 +1237,13 @@ int main(int argc, char **argv)
|
||||
event_request_timer(timer_event, "1 second", 1);
|
||||
event_request_timer(timer_event, "0 first", 0);
|
||||
event_request_timer(timer_event, "0 second", 0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argv[1])
|
||||
msg_verbose = atoi(argv[1]);
|
||||
event_request_timer(request, (char *) 0, 0);
|
||||
event_enable_read(fileno(stdin), echo, (char *) 0);
|
||||
event_drain(10);
|
||||
exit(0);
|
||||
|
@ -46,6 +46,10 @@
|
||||
/*
|
||||
/* HTABLE_INFO **htable_list(table)
|
||||
/* HTABLE *table;
|
||||
/*
|
||||
/* HTABLE_INFO *htable_sequence(table, how)
|
||||
/* HTABLE *table;
|
||||
/* int how;
|
||||
/* DESCRIPTION
|
||||
/* This module maintains one or more hash tables. Each table entry
|
||||
/* consists of a unique string-valued lookup key and a generic
|
||||
@ -85,6 +89,12 @@
|
||||
/* htable_list() returns a null-terminated list of pointers to
|
||||
/* all elements in the named table. The list should be passed to
|
||||
/* myfree().
|
||||
/*
|
||||
/* htable_sequence() returns the first or next element depending
|
||||
/* on the value of the "how" argument. Specify HTABLE_SEQ_FIRST
|
||||
/* to start a new sequence, HTABLE_SEQ_NEXT to continue, and
|
||||
/* HTABLE_SEQ_STOP to terminate a sequence early. The caller
|
||||
/* must not delete the current element.
|
||||
/* RESTRICTIONS
|
||||
/* A callback function should not modify the hash table that is
|
||||
/* specified to its caller.
|
||||
@ -172,6 +182,7 @@ HTABLE *htable_create(int size)
|
||||
|
||||
table = (HTABLE *) mymalloc(sizeof(HTABLE));
|
||||
htable_size(table, size < 13 ? 13 : size);
|
||||
table->seq_element = 0;
|
||||
return (table);
|
||||
}
|
||||
|
||||
@ -202,7 +213,7 @@ HTABLE_INFO *htable_enter(HTABLE *table, const char *key, char *value)
|
||||
{
|
||||
HTABLE_INFO *ht;
|
||||
|
||||
if (table->used >= table->size)
|
||||
if (table->used >= table->size && table->seq_element == 0)
|
||||
htable_grow(table);
|
||||
ht = (HTABLE_INFO *) mymalloc(sizeof(HTABLE_INFO));
|
||||
ht->key = mystrdup(key);
|
||||
@ -332,6 +343,34 @@ HTABLE_INFO **htable_list(HTABLE *table)
|
||||
return (list);
|
||||
}
|
||||
|
||||
/* htable_sequence - dict_cache(3) compatibility iterator */
|
||||
|
||||
HTABLE_INFO *htable_sequence(HTABLE *table, int how)
|
||||
{
|
||||
if (table == 0)
|
||||
return (0);
|
||||
|
||||
switch (how) {
|
||||
case HTABLE_SEQ_FIRST: /* start new sequence */
|
||||
table->seq_bucket = table->data;
|
||||
table->seq_element = table->seq_bucket[0];
|
||||
break;
|
||||
case HTABLE_SEQ_NEXT: /* next element */
|
||||
if (table->seq_element) {
|
||||
table->seq_element = table->seq_element->next;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
default: /* terminate sequence */
|
||||
return (table->seq_element = 0);
|
||||
}
|
||||
|
||||
while (table->seq_element == 0
|
||||
&& ++(table->seq_bucket) < table->data + table->size)
|
||||
table->seq_element = table->seq_bucket[0];
|
||||
return (table->seq_element);
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
#include <vstring_vstream.h>
|
||||
#include <myrand.h>
|
||||
@ -346,6 +385,7 @@ int main(int unused_argc, char **unused_argv)
|
||||
HTABLE_INFO *info;
|
||||
int i;
|
||||
int r;
|
||||
int op;
|
||||
|
||||
/*
|
||||
* Load a large number of strings and delete them in a random order.
|
||||
@ -353,6 +393,11 @@ int main(int unused_argc, char **unused_argv)
|
||||
hash = htable_create(10);
|
||||
while (vstring_get(buf, VSTREAM_IN) != VSTREAM_EOF)
|
||||
htable_enter(hash, vstring_str(buf), CAST_INT_TO_CHAR_PTR(count++));
|
||||
for (i = 0, op = HTABLE_SEQ_FIRST; htable_sequence(hash, op) != 0;
|
||||
i++, op = HTABLE_SEQ_NEXT)
|
||||
/* void */ ;
|
||||
if (i != hash->used)
|
||||
msg_panic("%d entries found, but %d entries exist", i, hash->used);
|
||||
ht_info = htable_list(hash);
|
||||
for (i = 0; i < hash->used; i++) {
|
||||
r = myrand() % hash->used;
|
||||
|
@ -26,6 +26,8 @@ typedef struct HTABLE {
|
||||
int size; /* length of entries array */
|
||||
int used; /* number of entries in table */
|
||||
HTABLE_INFO **data; /* entries array, auto-resized */
|
||||
HTABLE_INFO **seq_bucket; /* current sequence bucket */
|
||||
HTABLE_INFO *seq_element; /* current sequence element */
|
||||
} HTABLE;
|
||||
|
||||
extern HTABLE *htable_create(int);
|
||||
@ -36,6 +38,11 @@ extern void htable_delete(HTABLE *, const char *, void (*) (char *));
|
||||
extern void htable_free(HTABLE *, void (*) (char *));
|
||||
extern void htable_walk(HTABLE *, void (*) (HTABLE_INFO *, char *), char *);
|
||||
extern HTABLE_INFO **htable_list(HTABLE *);
|
||||
extern HTABLE_INFO *htable_sequence(HTABLE *, int);
|
||||
|
||||
#define HTABLE_SEQ_FIRST 0
|
||||
#define HTABLE_SEQ_NEXT 1
|
||||
#define HTABLE_SEQ_STOP (-1)
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
|
@ -63,8 +63,10 @@ verify.o: ../../include/cleanup_user.h
|
||||
verify.o: ../../include/data_redirect.h
|
||||
verify.o: ../../include/deliver_request.h
|
||||
verify.o: ../../include/dict.h
|
||||
verify.o: ../../include/dict_cache.h
|
||||
verify.o: ../../include/dict_ht.h
|
||||
verify.o: ../../include/dsn.h
|
||||
verify.o: ../../include/events.h
|
||||
verify.o: ../../include/htable.h
|
||||
verify.o: ../../include/int_filt.h
|
||||
verify.o: ../../include/iostuff.h
|
||||
|
@ -97,6 +97,10 @@
|
||||
/* .IP "\fBaddress_verify_negative_refresh_time (3h)\fR"
|
||||
/* The time after which a failed address verification probe needs to
|
||||
/* be refreshed.
|
||||
/* .PP
|
||||
/* Available with Postfix 2.7 and later:
|
||||
/* .IP "\fBaddress_verify_cache_cleanup_interval (12h)\fR"
|
||||
/* The amount of time between \fBverify\fR(8) cache cleanup runs.
|
||||
/* PROBE MESSAGE ROUTING CONTROLS
|
||||
/* .ad
|
||||
/* .fi
|
||||
@ -121,6 +125,16 @@
|
||||
/* .IP "\fBaddress_verify_default_transport ($default_transport)\fR"
|
||||
/* Overrides the default_transport parameter setting for address
|
||||
/* verification probes.
|
||||
/* .PP
|
||||
/* Available in Postfix 2.3 and later:
|
||||
/* .IP "\fBaddress_verify_sender_dependent_relayhost_maps ($sender_dependent_relayhost_maps)\fR"
|
||||
/* Overrides the sender_dependent_relayhost_maps parameter setting for address
|
||||
/* verification probes.
|
||||
/* .PP
|
||||
/* Available in Postfix 2.7 and later:
|
||||
/* .IP "\fBaddress_verify_sender_dependent_default_transport_maps ($sender_dependent_default_transport_maps)\fR"
|
||||
/* Overrides the sender_dependent_default_transport_maps parameter
|
||||
/* setting for address verification probes.
|
||||
/* MISCELLANEOUS CONTROLS
|
||||
/* .ad
|
||||
/* .fi
|
||||
@ -187,10 +201,11 @@
|
||||
#include <mymalloc.h>
|
||||
#include <htable.h>
|
||||
#include <dict_ht.h>
|
||||
#include <dict.h>
|
||||
#include <dict_cache.h>
|
||||
#include <split_at.h>
|
||||
#include <stringops.h>
|
||||
#include <set_eugid.h>
|
||||
#include <events.h>
|
||||
|
||||
/* Global library. */
|
||||
|
||||
@ -216,12 +231,13 @@ int var_verify_pos_exp;
|
||||
int var_verify_pos_try;
|
||||
int var_verify_neg_exp;
|
||||
int var_verify_neg_try;
|
||||
int var_verify_scan_cache;
|
||||
char *var_verify_sender;
|
||||
|
||||
/*
|
||||
* State.
|
||||
*/
|
||||
static DICT *verify_map;
|
||||
static DICT_CACHE *verify_map;
|
||||
|
||||
/*
|
||||
* Silly little macros.
|
||||
@ -344,7 +360,7 @@ static void verify_update_service(VSTREAM *client_stream)
|
||||
* some probes succeed the address will remain cached as OK.
|
||||
*/
|
||||
if (addr_status == DEL_RCPT_STAT_OK
|
||||
|| (raw_data = dict_get(verify_map, STR(addr))) == 0
|
||||
|| (raw_data = dict_cache_lookup(verify_map, STR(addr))) == 0
|
||||
|| STATUS_FROM_RAW_ENTRY(raw_data) != DEL_RCPT_STAT_OK) {
|
||||
probed = 0;
|
||||
updated = (long) time((time_t *) 0);
|
||||
@ -352,7 +368,7 @@ static void verify_update_service(VSTREAM *client_stream)
|
||||
if (msg_verbose)
|
||||
msg_info("PUT %s status=%d probed=%ld updated=%ld text=%s",
|
||||
STR(addr), addr_status, probed, updated, STR(text));
|
||||
dict_put(verify_map, STR(addr), STR(buf));
|
||||
dict_cache_update(verify_map, STR(addr), STR(buf));
|
||||
}
|
||||
attr_print(client_stream, ATTR_FLAG_NONE,
|
||||
ATTR_TYPE_INT, MAIL_ATTR_STATUS, VRFY_STAT_OK,
|
||||
@ -419,7 +435,7 @@ static void verify_query_service(VSTREAM *client_stream)
|
||||
|
||||
/* FIX 200501 IPv6 patch did not neuter ":" in address literals. */
|
||||
translit(STR(addr), ":", "_");
|
||||
if ((raw_data = dict_get(verify_map, STR(addr))) == 0 /* not found */
|
||||
if ((raw_data = dict_cache_lookup(verify_map, STR(addr))) == 0 /* not found */
|
||||
|| ((get_buf = vstring_alloc(10)),
|
||||
vstring_strcpy(get_buf, raw_data), /* malformed */
|
||||
verify_parse_entry(STR(get_buf), &addr_status, &probed,
|
||||
@ -432,7 +448,7 @@ static void verify_query_service(VSTREAM *client_stream)
|
||||
updated = 0;
|
||||
text = "Address verification in progress";
|
||||
if (raw_data != 0 && var_verify_neg_cache == 0)
|
||||
dict_del(verify_map, STR(addr));
|
||||
dict_cache_delete(verify_map, STR(addr));
|
||||
}
|
||||
if (msg_verbose)
|
||||
msg_info("GOT %s status=%d probed=%ld updated=%ld text=%s",
|
||||
@ -482,7 +498,7 @@ static void verify_query_service(VSTREAM *client_stream)
|
||||
if (msg_verbose)
|
||||
msg_info("PUT %s status=%d probed=%ld updated=%ld text=%s",
|
||||
STR(addr), addr_status, now, updated, text);
|
||||
dict_put(verify_map, STR(addr), STR(put_buf));
|
||||
dict_cache_update(verify_map, STR(addr), STR(put_buf));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -493,6 +509,29 @@ static void verify_query_service(VSTREAM *client_stream)
|
||||
vstring_free(put_buf);
|
||||
}
|
||||
|
||||
/* verify_cache_validator - cache cleanup validator */
|
||||
|
||||
static int verify_cache_validator(const char *addr, const char *raw_data,
|
||||
char *context)
|
||||
{
|
||||
VSTRING *get_buf = (VSTRING *) context;
|
||||
int addr_status;
|
||||
long probed;
|
||||
long updated;
|
||||
char *text;
|
||||
long now = (long) event_time();
|
||||
|
||||
#define POS_OR_NEG_ENTRY_EXPIRED(stat, stamp) \
|
||||
(POSITIVE_ENTRY_EXPIRED((stat), (stamp)) \
|
||||
|| NEGATIVE_ENTRY_EXPIRED((stat), (stamp)))
|
||||
|
||||
vstring_strcpy(get_buf, raw_data);
|
||||
return (verify_parse_entry(STR(get_buf), &addr_status, /* syntax OK */
|
||||
&probed, &updated, &text) == 0
|
||||
&& (now - probed < PROBE_TTL /* probe in progress */
|
||||
|| !POS_OR_NEG_ENTRY_EXPIRED(addr_status, updated)));
|
||||
}
|
||||
|
||||
/* verify_service - perform service for client */
|
||||
|
||||
static void verify_service(VSTREAM *client_stream, char *unused_service,
|
||||
@ -530,6 +569,21 @@ static void verify_service(VSTREAM *client_stream, char *unused_service,
|
||||
vstring_free(request);
|
||||
}
|
||||
|
||||
/* verify_dump - dump some statistics */
|
||||
|
||||
static void verify_dump(void)
|
||||
{
|
||||
|
||||
/*
|
||||
* Dump preliminary cache cleanup statistics when the process commits
|
||||
* suicide while a cache cleanup run is in progress. We can't currently
|
||||
* distinguish between "postfix reload" (we should restart) or "maximal
|
||||
* idle time reached" (we could finish the cache cleanup first).
|
||||
*/
|
||||
dict_cache_close(verify_map);
|
||||
verify_map = 0;
|
||||
}
|
||||
|
||||
/* post_jail_init - post-jail initialization */
|
||||
|
||||
static void post_jail_init(char *unused_name, char **unused_argv)
|
||||
@ -544,6 +598,20 @@ static void post_jail_init(char *unused_name, char **unused_argv)
|
||||
var_use_limit = 0;
|
||||
var_idle_limit = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the cache cleanup thread.
|
||||
*/
|
||||
if (var_verify_scan_cache > 0) {
|
||||
int expire_flags;
|
||||
|
||||
expire_flags = DICT_CACHE_FLAG_EXP_SUMMARY;
|
||||
if (msg_verbose)
|
||||
expire_flags |= DICT_CACHE_FLAG_EXP_VERBOSE;
|
||||
dict_cache_expire(verify_map, expire_flags, var_verify_scan_cache,
|
||||
verify_cache_validator,
|
||||
(char *) vstring_alloc(100));
|
||||
}
|
||||
}
|
||||
|
||||
/* pre_jail_init - pre-jail initialization */
|
||||
@ -585,17 +653,20 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
|
||||
|
||||
/*
|
||||
* Keep state in persistent (external) or volatile (internal) map.
|
||||
*
|
||||
* Start the cache cleanup thread after permanently dropping privileges.
|
||||
*/
|
||||
#define VERIFY_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE)
|
||||
|
||||
if (*var_verify_map) {
|
||||
saved_mask = umask(022);
|
||||
verify_map = dict_open(data_redirect_map(redirect, var_verify_map),
|
||||
O_CREAT | O_RDWR,
|
||||
VERIFY_DICT_OPEN_FLAGS);
|
||||
verify_map =
|
||||
dict_cache_open(data_redirect_map(redirect, var_verify_map),
|
||||
O_CREAT | O_RDWR, VERIFY_DICT_OPEN_FLAGS);
|
||||
(void) umask(saved_mask);
|
||||
} else {
|
||||
verify_map = dict_ht_open("verify", htable_create(0), myfree);
|
||||
verify_map =
|
||||
dict_cache_import(dict_ht_open("verify", htable_create(0), myfree));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -621,6 +692,7 @@ int main(int argc, char **argv)
|
||||
VAR_VERIFY_POS_TRY, DEF_VERIFY_POS_TRY, &var_verify_pos_try, 1, 0,
|
||||
VAR_VERIFY_NEG_EXP, DEF_VERIFY_NEG_EXP, &var_verify_neg_exp, 1, 0,
|
||||
VAR_VERIFY_NEG_TRY, DEF_VERIFY_NEG_TRY, &var_verify_neg_try, 1, 0,
|
||||
VAR_VERIFY_SCAN_CACHE, DEF_VERIFY_SCAN_CACHE, &var_verify_scan_cache, 0, 0,
|
||||
0,
|
||||
};
|
||||
|
||||
@ -635,5 +707,6 @@ int main(int argc, char **argv)
|
||||
MAIL_SERVER_PRE_INIT, pre_jail_init,
|
||||
MAIL_SERVER_POST_INIT, post_jail_init,
|
||||
MAIL_SERVER_SOLITARY,
|
||||
MAIL_SERVER_EXIT, verify_dump,
|
||||
0);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user