2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-22 18:07:41 +00:00

postfix-2.11-20131120

This commit is contained in:
Wietse Venema 2013-11-20 00:00:00 -05:00 committed by Viktor Dukhovni
parent f5ad0386b9
commit 4e73c4a049
22 changed files with 451 additions and 218 deletions

View File

@ -19168,18 +19168,44 @@ Apologies for any names omitted.
20131119
Bugfix (introduced: 20111211): the Postfix memcache client
did not propagate a persistent "open()" lock to the optional
backup database. File: global/dict_memcache.c.
Feature: a Postfix LMDB database can now be used as shared
cache. Until now only the Postfix memcache database could
be used in this manner. This is implemented by allowing a
database to downgrade the permanent DICT_FLAG_OPEN_LOCK
method to the temporary DICT_FLAG_LOCK method. Files:
util/dict.h, util/dict_alloc.c, util/dict_open.c,
util/dict_lmdb.c.
persistent cache with multiple postscreen(8) or verify(8)
daemons (but not both), without the need for a shared
proxymap server. Files: util/dict.h, util/dict_alloc.c,
util/dict_open.c, util/dict_lmdb.c.
Internal: DNS client support to report reply RCODE information,
in addition to the simplified DNS_NOTFOUND, DNS_RETRY etc.
Portability note: this requires the C99 __VA_ARGS__ feature.
Files: dns/dns.h. dns/dns_lookup.c, dns/test_dns_lookup.c.
20131120
Cleanup: reduced the code footprint for the LMDB < 0.9.10
heap-to-file information leak workaround, and simplified
the implementation to "good enough". Files: util/dict.h,
util/dict.c, util/dict_lmdb.c, postalias/postalias.c,
postmap/postmap.c.
Cleanup: reduced the code footprint for the handling of
multi-writer safe maps. A map only needs to assert that it
is multi-writer safe, and the rest just happens. Files:
util/dict.h, util/dict_open.c, util/dict_lmdb.c,
global/dict_memcache.c.
Cleanup: Postfix daemons no longer restart when a multi-writer
safe map is updated. File: util/dict.c.
Documentation: sharing an LMDB cache between multiple
verify(8) or postscreen(8) servers (but not both). Files:
proto/ADDRESS_VERIFICATION_README.html,
proto/POSTSCREEN_README.html.
Cleanup: improve suppression of TLSA lookups in insecure
zones. This is now applied not only to non-MX destinations,
but also to each MX record. Viktor Dukhovni. Files:
src/posttls-finger/posttls-finger.c, src/smtp/smtp_tls_policy.c,
src/tls/tls.h, src/tls/tls_dane.c.
Workaround: increased the 5s connection timeout to 30s.
Viktor Dukhovni. File: posttls-finger/posttls-finger.c.

View File

@ -292,23 +292,35 @@ parameter specifies persistent storage for sender or recipient address
verification results. If you specify an empty value, all address verification
results are lost after "postfix reload" or "postfix stop".
# Example 1: Default setting for Postfix 2.7 and later.
# Note: avoid hash files here. Use btree instead.
/etc/postfix/main.cf:
# Default setting for Postfix 2.7 and later.
# Note: avoid hash files here. Use btree instead.
address_verify_map = btree:$data_directory/verify_cache
# Shared persistent cache (requires Postfix 2.9 or later).
address_verify_map = proxy:btree:$data_directory/verify_cache
# Disable automatic cache cleanup in all Postfix instances except
# for one instance that will be responsible for cache cleanup.
# Example 2: Shared persistent lmdb: cache (Postfix 2.11 or later).
# Disable automatic cache cleanup in all Postfix instances except
# for one instance that will be responsible for cache cleanup.
/etc/postfix/main.cf:
address_verify_map = lmdb:$data_directory/verify_cache
# address_verify_cache_cleanup_interval = 0
# Shared memory cache (requires Postfix 2.9 or later).
# See memcache_table(5) for details.
address_verify_map = memcache:/etc/postfix/verify-memcache.cf
# Example 3: Shared persistent btree: cache (Postfix 2.9 or later).
# Disable automatic cache cleanup in all Postfix instances except
# for one instance that will be responsible for cache cleanup.
/etc/postfix/main.cf:
address_verify_map = proxy:btree:$data_directory/verify_cache
# address_verify_cache_cleanup_interval = 0
# Default setting for Postfix 2.6 and earlier.
# This uses non-persistent storage only.
# Example 4: Shared memory cache (requires Postfix 2.9 or later).
# Disable automatic cache cleanup in all Postfix instances.
# See memcache_table(5) for details.
/etc/postfix/main.cf:
address_verify_map = memcache:/etc/postfix/verify-memcache.cf
address_verify_cache_cleanup_interval = 0
# Example 5: Default setting for Postfix 2.6 and earlier.
# This uses non-persistent storage only.
/etc/postfix/main.cf:
address_verify_map =
NOTE 1: The database file should be stored under a Postfix-owned directory,

View File

@ -165,17 +165,8 @@ postscreen_cache_map parameter specifies the location of the temporary
whitelist. The temporary whitelist is not used for SMTP client addresses that
appear on the permanent access list.
NOTE: To share a postscreen(8) cache between multiple postscreen(8)
instances under the same master(8) daemon, use "postscreen_cache_map =
proxy:btree:$data_directory/postscreen_cache", and disable cache cleanup
(postscreen_cache_cleanup_interval = 0) in all postscreen(8) instances
except one that is responsible for cache cleanup.
postscreen(8) cache sharing requires Postfix 2.9 or later; earlier proxymap
(8) implementations don't support cache cleanup.
For an alternative postscreen(8) cache sharing approach, see the
memcache_table(5) manpage.
By default the temporary whitelist is not shared with other postscreen(8)
daemons. See Sharing the temporary whitelist below for alternatives.
When the SMTP client address appears on the temporary whitelist, postscreen(8)
logs this with the client address and port number as:
@ -551,6 +542,7 @@ systems.
* postscreen(8) TLS configuration
* Blocking mail with postscreen(8)
* Turning off postscreen(8)
* Sharing the temporary whitelist
TTuurrnniinngg oonn ppoossttssccrreeeenn((88)) wwiitthhoouutt bblloocckkiinngg mmaaiill
@ -754,6 +746,72 @@ processes:
6. Read the new configuration with "postfix reload".
SShhaarriinngg tthhee tteemmppoorraarryy wwhhiitteelliisstt
By default, the temporary whitelist is not shared between multiple postscreen
(8) daemons. To enable sharing, choose one of the following options:
* A non-persistent memcache: temporary whitelist can be shared between
postscreen(8) daemons on the same host or different hosts. Disable cache
cleanup (postscreen_cache_cleanup_interval = 0) in all postscreen(8)
daemons because memcache: does not implement this (but see example 4 below
for memcache: with persistent backup). This requires Postfix 2.9 or later.
# Example 1: non-persistent memcache: whitelist.
/etc/postfix/main.cf:
postscreen_cache_map = memcache:/etc/postfix/postscreen_cache
postscreen_cache_cleanup_interval = 0
/etc/postfix/postscreen_cache:
memcache = inet:127.0.0.1:11211
key_format = postscreen:%s
* A persistent lmdb: temporary whitelist can be shared between postscreen(8)
daemons that run under the same master(8) daemon, or under different master
(8) daemons on the same host. Disable cache cleanup
(postscreen_cache_cleanup_interval = 0) in all postscreen(8) daemons except
one that is responsible for cache cleanup. This requires Postfix 2.11 or
later.
# Example 2: persistent lmdb: whitelist.
/etc/postfix/main.cf:
postscreen_cache_map = lmdb:$data_directory/postscreen_cache
# See note 1 below.
# postscreen_cache_cleanup_interval = 0
* Other kinds of persistent temporary whitelist can be shared only between
postscreen(8) daemons that run under the same master(8) daemon. In this
case, temporary whitelist access must be shared through the proxymap(8)
daemon. This requires Postfix 2.9 or later.
# Example 3: proxied btree: whitelist.
/etc/postfix/main.cf:
postscreen_cache_map =
proxy:btree:/var/lib/postfix/postscreen_cache
# See note 1 below.
# postscreen_cache_cleanup_interval = 0
# Example 4: proxied btree: whitelist with memcache: accelerator.
/etc/postfix/main.cf:
postscreen_cache_map = memcache:/etc/postfix/postscreen_cache
proxy_write_maps =
proxy:btree:/var/lib/postfix/postscreen_cache
... other proxied tables ...
# See note 1 below.
# postscreen_cache_cleanup_interval = 0
/etc/postfix/postscreen_cache:
# Note: the $data_directory macro is not defined in this context.
memcache = inet:127.0.0.1:11211
backup = proxy:btree:/var/lib/postfix/postscreen_cache
key_format = postscreen:%s
Note 1: disable cache cleanup (postscreen_cache_cleanup_interval = 0) in
all postscreen(8) daemons except one that is responsible for cache cleanup.
Note 2: postscreen(8) cache sharing via proxymap(8) requires Postfix 2.9 or
later; earlier proxymap(8) implementations don't support cache cleanup.
HHiissttoorriiccaall nnootteess aanndd ccrreeddiittss
Many ideas in postscreen(8) were explored in earlier work by Michael Tokarev,

View File

@ -454,23 +454,35 @@ results are lost after "postfix reload" or "postfix stop". </p>
<blockquote>
<pre>
# Example 1: Default setting for Postfix 2.7 and later.
# Note: avoid hash files here. Use btree instead.
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
# Default setting for Postfix 2.7 and later.
# Note: avoid hash files here. Use btree instead.
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = btree:$<a href="postconf.5.html#data_directory">data_directory</a>/verify_cache
# Shared persistent cache (requires Postfix 2.9 or later).
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="proxymap.8.html">proxy</a>:btree:$<a href="postconf.5.html#data_directory">data_directory</a>/verify_cache
# Disable automatic cache cleanup in all Postfix instances except
# for one instance that will be responsible for cache cleanup.
# Example 2: Shared persistent <a href="LMDB_README.html">lmdb</a>: cache (Postfix 2.11 or later).
# Disable automatic cache cleanup in all Postfix instances except
# for one instance that will be responsible for cache cleanup.
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="LMDB_README.html">lmdb</a>:$<a href="postconf.5.html#data_directory">data_directory</a>/verify_cache
# <a href="postconf.5.html#address_verify_cache_cleanup_interval">address_verify_cache_cleanup_interval</a> = 0
# Shared memory cache (requires Postfix 2.9 or later).
# See <a href="memcache_table.5.html">memcache_table(5)</a> for details.
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="memcache_table.5.html">memcache</a>:/etc/postfix/verify-memcache.cf
# Example 3: Shared persistent btree: cache (Postfix 2.9 or later).
# Disable automatic cache cleanup in all Postfix instances except
# for one instance that will be responsible for cache cleanup.
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="proxymap.8.html">proxy</a>:btree:$<a href="postconf.5.html#data_directory">data_directory</a>/verify_cache
# <a href="postconf.5.html#address_verify_cache_cleanup_interval">address_verify_cache_cleanup_interval</a> = 0
# Default setting for Postfix 2.6 and earlier.
# This uses non-persistent storage only.
# Example 4: Shared memory cache (requires Postfix 2.9 or later).
# Disable automatic cache cleanup in all Postfix instances.
# See <a href="memcache_table.5.html">memcache_table(5)</a> for details.
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="memcache_table.5.html">memcache</a>:/etc/postfix/verify-memcache.cf
<a href="postconf.5.html#address_verify_cache_cleanup_interval">address_verify_cache_cleanup_interval</a> = 0
# Example 5: Default setting for Postfix 2.6 and earlier.
# This uses non-persistent storage only.
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#address_verify_map">address_verify_map</a> =
</pre>
</blockquote>

View File

@ -227,24 +227,9 @@ specifies the location of the temporary whitelist. The
temporary whitelist is not used for SMTP client addresses
that appear on the <i>permanent</i> access list. </p>
<blockquote>
<p> NOTE: To share a <a href="postscreen.8.html">postscreen(8)</a> cache between multiple
<a href="postscreen.8.html">postscreen(8)</a> instances under the same <a href="master.8.html">master(8)</a> daemon, use
"<tt><a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> =
<a href="proxymap.8.html">proxy</a>:btree:$<a href="postconf.5.html#data_directory">data_directory</a>/postscreen_cache</tt>", and disable
cache cleanup (<a href="postconf.5.html#postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a> = 0) in all
<a href="postscreen.8.html">postscreen(8)</a> instances except one that is responsible for cache
cleanup. </p>
<p> <a href="postscreen.8.html">postscreen(8)</a> cache sharing requires Postfix 2.9 or later;
earlier <a href="proxymap.8.html">proxymap(8)</a> implementations don't support cache cleanup.
</p>
<p> For an alternative <a href="postscreen.8.html">postscreen(8)</a> cache sharing approach,
see the <a href="memcache_table.5.html">memcache_table(5)</a> manpage. </p>
</blockquote>
<p> By default the temporary whitelist is not shared with other
postscreen(8) daemons. See <a href="#temp_white_sharing"> Sharing
the temporary whitelist </a> below for alternatives. </p>
<p> When the SMTP client address appears on the temporary
whitelist, <a href="postscreen.8.html">postscreen(8)</a> logs this with the client address and port
@ -775,6 +760,9 @@ mail</a>
<li> <a href="#turnoff"> Turning off postscreen(8) </a>
<li> <a href="#temp_white_sharing"> Sharing the temporary whitelist
</a>
</ul>
<h3> <a name="enable"> Turning on postscreen(8) without blocking mail</a> </h3>
@ -1057,6 +1045,87 @@ may follow. </p>
</ol>
<h3> <a name="temp_white_sharing"> Sharing the temporary whitelist </a> </h3>
<p> By default, the temporary whitelist is not shared between
multiple <a href="postscreen.8.html">postscreen(8)</a> daemons. To enable sharing, choose one
of the following options: </p>
<ul>
<li> <p> A non-persistent <a href="memcache_table.5.html">memcache</a>: temporary whitelist can be shared
between <a href="postscreen.8.html">postscreen(8)</a> daemons on the same host or different
hosts. Disable cache cleanup (<a href="postconf.5.html#postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a>
= 0) in all <a href="postscreen.8.html">postscreen(8)</a> daemons because <a href="memcache_table.5.html">memcache</a>: does not
implement this (but see example 4 below for <a href="memcache_table.5.html">memcache</a>: with
persistent backup). This requires Postfix 2.9 or later. </p>
<pre>
# Example 1: non-persistent <a href="memcache_table.5.html">memcache</a>: whitelist.
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> = <a href="memcache_table.5.html">memcache</a>:/etc/postfix/postscreen_cache
<a href="postconf.5.html#postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a> = 0
/etc/postfix/postscreen_cache:
memcache = inet:127.0.0.1:11211
key_format = postscreen:%s
</pre>
<li> <p> A persistent <a href="LMDB_README.html">lmdb</a>: temporary whitelist can be shared between
<a href="postscreen.8.html">postscreen(8)</a> daemons that run under the same <a href="master.8.html">master(8)</a> daemon,
or under different <a href="master.8.html">master(8)</a> daemons on the same host. Disable
cache cleanup (<a href="postconf.5.html#postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a> = 0) in all
<a href="postscreen.8.html">postscreen(8)</a> daemons except one that is responsible for cache
cleanup. This requires Postfix 2.11 or later. </p>
<pre>
# Example 2: persistent <a href="LMDB_README.html">lmdb</a>: whitelist.
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> = <a href="LMDB_README.html">lmdb</a>:$<a href="postconf.5.html#data_directory">data_directory</a>/postscreen_cache
# See note 1 below.
# <a href="postconf.5.html#postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a> = 0
</pre>
<li> <p> Other kinds of persistent temporary whitelist can be shared
only between <a href="postscreen.8.html">postscreen(8)</a> daemons that run under the same
<a href="master.8.html">master(8)</a> daemon. In this case, temporary whitelist access must
be shared through the <a href="proxymap.8.html">proxymap(8)</a> daemon. This requires Postfix
2.9 or later. </p>
<pre>
# Example 3: proxied btree: whitelist.
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> =
<a href="proxymap.8.html">proxy</a>:btree:/var/lib/postfix/postscreen_cache
# See note 1 below.
# <a href="postconf.5.html#postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a> = 0
# Example 4: proxied btree: whitelist with <a href="memcache_table.5.html">memcache</a>: accelerator.
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> = <a href="memcache_table.5.html">memcache</a>:/etc/postfix/postscreen_cache
<a href="postconf.5.html#proxy_write_maps">proxy_write_maps</a> =
<a href="proxymap.8.html">proxy</a>:btree:/var/lib/postfix/postscreen_cache
... other proxied tables ...
# See note 1 below.
# <a href="postconf.5.html#postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a> = 0
/etc/postfix/postscreen_cache:
# Note: the $<a href="postconf.5.html#data_directory">data_directory</a> macro is not defined in this context.
memcache = inet:127.0.0.1:11211
backup = <a href="proxymap.8.html">proxy</a>:btree:/var/lib/postfix/postscreen_cache
key_format = postscreen:%s
</pre>
<p> Note 1: disable cache cleanup (<a href="postconf.5.html#postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a>
= 0) in all <a href="postscreen.8.html">postscreen(8)</a> daemons except one that is responsible
for cache cleanup. </p>
<p> Note 2: <a href="postscreen.8.html">postscreen(8)</a> cache sharing via <a href="proxymap.8.html">proxymap(8)</a> requires Postfix
2.9 or later; earlier <a href="proxymap.8.html">proxymap(8)</a> implementations don't support
cache cleanup. </p>
</ul>
<h2> <a name="historical"> Historical notes and credits </a> </h2>
<p> Many ideas in <a href="postscreen.8.html">postscreen(8)</a> were explored in earlier work by

View File

@ -286,7 +286,7 @@ POSTTLS-FINGER(1) POSTTLS-FINGER(1)
tive ports can specified by appending "<i>:service-</i>
<i>name</i>" or ":<i>portnumber</i>" to the destination argument.
<b>-t</b> <i>timeout</i> (default: <b>5</b>)
<b>-t</b> <i>timeout</i> (default: <b>30</b>)
The TCP connection timeout to use. This is also
the timeout for reading the remote server's 220
banner.

View File

@ -226,7 +226,7 @@ Disable SMTP; that is, connect to an LMTP server. The default port for
LMTP over TCP is 24. Alternative ports can specified by appending
"\fI:servicename\fR" or ":\fIportnumber\fR" to the destination
argument.
.IP "\fB-t \fItimeout\fR (default: \fB5\fR)"
.IP "\fB-t \fItimeout\fR (default: \fB30\fR)"
The TCP connection timeout to use. This is also the timeout for
reading the remote server's 220 banner.
.IP "\fB-T \fItimeout\fR (default: \fB30\fR)"

View File

@ -454,23 +454,35 @@ results are lost after "postfix reload" or "postfix stop". </p>
<blockquote>
<pre>
# Example 1: Default setting for Postfix 2.7 and later.
# Note: avoid hash files here. Use btree instead.
/etc/postfix/main.cf:
# Default setting for Postfix 2.7 and later.
# Note: avoid hash files here. Use btree instead.
address_verify_map = btree:$data_directory/verify_cache
# Shared persistent cache (requires Postfix 2.9 or later).
address_verify_map = proxy:btree:$data_directory/verify_cache
# Disable automatic cache cleanup in all Postfix instances except
# for one instance that will be responsible for cache cleanup.
# Example 2: Shared persistent lmdb: cache (Postfix 2.11 or later).
# Disable automatic cache cleanup in all Postfix instances except
# for one instance that will be responsible for cache cleanup.
/etc/postfix/main.cf:
address_verify_map = lmdb:$data_directory/verify_cache
# address_verify_cache_cleanup_interval = 0
# Shared memory cache (requires Postfix 2.9 or later).
# See memcache_table(5) for details.
address_verify_map = memcache:/etc/postfix/verify-memcache.cf
# Example 3: Shared persistent btree: cache (Postfix 2.9 or later).
# Disable automatic cache cleanup in all Postfix instances except
# for one instance that will be responsible for cache cleanup.
/etc/postfix/main.cf:
address_verify_map = proxy:btree:$data_directory/verify_cache
# address_verify_cache_cleanup_interval = 0
# Default setting for Postfix 2.6 and earlier.
# This uses non-persistent storage only.
# Example 4: Shared memory cache (requires Postfix 2.9 or later).
# Disable automatic cache cleanup in all Postfix instances.
# See memcache_table(5) for details.
/etc/postfix/main.cf:
address_verify_map = memcache:/etc/postfix/verify-memcache.cf
address_verify_cache_cleanup_interval = 0
# Example 5: Default setting for Postfix 2.6 and earlier.
# This uses non-persistent storage only.
/etc/postfix/main.cf:
address_verify_map =
</pre>
</blockquote>

View File

@ -227,24 +227,9 @@ specifies the location of the temporary whitelist. The
temporary whitelist is not used for SMTP client addresses
that appear on the <i>permanent</i> access list. </p>
<blockquote>
<p> NOTE: To share a postscreen(8) cache between multiple
postscreen(8) instances under the same master(8) daemon, use
"<tt>postscreen_cache_map =
proxy:btree:$data_directory/postscreen_cache</tt>", and disable
cache cleanup (postscreen_cache_cleanup_interval = 0) in all
postscreen(8) instances except one that is responsible for cache
cleanup. </p>
<p> postscreen(8) cache sharing requires Postfix 2.9 or later;
earlier proxymap(8) implementations don't support cache cleanup.
</p>
<p> For an alternative postscreen(8) cache sharing approach,
see the memcache_table(5) manpage. </p>
</blockquote>
<p> By default the temporary whitelist is not shared with other
postscreen(8) daemons. See <a href="#temp_white_sharing"> Sharing
the temporary whitelist </a> below for alternatives. </p>
<p> When the SMTP client address appears on the temporary
whitelist, postscreen(8) logs this with the client address and port
@ -775,6 +760,9 @@ mail</a>
<li> <a href="#turnoff"> Turning off postscreen(8) </a>
<li> <a href="#temp_white_sharing"> Sharing the temporary whitelist
</a>
</ul>
<h3> <a name="enable"> Turning on postscreen(8) without blocking mail</a> </h3>
@ -1057,6 +1045,87 @@ may follow. </p>
</ol>
<h3> <a name="temp_white_sharing"> Sharing the temporary whitelist </a> </h3>
<p> By default, the temporary whitelist is not shared between
multiple postscreen(8) daemons. To enable sharing, choose one
of the following options: </p>
<ul>
<li> <p> A non-persistent memcache: temporary whitelist can be shared
between postscreen(8) daemons on the same host or different
hosts. Disable cache cleanup (postscreen_cache_cleanup_interval
= 0) in all postscreen(8) daemons because memcache: does not
implement this (but see example 4 below for memcache: with
persistent backup). This requires Postfix 2.9 or later. </p>
<pre>
# Example 1: non-persistent memcache: whitelist.
/etc/postfix/main.cf:
postscreen_cache_map = memcache:/etc/postfix/postscreen_cache
postscreen_cache_cleanup_interval = 0
/etc/postfix/postscreen_cache:
memcache = inet:127.0.0.1:11211
key_format = postscreen:%s
</pre>
<li> <p> A persistent lmdb: temporary whitelist can be shared between
postscreen(8) daemons that run under the same master(8) daemon,
or under different master(8) daemons on the same host. Disable
cache cleanup (postscreen_cache_cleanup_interval = 0) in all
postscreen(8) daemons except one that is responsible for cache
cleanup. This requires Postfix 2.11 or later. </p>
<pre>
# Example 2: persistent lmdb: whitelist.
/etc/postfix/main.cf:
postscreen_cache_map = lmdb:$data_directory/postscreen_cache
# See note 1 below.
# postscreen_cache_cleanup_interval = 0
</pre>
<li> <p> Other kinds of persistent temporary whitelist can be shared
only between postscreen(8) daemons that run under the same
master(8) daemon. In this case, temporary whitelist access must
be shared through the proxymap(8) daemon. This requires Postfix
2.9 or later. </p>
<pre>
# Example 3: proxied btree: whitelist.
/etc/postfix/main.cf:
postscreen_cache_map =
proxy:btree:/var/lib/postfix/postscreen_cache
# See note 1 below.
# postscreen_cache_cleanup_interval = 0
# Example 4: proxied btree: whitelist with memcache: accelerator.
/etc/postfix/main.cf:
postscreen_cache_map = memcache:/etc/postfix/postscreen_cache
proxy_write_maps =
proxy:btree:/var/lib/postfix/postscreen_cache
... other proxied tables ...
# See note 1 below.
# postscreen_cache_cleanup_interval = 0
/etc/postfix/postscreen_cache:
# Note: the $data_directory macro is not defined in this context.
memcache = inet:127.0.0.1:11211
backup = proxy:btree:/var/lib/postfix/postscreen_cache
key_format = postscreen:%s
</pre>
<p> Note 1: disable cache cleanup (postscreen_cache_cleanup_interval
= 0) in all postscreen(8) daemons except one that is responsible
for cache cleanup. </p>
<p> Note 2: postscreen(8) cache sharing via proxymap(8) requires Postfix
2.9 or later; earlier proxymap(8) implementations don't support
cache cleanup. </p>
</ul>
<h2> <a name="historical"> Historical notes and credits </a> </h2>
<p> Many ideas in postscreen(8) were explored in earlier work by

View File

@ -98,9 +98,6 @@
/* Request DNSSEC validation. This flag is silently ignored
/* when the system stub resolver API, resolver(3), does not
/* implement DNSSEC.
/* .IP
/* Pointer to storage for the reply RCODE value. This gives
/* more detailed information than DNS_FAIL, DNS_RETRY, etc.
/* .RE
/* .IP lflags
/* Multi-type request control for dns_lookup_l() and dns_lookup_v().
@ -132,6 +129,9 @@
/* name found for \fIname\fR.
/* .IP why
/* A null pointer, or storage for the reason for failure.
/* .IP rcode
/* Pointer to storage for the reply RCODE value. This gives
/* more detailed information than DNS_FAIL, DNS_RETRY, etc.
/* DIAGNOSTICS
/* dns_lookup() returns one of the following codes and sets the
/* \fIwhy\fR argument accordingly:

View File

@ -574,29 +574,10 @@ DICT *dict_memcache_open(const char *name, int open_flags, int dict_flags)
(char *) 0, 0, 0);
if (backup) {
dict_mc->backup = dict_open(backup, open_flags, dict_flags);
/* Expose backup lock and status to caller. */
dict_mc->dict.lock = dict_mc->backup->lock;
dict_mc->dict.lock_type = dict_mc->backup->lock_type;
dict_mc->dict.lock_fd = dict_mc->backup->lock_fd;
dict_mc->dict.stat_fd = dict_mc->backup->stat_fd;
myfree(backup);
} else
dict_mc->backup = 0;
/*
* Memcached is write-share safe. If the backup database is also
* write-share safe, e.g. it has downgraded its persistent lock to
* temporary, then expose that downgraded lock to the caller.
*/
if ((dict_flags & DICT_FLAG_OPEN_LOCK) != 0
&& (dict_mc->backup == 0
|| dict_mc->backup->lock_fd < 0
|| ((dict_mc->backup->flags & DICT_FLAG_OPEN_LOCK) == 0
&& (dict_mc->backup->flags & DICT_FLAG_LOCK) != 0))) {
dict_mc->dict.flags &= ~DICT_FLAG_OPEN_LOCK;
dict_mc->dict.flags |= DICT_FLAG_LOCK;
}
/*
* Parse templates and common database parameters. Maps that use
* substring keys should only be used with the full input key.
@ -611,5 +592,7 @@ DICT *dict_memcache_open(const char *name, int open_flags, int dict_flags)
else
dict_mc->dict.flags |= DICT_FLAG_FIXED;
dict_mc->dict.flags |= DICT_FLAG_MULTI_WRITER;
return (&dict_mc->dict);
}

View File

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

View File

@ -290,7 +290,6 @@ static void postalias(char *map_type, char *path_name, int postalias_flags,
if ((source_fp = vstream_fopen(path_name, O_RDONLY, 0)) == 0)
msg_fatal("open %s: %m", path_name);
}
dict_flags |= DICT_FLAG_WORLD_READ;
if (fstat(vstream_fileno(source_fp), &st) < 0)
msg_fatal("fstat %s: %m", path_name);

View File

@ -353,7 +353,6 @@ static void postmap(char *map_type, char *path_name, int postmap_flags,
if ((source_fp = vstream_fopen(path_name, O_RDONLY, 0)) == 0)
msg_fatal("open %s: %m", path_name);
}
dict_flags |= DICT_FLAG_WORLD_READ;
if (fstat(vstream_fileno(source_fp), &st) < 0)
msg_fatal("fstat %s: %m", path_name);

View File

@ -220,7 +220,7 @@
/* LMTP over TCP is 24. Alternative ports can specified by appending
/* "\fI:servicename\fR" or ":\fIportnumber\fR" to the destination
/* argument.
/* .IP "\fB-t \fItimeout\fR (default: \fB5\fR)"
/* .IP "\fB-t \fItimeout\fR (default: \fB30\fR)"
/* The TCP connection timeout to use. This is also the timeout for
/* reading the remote server's 220 banner.
/* .IP "\fB-T \fItimeout\fR (default: \fB30\fR)"
@ -358,7 +358,7 @@
*/
#include "tlsmgrmem.h"
static int conn_tmout = 5;
static int conn_tmout = 30;
static int smtp_tmout = 30;
#define HOST_FLAG_DNS (1<<0)
@ -1163,26 +1163,10 @@ static DNS_RR *host_addr(STATE *state, const char *host)
static int dane_host_level(STATE *state, DNS_RR *addr)
{
int level = state->level;
int valid;
int mxvalid;
#ifdef USE_TLS
if (level == TLS_LEV_DANE) {
/*
* Suppress TLSA lookups for non-DNSSEC + non-MX + non-CNAME hosts.
* If the host address is not DNSSEC validated, the TLSA RRset is
* safely assumed to not be in a DNSSEC Look-aside Validation child
* zone.
*/
mxvalid = state->mx == 0 || state->mx->dnssec_valid;
valid = addr->dnssec_valid;
if (!state->force_tlsa
&& !valid
&& state->mx == 0
&& strcmp(addr->qname, addr->rname) == 0)
mxvalid = 0;
if (mxvalid) {
if (state->mx == 0 || state->mx->dnssec_valid) {
if (state->log_mask & (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE))
tls_dane_verbose(1);
else
@ -1192,19 +1176,19 @@ static int dane_host_level(STATE *state, DNS_RR *addr)
if (state->ddane)
tls_dane_free(state->ddane);
/* When TLSA lookups fail, next host */
state->ddane = tls_dane_resolve(addr->qname,
valid ? addr->rname : 0,
"tcp", state->port);
/*
* When TLSA lookups fail, next host. If unusable or not found,
* fallback to "secure"
*/
state->ddane = tls_dane_resolve(state->port, "tcp", addr,
state->force_tlsa);
if (!state->ddane) {
dsb_simple(state->why, "4.7.5",
"TLSA lookup error for %s:%u",
HNAME(addr), ntohs(state->port));
return (TLS_LEV_INVALID);
}
/* If unusable or not found, same fallback to "secure" */
if (tls_dane_notfound(state->ddane)
|| tls_dane_unusable(state->ddane)) {
level = TLS_LEV_INVALID;
} else if (tls_dane_notfound(state->ddane)
|| tls_dane_unusable(state->ddane)) {
if (msg_verbose)
msg_info("no %sTLSA records found, "
"resorting to \"secure\"",

View File

@ -712,8 +712,6 @@ static int global_tls_level(void)
static void dane_init(SMTP_TLS_POLICY *tls, SMTP_ITERATOR *iter)
{
TLS_DANE *dane;
int valid;
int mxvalid;
if (!iter->port) {
msg_warn("%s: the \"dane\" security level is invalid for delivery via"
@ -764,20 +762,8 @@ static void dane_init(SMTP_TLS_POLICY *tls, SMTP_ITERATOR *iter)
* nexthop domain, or if the MX RRset is DNS validated, we can at least
* try DANE with the destination host prior to CNAME expansion, but we
* prefer CNAME expanded MX hosts if those are also secure.
*
* By default suppress TLSA lookups for non-DNSSEC + non-MX + non-CNAME
* hosts. If the host address is not DNSSEC validated, the TLSA RRset is
* safely assumed to not be in a DNSSEC Look-aside Validation child zone.
*/
mxvalid = iter->mx == 0 || iter->mx->dnssec_valid;
valid = iter->rr && iter->rr->dnssec_valid;
if (!var_smtp_tls_force_tlsa
&& !valid
&& iter->mx == 0
&& strcmp(iter->rr->qname, iter->rr->rname) == 0)
mxvalid = 0;
if (!mxvalid) {
if (iter->mx && !iter->mx->dnssec_valid) {
if (tls->level == TLS_LEV_DANE) {
tls->level = TLS_LEV_MAY;
if (msg_verbose)
@ -789,8 +775,8 @@ static void dane_init(SMTP_TLS_POLICY *tls, SMTP_ITERATOR *iter)
return;
}
/* When TLSA lookups fail, we defer the message */
if ((dane = tls_dane_resolve(iter->rr->qname, valid ? iter->rr->rname : 0,
"tcp", iter->port)) == 0) {
if ((dane = tls_dane_resolve(iter->port, "tcp", iter->rr,
var_smtp_tls_force_tlsa)) == 0) {
tls->level = TLS_LEV_INVALID;
dsb_simple(tls->why, "4.7.5", "TLSA lookup error for %s:%u",
STR(iter->host), ntohs(iter->port));

View File

@ -90,6 +90,7 @@ extern const NAME_CODE tls_level_table[];
#include <vstream.h>
#include <name_mask.h>
#include <name_code.h>
#include <dns.h>
/*
* Names of valid tlsmgr(8) session caches.
@ -173,8 +174,7 @@ extern TLS_DANE *tls_dane_alloc(int);
extern void tls_dane_split(TLS_DANE *, int, int, const char *, const char *,
const char *);
extern void tls_dane_free(TLS_DANE *);
extern TLS_DANE *tls_dane_resolve(const char *, const char *, const char *,
unsigned);
extern TLS_DANE *tls_dane_resolve(unsigned, const char *, DNS_RR *, int);
extern int tls_dane_load_trustfile(TLS_DANE *, const char *);
/*

View File

@ -41,11 +41,11 @@
/* SSL_CTX *ssl_ctx;
/* TLS_SESS_STATE *TLScontext;
/*
/* TLS_DANE *tls_dane_resolve(qname, rname, proto, port)
/* const char *qname;
/* const char *rname;
/* const char *proto;
/* TLS_DANE *tls_dane_resolve(port, proto, hostrr, forcetlsa)
/* unsigned port;
/* const char *proto;
/* DNS_RR *hostrr;
/* int forcetlsa;
/*
/* int tls_dane_unusable(dane)
/* const TLS_DANE *dane;
@ -96,7 +96,7 @@
/* anchors always override the legacy public CA PKI. Otherwise, the
/* callback MUST be cleared.
/*
/* tls_dane_resolve() maps a (qname, rname, protocol, port) tuple to a
/* tls_dane_resolve() maps a (port, protocol, hostrr) tuple to a
/* a corresponding TLS_DANE policy structure found in the DNS. The port
/* argument is in network byte order. A null pointer is returned when
/* the DNS query for the TLSA record tempfailed. In all other cases the
@ -117,14 +117,17 @@
/* .IP dane
/* Pointer to a TLS_DANE structure that lists the valid trust-anchor
/* and end-entity full-certificate and/or public-key digests.
/* .IP qname
/* FQDN of target service (original input form).
/* .IP rname
/* DNSSEC validated (cname resolved) FQDN of target service.
/* .IP proto
/* Almost certainly "tcp".
/* .IP port
/* The TCP port in network byte order.
/* .IP proto
/* Almost certainly "tcp".
/* .IP hostrr
/* DNS_RR pointer to TLSA base domain data. When dnssec_valid is false,
/* the rname (and the qname if same as rname) are insecure.
/* .IP forcetlsa
/* When true, TLSA lookups are performed even when the qname and rname
/* are insecure. This is only useful in the unlikely case that DLV is
/* used to secure the TLSA RRset in an otherwise insecure zone.
/* .IP flags
/* Only one flag is part of the public interface at this time:
/* .IP TLScontext
@ -314,7 +317,7 @@ static EVP_PKEY *gencakey(void)
#ifdef WRAP_SIGNED
EC_KEY *eckey;
EC_GROUP *group;
EC_GROUP *group = 0;
ERR_clear_error();
@ -676,14 +679,14 @@ static void parse_tlsa_rrs(TLS_DANE *dane, DNS_RR *rr)
for ( /* nop */ ; rr; rr = rr->next) {
const char *mdalg = 0;
char *digest;
int same = (strcasecmp(rr->rname, rr->qname) == 0);
int iscname = strcasecmp(rr->rname, rr->qname);
uint8_t *ip = (uint8_t *) rr->data;
X509 *x = 0; /* OpenSSL tries to re-use *x if x!=0 */
EVP_PKEY *k = 0; /* OpenSSL tries to re-use *k if k!=0 */
digest_info *di;
#define rcname(rr) (same ? "" : rr->qname)
#define rarrow(rr) (same ? "" : " -> ")
#define rcname(rr) (iscname ? rr->qname : "")
#define rarrow(rr) (iscname ? " -> " : "")
if (rr->type != T_TLSA)
msg_panic("unexpected non-TLSA RR type %u for %s%s%s", rr->type,
@ -946,6 +949,8 @@ static TLS_DANE *resolve_host(const char *host, const char *proto,
dane = (TLS_DANE *) ctable_refresh(dane_cache, STR(query_domain));
if (dane->base_domain == 0)
dane->base_domain = mystrdup(host);
/* Increment ref-count of cached entry */
++dane->refs;
return (dane);
}
@ -953,10 +958,11 @@ static TLS_DANE *resolve_host(const char *host, const char *proto,
/* tls_dane_resolve - cached map: (name, proto, port) -> TLS_DANE */
TLS_DANE *tls_dane_resolve(const char *qname, const char *rname,
const char *proto, unsigned port)
TLS_DANE *tls_dane_resolve(unsigned port, const char *proto, DNS_RR *hostrr,
int forcetlsa)
{
TLS_DANE *dane = 0;
int iscname;
#ifdef DANE_TLSA_SUPPORT
if (!tls_dane_avail())
@ -966,19 +972,32 @@ TLS_DANE *tls_dane_resolve(const char *qname, const char *rname,
dane_cache = ctable_create(CACHE_SIZE, dane_lookup, dane_free, 0);
/*
* Try the rname first, if nothing there, try the qname. Note, lookup
* errors are distinct from success with nothing found. If the rname
* lookup fails we don't try the qname. The rname may be null when only
* the qname is in a secure zone.
* By default suppress TLSA lookups for non-DNSSEC + non-CNAME hosts. If
* the host address is not DNSSEC validated, the TLSA RRset is safely
* assumed to not be in a DNSSEC Look-aside Validation child zone.
*/
if (rname)
dane = resolve_host(rname, proto, port);
if (!rname || (tls_dane_notfound(dane) && strcmp(qname, rname) != 0))
dane = resolve_host(qname, proto, port);
if (dane->flags & TLS_DANE_FLAG_ERROR)
return (0);
iscname = strcasecmp(hostrr->rname, hostrr->qname);
if (!forcetlsa && !hostrr->dnssec_valid && !iscname) {
dane = tls_dane_alloc(0);
dane->flags = TLS_DANE_FLAG_NORRS;
} else {
/*
* Try the rname first, if nothing there, try the qname. Note,
* lookup errors are distinct from success with nothing found. If
* the rname lookup fails we don't try the qname.
*/
if (hostrr->dnssec_valid)
dane = resolve_host(hostrr->rname, proto, port);
if (!dane || (iscname && tls_dane_notfound(dane)))
dane = resolve_host(hostrr->qname, proto, port);
if (dane->flags & TLS_DANE_FLAG_ERROR) {
/* We don't return this object. */
tls_dane_free(dane);
dane = 0;
}
}
++dane->refs;
#endif
return (dane);
}

View File

@ -555,7 +555,9 @@ const char *dict_changed_name(void)
msg_warn("%s: table %s: null time stamp", myname, h->key);
if (fstat(dict->stat_fd, &st) < 0)
msg_fatal("%s: fstat: %m", myname);
if (st.st_mtime != dict->mtime || st.st_nlink == 0)
if (((dict->flags & DICT_FLAG_MULTI_WRITER) == 0
&& st.st_mtime != dict->mtime)
|| st.st_nlink == 0)
status = h->key;
}
myfree((char *) ht_info_list);
@ -590,7 +592,7 @@ static const NAME_MASK dict_mask[] = {
"fold_mul", DICT_FLAG_FOLD_MUL, /* case-fold with multi-case key map */
"open_lock", DICT_FLAG_OPEN_LOCK, /* permanent lock upon open */
"bulk_update", DICT_FLAG_BULK_UPDATE, /* bulk update if supported */
"world_read", DICT_FLAG_WORLD_READ, /* assume writer != reader */
"multi_writer", DICT_FLAG_MULTI_WRITER, /* multi-writer safe */
0,
};

View File

@ -97,7 +97,7 @@ extern DICT *dict_debug(DICT *);
#define DICT_FLAG_FOLD_ANY (DICT_FLAG_FOLD_FIX | DICT_FLAG_FOLD_MUL)
#define DICT_FLAG_OPEN_LOCK (1<<16) /* perm lock if not multi-writer safe */
#define DICT_FLAG_BULK_UPDATE (1<<17) /* optimize for bulk updates */
#define DICT_FLAG_WORLD_READ (1<<18) /* assume writer != reader */
#define DICT_FLAG_MULTI_WRITER (1<<18) /* multi-writer safe map */
/* IMPORTANT: Update the dict_mask[] table when the above changes */
@ -124,7 +124,8 @@ extern DICT *dict_debug(DICT *);
*/
#define DICT_FLAG_PARANOID \
(DICT_FLAG_NO_REGSUB | DICT_FLAG_NO_PROXY | DICT_FLAG_NO_UNAUTH)
#define DICT_FLAG_IMPL_MASK (DICT_FLAG_FIXED | DICT_FLAG_PATTERN)
#define DICT_FLAG_IMPL_MASK (DICT_FLAG_FIXED | DICT_FLAG_PATTERN | \
DICT_FLAG_MULTI_WRITER)
#define DICT_FLAG_RQST_MASK (DICT_FLAG_FOLD_ANY | DICT_FLAG_LOCK | \
DICT_FLAG_DUP_REPLACE | DICT_FLAG_DUP_WARN | \
DICT_FLAG_DUP_IGNORE | DICT_FLAG_SYNC_UPDATE | \

View File

@ -591,16 +591,16 @@ DICT *dict_lmdb_open(const char *path, int open_flags, int dict_flags)
*
* As a workaround the postmap(1) and postalias(1) commands turn on
* MDB_WRITEMAP which disables the use of malloc() in LMDB. However, that
* does not address several disclosures of stack memory. Other Postfix
* databases are maintained by Postfix daemon processes, and are
* accessible only by the postfix user.
* does not address several disclosures of stack memory. We don't enable
* this workaround for Postfix databases are maintained by Postfix daemon
* processes, because those are accessible only by the postfix user.
*
* LMDB 0.9.10 by default does not write uninitialized heap memory to file
* (specify MDB_NOMEMINIT to revert that change). We use the MDB_WRITEMAP
* workaround for older LMDB versions.
*/
#ifndef MDB_NOMEMINIT
if (dict_flags & DICT_FLAG_WORLD_READ)
if (dict_flags & DICT_FLAG_BULK_UPDATE) /* XXX Good enough */
mdb_flags |= MDB_WRITEMAP;
#endif
@ -664,7 +664,9 @@ DICT *dict_lmdb_open(const char *path, int open_flags, int dict_flags)
&& st.st_mtime < time((time_t *) 0) - 100)
msg_warn("database %s is older than source file %s", mdb_path, path);
dict_lmdb->dict.flags = dict_flags | DICT_FLAG_FIXED;
#define DICT_LMDB_IMPL_FLAGS (DICT_FLAG_FIXED | DICT_FLAG_MULTI_WRITER)
dict_lmdb->dict.flags = dict_flags | DICT_LMDB_IMPL_FLAGS;
if ((dict_flags & (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL)) == 0)
dict_lmdb->dict.flags |= (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL);
if (dict_flags & DICT_FLAG_FOLD_FIX)
@ -673,12 +675,6 @@ DICT *dict_lmdb_open(const char *path, int open_flags, int dict_flags)
if (dict_flags & DICT_FLAG_BULK_UPDATE)
dict_jmp_alloc(&dict_lmdb->dict);
/* LMDB is write-share safe; downgrade a persistent lock to temporary. */
if (dict_flags & DICT_FLAG_OPEN_LOCK) {
dict_lmdb->dict.flags &= ~DICT_FLAG_OPEN_LOCK;
dict_lmdb->dict.flags |= DICT_FLAG_LOCK;
}
/*
* The following requests return an error result only if we have serious
* memory corruption problem.

View File

@ -92,13 +92,17 @@
/* before writing, and acquire a shared lock before reading.
/* Release the lock when the operation completes.
/* .IP DICT_FLAG_OPEN_LOCK
/* With databases that are not multi-writer safe, request that
/* dict_open() acquires an exclusive lock, or that it terminates
/* with a fatal run-time error.
/* The behavior of this flag depends on whether a database
/* sets the DICT_FLAG_MULTI_WRITER flag to indicate that it
/* is multi-writer safe.
/*
/* With databases that are multi-writer safe, downgrade from
/* DICT_FLAG_OPEN_LOCK (persistent lock) to DICT_FLAG_LOCK
/* (temporary lock).
/* With databases that are not multi-writer safe, dict_open()
/* acquires a persistent exclusive lock, or it terminates with
/* a fatal run-time error.
/*
/* With databases that are multi-writer safe, dict_open()
/* downgrades the DICT_FLAG_OPEN_LOCK flag (persistent lock)
/* to DICT_FLAG_LOCK (temporary lock).
/* .IP DICT_FLAG_FOLD_FIX
/* With databases whose lookup fields are fixed-case strings,
/* fold the search string to lower case before accessing the
@ -131,9 +135,6 @@
/* Enable preliminary code for bulk-mode database updates.
/* The caller must create an exception handler with dict_jmp_alloc()
/* and must trap exceptions from the database client with dict_setjmp().
/* .IP DICT_FLAG_WORLD_READ
/* Assume that the database file will be read by users other
/* than the writer.
/* .IP DICT_FLAG_DEBUG
/* Enable additional logging.
/* .PP
@ -389,13 +390,18 @@ DICT *dict_open3(const char *dict_type, const char *dict_name,
"cannot open %s:%s: %m", dict_type, dict_name));
if (msg_verbose)
msg_info("%s: %s:%s", myname, dict_type, dict_name);
/* Write-share safe maps may downgrade a persistent lock to temporary. */
/* XXX The choice between wait-for-lock or no-wait is hard-coded. */
if (dict->flags & DICT_FLAG_OPEN_LOCK) {
if (dict->flags & DICT_FLAG_LOCK)
msg_panic("%s: attempt to open %s:%s with both \"open\" lock and \"access\" lock",
myname, dict_type, dict_name);
if (dict->lock(dict, MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT) < 0)
/* Multi-writer safe map: downgrade persistent lock to temporary. */
if (dict->flags & DICT_FLAG_MULTI_WRITER) {
dict->flags &= ~DICT_FLAG_OPEN_LOCK;
dict->flags |= DICT_FLAG_LOCK;
}
/* Multi-writer unsafe map: acquire exclusive lock or bust. */
else if (dict->lock(dict, MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT) < 0)
msg_fatal("%s:%s: unable to get exclusive lock: %m",
dict_type, dict_name);
}