2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-22 09:57:34 +00:00

postfix-2.11-20131119

This commit is contained in:
Wietse Venema 2013-11-19 00:00:00 -05:00 committed by Viktor Dukhovni
parent 9de1f6a1d7
commit f5ad0386b9
38 changed files with 182 additions and 77 deletions

View File

@ -19165,3 +19165,21 @@ Apologies for any names omitted.
Cleanup: removed redundant sort operation. Viktor Dukhovni. Cleanup: removed redundant sort operation. Viktor Dukhovni.
File: tls/tls_dane.c. File: tls/tls_dane.c.
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.
Internal: DNS client support to report reply RCODE information,
in addition to the simplified DNS_NOTFOUND, DNS_RETRY etc.
Files: dns/dns.h. dns/dns_lookup.c, dns/test_dns_lookup.c.

View File

@ -10,9 +10,9 @@ LDAP_TABLE(5) LDAP_TABLE(5)
ldap_table - Postfix LDAP client configuration ldap_table - Postfix LDAP client configuration
<b>SYNOPSIS</b> <b>SYNOPSIS</b>
<b>postmap -q "<i></b>string</i><b>" <a href="ldap_table.5.html">ldap</a>:/etc/postfix/filename</b> <b>postmap -q "</b><i>string</i><b>" <a href="ldap_table.5.html">ldap</a>:/etc/postfix/</b><i>filename</i>
<b>postmap -q - <a href="ldap_table.5.html">ldap</a>:/etc/postfix/<i></b>filename</i> &lt;<i>inputfile</i> <b>postmap -q - <a href="ldap_table.5.html">ldap</a>:/etc/postfix/</b><i>filename</i> &lt;<i>inputfile</i>
<b>DESCRIPTION</b> <b>DESCRIPTION</b>
The Postfix mail system uses optional tables for address The Postfix mail system uses optional tables for address

View File

@ -10,7 +10,7 @@ MEMCACHE_TABLE(5) MEMCACHE_TABLE(5)
memcache_table - Postfix memcache client configuration memcache_table - Postfix memcache client configuration
<b>SYNOPSIS</b> <b>SYNOPSIS</b>
<b>postmap -q "</b><i>string</i><b>" <a href="memcache_table.5.html">memcache</a>:/etc/postfix/filename</b> <b>postmap -q "</b><i>string</i><b>" <a href="memcache_table.5.html">memcache</a>:/etc/postfix/</b><i>filename</i>
<b>postmap -q - <a href="memcache_table.5.html">memcache</a>:/etc/postfix/</b><i>filename</i> &lt;<i>inputfile</i> <b>postmap -q - <a href="memcache_table.5.html">memcache</a>:/etc/postfix/</b><i>filename</i> &lt;<i>inputfile</i>

View File

@ -10,7 +10,7 @@ MYSQL_TABLE(5) MYSQL_TABLE(5)
mysql_table - Postfix MySQL client configuration mysql_table - Postfix MySQL client configuration
<b>SYNOPSIS</b> <b>SYNOPSIS</b>
<b>postmap -q "</b><i>string</i><b>" <a href="mysql_table.5.html">mysql</a>:/etc/postfix/filename</b> <b>postmap -q "</b><i>string</i><b>" <a href="mysql_table.5.html">mysql</a>:/etc/postfix/</b><i>filename</i>
<b>postmap -q - <a href="mysql_table.5.html">mysql</a>:/etc/postfix/</b><i>filename</i> &lt;<i>inputfile</i> <b>postmap -q - <a href="mysql_table.5.html">mysql</a>:/etc/postfix/</b><i>filename</i> &lt;<i>inputfile</i>

View File

@ -10,7 +10,7 @@ PGSQL_TABLE(5) PGSQL_TABLE(5)
pgsql_table - Postfix PostgreSQL client configuration pgsql_table - Postfix PostgreSQL client configuration
<b>SYNOPSIS</b> <b>SYNOPSIS</b>
<b>postmap -q "</b><i>string</i><b>" <a href="pgsql_table.5.html">pgsql</a>:/etc/postfix/filename</b> <b>postmap -q "</b><i>string</i><b>" <a href="pgsql_table.5.html">pgsql</a>:/etc/postfix/</b><i>filename</i>
<b>postmap -q - <a href="pgsql_table.5.html">pgsql</a>:/etc/postfix/</b><i>filename</i> &lt;<i>inputfile</i> <b>postmap -q - <a href="pgsql_table.5.html">pgsql</a>:/etc/postfix/</b><i>filename</i> &lt;<i>inputfile</i>

View File

@ -8571,7 +8571,8 @@ address, and one address extension per email address. </p>
extension by the first character that matches the <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> extension by the first character that matches the <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a>
set. </p> set. </p>
<p> When used in <a href="postconf.5.html#forward_path">forward_path</a>, ${<a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a>} is replaced <p> When used in <a href="postconf.5.html#command_execution_directory">command_execution_directory</a>, <a href="postconf.5.html#forward_path">forward_path</a>, or
<a href="postconf.5.html#luser_relay">luser_relay</a>, ${<a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a>} is replaced
with the recipient delimiter that was found in the recipient email with the recipient delimiter that was found in the recipient email
address (Postfix 2.11 and later), or it is replaced with the <a href="postconf.5.html">main.cf</a> address (Postfix 2.11 and later), or it is replaced with the <a href="postconf.5.html">main.cf</a>
<a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> parameter value (Postfix 2.10 and earlier). <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> parameter value (Postfix 2.10 and earlier).

View File

@ -10,7 +10,7 @@ SQLITE_TABLE(5) SQLITE_TABLE(5)
sqlite_table - Postfix SQLite configuration sqlite_table - Postfix SQLite configuration
<b>SYNOPSIS</b> <b>SYNOPSIS</b>
<b>postmap -q "</b><i>string</i><b>" <a href="sqlite_table.5.html">sqlite</a>:/etc/postfix/filename</b> <b>postmap -q "</b><i>string</i><b>" <a href="sqlite_table.5.html">sqlite</a>:/etc/postfix/</b><i>filename</i>
<b>postmap -q - <a href="sqlite_table.5.html">sqlite</a>:/etc/postfix/</b><i>filename</i> &lt;<i>inputfile</i> <b>postmap -q - <a href="sqlite_table.5.html">sqlite</a>:/etc/postfix/</b><i>filename</i> &lt;<i>inputfile</i>

View File

@ -10,7 +10,7 @@ format of Postfix CIDR tables
.nf .nf
\fBpostmap -q "\fIstring\fB" cidr:/etc/postfix/\fIfilename\fR \fBpostmap -q "\fIstring\fB" cidr:/etc/postfix/\fIfilename\fR
\fBpostmap -q - cidr:/etc/postfix/\fIfilename\fR <\fIinputfile\fR \fBpostmap -q - cidr:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
.SH DESCRIPTION .SH DESCRIPTION
.ad .ad
.fi .fi

View File

@ -8,9 +8,9 @@ Postfix LDAP client configuration
.SH "SYNOPSIS" .SH "SYNOPSIS"
.na .na
.nf .nf
\fBpostmap -q "\fIstring\fB" ldap:/etc/postfix/filename\fR \fBpostmap -q "\fIstring\fB" ldap:/etc/postfix/\fIfilename\fR
\fBpostmap -q - ldap:/etc/postfix/\fIfilename\fR <\fIinputfile\fR \fBpostmap -q - ldap:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
.SH DESCRIPTION .SH DESCRIPTION
.ad .ad
.fi .fi

View File

@ -8,9 +8,9 @@ Postfix memcache client configuration
.SH "SYNOPSIS" .SH "SYNOPSIS"
.na .na
.nf .nf
\fBpostmap -q "\fIstring\fB" memcache:/etc/postfix/filename\fR \fBpostmap -q "\fIstring\fB" memcache:/etc/postfix/\fIfilename\fR
\fBpostmap -q - memcache:/etc/postfix/\fIfilename\fR <\fIinputfile\fR \fBpostmap -q - memcache:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
.SH DESCRIPTION .SH DESCRIPTION
.ad .ad
.fi .fi

View File

@ -8,9 +8,9 @@ Postfix MySQL client configuration
.SH "SYNOPSIS" .SH "SYNOPSIS"
.na .na
.nf .nf
\fBpostmap -q "\fIstring\fB" mysql:/etc/postfix/filename\fR \fBpostmap -q "\fIstring\fB" mysql:/etc/postfix/\fIfilename\fR
\fBpostmap -q - mysql:/etc/postfix/\fIfilename\fR <\fIinputfile\fR \fBpostmap -q - mysql:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
.SH DESCRIPTION .SH DESCRIPTION
.ad .ad
.fi .fi

View File

@ -10,7 +10,7 @@ Postfix NIS+ client
.nf .nf
\fBpostmap -q "\fIstring\fB" "nisplus:[\fIname\fB=%s];\fIname.name.\fB"\fR \fBpostmap -q "\fIstring\fB" "nisplus:[\fIname\fB=%s];\fIname.name.\fB"\fR
\fBpostmap -q - "nisplus:[\fIname\fB=%s];\fIname.name.\fB"\fR <\fIinputfile\fR \fBpostmap -q - "nisplus:[\fIname\fB=%s];\fIname.name.\fB" <\fIinputfile\fR
.SH DESCRIPTION .SH DESCRIPTION
.ad .ad
.fi .fi

View File

@ -10,7 +10,7 @@ format of Postfix PCRE tables
.nf .nf
\fBpostmap -q "\fIstring\fB" pcre:/etc/postfix/\fIfilename\fR \fBpostmap -q "\fIstring\fB" pcre:/etc/postfix/\fIfilename\fR
\fBpostmap -q - pcre:/etc/postfix/\fIfilename\fR <\fIinputfile\fR \fBpostmap -q - pcre:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
.SH DESCRIPTION .SH DESCRIPTION
.ad .ad
.fi .fi

View File

@ -8,9 +8,9 @@ Postfix PostgreSQL client configuration
.SH "SYNOPSIS" .SH "SYNOPSIS"
.na .na
.nf .nf
\fBpostmap -q "\fIstring\fB" pgsql:/etc/postfix/filename\fR \fBpostmap -q "\fIstring\fB" pgsql:/etc/postfix/\fIfilename\fR
\fBpostmap -q - pgsql:/etc/postfix/\fIfilename\fR <\fIinputfile\fR \fBpostmap -q - pgsql:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
.SH DESCRIPTION .SH DESCRIPTION
.ad .ad
.fi .fi

View File

@ -5144,7 +5144,8 @@ When the recipient_delimiter set contains multiple characters
extension by the first character that matches the recipient_delimiter extension by the first character that matches the recipient_delimiter
set. set.
.PP .PP
When used in forward_path, ${recipient_delimiter} is replaced When used in command_execution_directory, forward_path, or
luser_relay, ${recipient_delimiter} is replaced
with the recipient delimiter that was found in the recipient email with the recipient delimiter that was found in the recipient email
address (Postfix 2.11 and later), or it is replaced with the main.cf address (Postfix 2.11 and later), or it is replaced with the main.cf
recipient_delimiter parameter value (Postfix 2.10 and earlier). recipient_delimiter parameter value (Postfix 2.10 and earlier).

View File

@ -10,7 +10,7 @@ format of Postfix regular expression tables
.nf .nf
\fBpostmap -q "\fIstring\fB" regexp:/etc/postfix/\fIfilename\fR \fBpostmap -q "\fIstring\fB" regexp:/etc/postfix/\fIfilename\fR
\fBpostmap -q - regexp:/etc/postfix/\fIfilename\fR <\fIinputfile\fR \fBpostmap -q - regexp:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
.SH DESCRIPTION .SH DESCRIPTION
.ad .ad
.fi .fi

View File

@ -8,9 +8,9 @@ Postfix SQLite configuration
.SH "SYNOPSIS" .SH "SYNOPSIS"
.na .na
.nf .nf
\fBpostmap -q "\fIstring\fB" sqlite:/etc/postfix/filename\fR \fBpostmap -q "\fIstring\fB" sqlite:/etc/postfix/\fIfilename\fR
\fBpostmap -q - sqlite:/etc/postfix/\fIfilename\fR <\fIinputfile\fR \fBpostmap -q - sqlite:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
.SH DESCRIPTION .SH DESCRIPTION
.ad .ad
.fi .fi

View File

@ -10,7 +10,7 @@ Postfix client/server table lookup protocol
.nf .nf
\fBpostmap -q "\fIstring\fB" tcp:\fIhost:port\fR \fBpostmap -q "\fIstring\fB" tcp:\fIhost:port\fR
\fBpostmap -q - tcp:\fIhost:port\fR <\fIinputfile\fR \fBpostmap -q - tcp:\fIhost:port\fB <\fIinputfile\fR
.SH DESCRIPTION .SH DESCRIPTION
.ad .ad
.fi .fi

View File

@ -6,7 +6,7 @@
# SYNOPSIS # SYNOPSIS
# \fBpostmap -q "\fIstring\fB" cidr:/etc/postfix/\fIfilename\fR # \fBpostmap -q "\fIstring\fB" cidr:/etc/postfix/\fIfilename\fR
# #
# \fBpostmap -q - cidr:/etc/postfix/\fIfilename\fR <\fIinputfile\fR # \fBpostmap -q - cidr:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
# DESCRIPTION # DESCRIPTION
# The Postfix mail system uses optional lookup tables. # The Postfix mail system uses optional lookup tables.
# These tables are usually in \fBdbm\fR or \fBdb\fR format. # These tables are usually in \fBdbm\fR or \fBdb\fR format.

View File

@ -4,9 +4,9 @@
# SUMMARY # SUMMARY
# Postfix LDAP client configuration # Postfix LDAP client configuration
# SYNOPSIS # SYNOPSIS
# \fBpostmap -q "\fIstring\fB" ldap:/etc/postfix/filename\fR # \fBpostmap -q "\fIstring\fB" ldap:/etc/postfix/\fIfilename\fR
# #
# \fBpostmap -q - ldap:/etc/postfix/\fIfilename\fR <\fIinputfile\fR # \fBpostmap -q - ldap:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
# DESCRIPTION # DESCRIPTION
# The Postfix mail system uses optional tables for address # The Postfix mail system uses optional tables for address
# rewriting or mail routing. These tables are usually in # rewriting or mail routing. These tables are usually in

View File

@ -4,9 +4,9 @@
# SUMMARY # SUMMARY
# Postfix memcache client configuration # Postfix memcache client configuration
# SYNOPSIS # SYNOPSIS
# \fBpostmap -q "\fIstring\fB" memcache:/etc/postfix/filename\fR # \fBpostmap -q "\fIstring\fB" memcache:/etc/postfix/\fIfilename\fR
# #
# \fBpostmap -q - memcache:/etc/postfix/\fIfilename\fR <\fIinputfile\fR # \fBpostmap -q - memcache:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
# DESCRIPTION # DESCRIPTION
# The Postfix mail system uses optional tables for address # The Postfix mail system uses optional tables for address
# rewriting or mail routing. These tables are usually in # rewriting or mail routing. These tables are usually in

View File

@ -4,9 +4,9 @@
# SUMMARY # SUMMARY
# Postfix MySQL client configuration # Postfix MySQL client configuration
# SYNOPSIS # SYNOPSIS
# \fBpostmap -q "\fIstring\fB" mysql:/etc/postfix/filename\fR # \fBpostmap -q "\fIstring\fB" mysql:/etc/postfix/\fIfilename\fR
# #
# \fBpostmap -q - mysql:/etc/postfix/\fIfilename\fR <\fIinputfile\fR # \fBpostmap -q - mysql:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
# DESCRIPTION # DESCRIPTION
# The Postfix mail system uses optional tables for address # The Postfix mail system uses optional tables for address
# rewriting or mail routing. These tables are usually in # rewriting or mail routing. These tables are usually in

View File

@ -6,7 +6,7 @@
# SYNOPSIS # SYNOPSIS
# \fBpostmap -q "\fIstring\fB" "nisplus:[\fIname\fB=%s];\fIname.name.\fB"\fR # \fBpostmap -q "\fIstring\fB" "nisplus:[\fIname\fB=%s];\fIname.name.\fB"\fR
# #
# \fBpostmap -q - "nisplus:[\fIname\fB=%s];\fIname.name.\fB"\fR <\fIinputfile\fR # \fBpostmap -q - "nisplus:[\fIname\fB=%s];\fIname.name.\fB" <\fIinputfile\fR
# DESCRIPTION # DESCRIPTION
# The Postfix mail system uses optional lookup tables. # The Postfix mail system uses optional lookup tables.
# These tables are usually in \fBdbm\fR or \fBdb\fR format. # These tables are usually in \fBdbm\fR or \fBdb\fR format.

View File

@ -6,7 +6,7 @@
# SYNOPSIS # SYNOPSIS
# \fBpostmap -q "\fIstring\fB" pcre:/etc/postfix/\fIfilename\fR # \fBpostmap -q "\fIstring\fB" pcre:/etc/postfix/\fIfilename\fR
# #
# \fBpostmap -q - pcre:/etc/postfix/\fIfilename\fR <\fIinputfile\fR # \fBpostmap -q - pcre:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
# DESCRIPTION # DESCRIPTION
# The Postfix mail system uses optional tables for address # The Postfix mail system uses optional tables for address
# rewriting, mail routing, or access control. These tables # rewriting, mail routing, or access control. These tables

View File

@ -4,9 +4,9 @@
# SUMMARY # SUMMARY
# Postfix PostgreSQL client configuration # Postfix PostgreSQL client configuration
# SYNOPSIS # SYNOPSIS
# \fBpostmap -q "\fIstring\fB" pgsql:/etc/postfix/filename\fR # \fBpostmap -q "\fIstring\fB" pgsql:/etc/postfix/\fIfilename\fR
# #
# \fBpostmap -q - pgsql:/etc/postfix/\fIfilename\fR <\fIinputfile\fR # \fBpostmap -q - pgsql:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
# DESCRIPTION # DESCRIPTION
# The Postfix mail system uses optional tables for address # The Postfix mail system uses optional tables for address
# rewriting or mail routing. These tables are usually in # rewriting or mail routing. These tables are usually in

View File

@ -6,7 +6,7 @@
# SYNOPSIS # SYNOPSIS
# \fBpostmap -q "\fIstring\fB" regexp:/etc/postfix/\fIfilename\fR # \fBpostmap -q "\fIstring\fB" regexp:/etc/postfix/\fIfilename\fR
# #
# \fBpostmap -q - regexp:/etc/postfix/\fIfilename\fR <\fIinputfile\fR # \fBpostmap -q - regexp:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
# DESCRIPTION # DESCRIPTION
# The Postfix mail system uses optional tables for address # The Postfix mail system uses optional tables for address
# rewriting, mail routing, or access control. These tables # rewriting, mail routing, or access control. These tables

View File

@ -4,9 +4,9 @@
# SUMMARY # SUMMARY
# Postfix SQLite configuration # Postfix SQLite configuration
# SYNOPSIS # SYNOPSIS
# \fBpostmap -q "\fIstring\fB" sqlite:/etc/postfix/filename\fR # \fBpostmap -q "\fIstring\fB" sqlite:/etc/postfix/\fIfilename\fR
# #
# \fBpostmap -q - sqlite:/etc/postfix/\fIfilename\fR <\fIinputfile\fR # \fBpostmap -q - sqlite:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
# DESCRIPTION # DESCRIPTION
# The Postfix mail system uses optional tables for address # The Postfix mail system uses optional tables for address
# rewriting or mail routing. These tables are usually in # rewriting or mail routing. These tables are usually in

View File

@ -6,7 +6,7 @@
# SYNOPSIS # SYNOPSIS
# \fBpostmap -q "\fIstring\fB" tcp:\fIhost:port\fR # \fBpostmap -q "\fIstring\fB" tcp:\fIhost:port\fR
# #
# \fBpostmap -q - tcp:\fIhost:port\fR <\fIinputfile\fR # \fBpostmap -q - tcp:\fIhost:port\fB <\fIinputfile\fR
# DESCRIPTION # DESCRIPTION
# The Postfix mail system uses optional tables for address # The Postfix mail system uses optional tables for address
# rewriting or mail routing. These tables are usually in # rewriting or mail routing. These tables are usually in

View File

@ -207,12 +207,20 @@ extern int dns_rr_eq_sa(DNS_RR *, struct sockaddr *);
/* /*
* dns_lookup.c * dns_lookup.c
*/ */
extern int dns_lookup(const char *, unsigned, unsigned, DNS_RR **, extern int dns_lookup_r(const char *, unsigned, unsigned, DNS_RR **,
VSTRING *, VSTRING *); VSTRING *, VSTRING *, int *);
extern int dns_lookup_l(const char *, unsigned, DNS_RR **, VSTRING *, extern int dns_lookup_rl(const char *, unsigned, DNS_RR **, VSTRING *,
VSTRING *, int,...); VSTRING *, int *, int,...);
extern int dns_lookup_v(const char *, unsigned, DNS_RR **, VSTRING *, extern int dns_lookup_rv(const char *, unsigned, DNS_RR **, VSTRING *,
VSTRING *, int, unsigned *); VSTRING *, int *, int, unsigned *);
#define dns_lookup(name, type, rflags, list, fqdn, why) \
dns_lookup_r((name), (type), (rflags), (list), (fqdn), (why), (int *) 0)
#define dns_lookup_l(name, rflags, list, fqdn, why, lflags, ...) \
dns_lookup_rl((name), (rflags), (list), (fqdn), (why), (int *) 0, \
(lflags), __VA_ARGS__)
#define dns_lookup_v(name, rflags, list, fqdn, why, lflags, ltype) \
dns_lookup_rv((name), (rflags), (list), (fqdn), (why), (int *) 0, \
(lflags), (ltype))
/* /*
* Request flags. * Request flags.

View File

@ -31,6 +31,37 @@
/* VSTRING *why; /* VSTRING *why;
/* int lflags; /* int lflags;
/* unsigned *ltype; /* unsigned *ltype;
/* AUXILIARY FUNCTIONS
/* int dns_lookup_r(name, type, rflags, list, fqdn, why, rcode)
/* const char *name;
/* unsigned type;
/* unsigned rflags;
/* DNS_RR **list;
/* VSTRING *fqdn;
/* VSTRING *why;
/* int *rcode;
/*
/* int dns_lookup_rl(name, rflags, list, fqdn, why, rcode, lflags,
/* ltype, ...)
/* const char *name;
/* unsigned rflags;
/* DNS_RR **list;
/* VSTRING *fqdn;
/* VSTRING *why;
/* int *rcode;
/* int lflags;
/* unsigned ltype;
/*
/* int dns_lookup_rv(name, rflags, list, fqdn, why, rcode, lflags,
/* ltype)
/* const char *name;
/* unsigned rflags;
/* DNS_RR **list;
/* VSTRING *fqdn;
/* VSTRING *why;
/* int *rcode;
/* int lflags;
/* unsigned *ltype;
/* DESCRIPTION /* DESCRIPTION
/* dns_lookup() looks up DNS resource records. When requested to /* dns_lookup() looks up DNS resource records. When requested to
/* look up data other than type CNAME, it will follow a limited /* look up data other than type CNAME, it will follow a limited
@ -42,6 +73,9 @@
/* /*
/* dns_lookup_l() and dns_lookup_v() allow the user to specify /* dns_lookup_l() and dns_lookup_v() allow the user to specify
/* a list of resource types. /* a list of resource types.
/*
/* dns_lookup_r(), dns_lookup_rl() and dns_lookup_rv() provide
/* additional information.
/* INPUTS /* INPUTS
/* .ad /* .ad
/* .fi /* .fi
@ -64,6 +98,9 @@
/* Request DNSSEC validation. This flag is silently ignored /* Request DNSSEC validation. This flag is silently ignored
/* when the system stub resolver API, resolver(3), does not /* when the system stub resolver API, resolver(3), does not
/* implement DNSSEC. /* implement DNSSEC.
/* .IP
/* Pointer to storage for the reply RCODE value. This gives
/* more detailed information than DNS_FAIL, DNS_RETRY, etc.
/* .RE /* .RE
/* .IP lflags /* .IP lflags
/* Multi-type request control for dns_lookup_l() and dns_lookup_v(). /* Multi-type request control for dns_lookup_l() and dns_lookup_v().
@ -161,11 +198,12 @@
* Structure to keep track of things while decoding a name server reply. * Structure to keep track of things while decoding a name server reply.
*/ */
#define DEF_DNS_REPLY_SIZE 4096 /* in case we're using TCP */ #define DEF_DNS_REPLY_SIZE 4096 /* in case we're using TCP */
#define MAX_DNS_REPLY_SIZE 32768 /* in case we're using TCP */ #define MAX_DNS_REPLY_SIZE 65536 /* in case we're using TCP */
typedef struct DNS_REPLY { typedef struct DNS_REPLY {
unsigned char *buf; /* raw reply data */ unsigned char *buf; /* raw reply data */
size_t buf_len; /* reply buffer length */ size_t buf_len; /* reply buffer length */
int rcode; /* unfiltered reply code */
int dnssec_valid; /* DNSSEC AD bit */ int dnssec_valid; /* DNSSEC AD bit */
int query_count; /* number of queries */ int query_count; /* number of queries */
int answer_count; /* number of answers */ int answer_count; /* number of answers */
@ -238,6 +276,8 @@ static int dns_query(const char *name, int type, int flags,
len = res_search((char *) name, C_IN, type, reply->buf, reply->buf_len); len = res_search((char *) name, C_IN, type, reply->buf, reply->buf_len);
_res.options &= ~flags; _res.options &= ~flags;
_res.options |= saved_options; _res.options |= saved_options;
reply_header = (HEADER *) reply->buf;
reply->rcode = reply_header->rcode;
if (len < 0) { if (len < 0) {
if (why) if (why)
vstring_sprintf(why, "Host or domain name not found. " vstring_sprintf(why, "Host or domain name not found. "
@ -259,7 +299,6 @@ static int dns_query(const char *name, int type, int flags,
if (msg_verbose) if (msg_verbose)
msg_info("dns_query: %s (%s): OK", name, dns_strtype(type)); msg_info("dns_query: %s (%s): OK", name, dns_strtype(type));
reply_header = (HEADER *) reply->buf;
if (reply_header->tc == 0 || reply->buf_len >= MAX_DNS_REPLY_SIZE) if (reply_header->tc == 0 || reply->buf_len >= MAX_DNS_REPLY_SIZE)
break; break;
reply->buf = (unsigned char *) reply->buf = (unsigned char *)
@ -602,10 +641,11 @@ static int dns_get_answer(const char *orig_name, DNS_REPLY *reply, int type,
return (not_found_status); return (not_found_status);
} }
/* dns_lookup - DNS lookup user interface */ /* dns_lookup_r - DNS lookup user interface */
int dns_lookup(const char *name, unsigned type, unsigned flags, int dns_lookup_r(const char *name, unsigned type, unsigned flags,
DNS_RR **rrlist, VSTRING *fqdn, VSTRING *why) DNS_RR **rrlist, VSTRING *fqdn, VSTRING *why,
int *rcode)
{ {
char cname[DNS_NAME_LEN]; char cname[DNS_NAME_LEN];
int c_len = sizeof(cname); int c_len = sizeof(cname);
@ -648,7 +688,10 @@ int dns_lookup(const char *name, unsigned type, unsigned flags,
/* /*
* Perform the DNS lookup, and pre-parse the name server reply. * Perform the DNS lookup, and pre-parse the name server reply.
*/ */
if ((status = dns_query(name, type, flags, &reply, why)) != DNS_OK) status = dns_query(name, type, flags, &reply, why);
if (rcode)
*rcode = reply.rcode;
if (status != DNS_OK)
return (status); return (status);
/* /*
@ -680,10 +723,11 @@ int dns_lookup(const char *name, unsigned type, unsigned flags,
return (DNS_NOTFOUND); return (DNS_NOTFOUND);
} }
/* dns_lookup_l - DNS lookup interface with types list */ /* dns_lookup_rl - DNS lookup interface with types list */
int dns_lookup_l(const char *name, unsigned flags, DNS_RR **rrlist, int dns_lookup_rl(const char *name, unsigned flags, DNS_RR **rrlist,
VSTRING *fqdn, VSTRING *why, int lflags,...) VSTRING *fqdn, VSTRING *why, int *rcode,
int lflags,...)
{ {
va_list ap; va_list ap;
unsigned type; unsigned type;
@ -699,8 +743,8 @@ int dns_lookup_l(const char *name, unsigned flags, DNS_RR **rrlist,
if (msg_verbose) if (msg_verbose)
msg_info("lookup %s type %s flags %d", msg_info("lookup %s type %s flags %d",
name, dns_strtype(type), flags); name, dns_strtype(type), flags);
status = dns_lookup(name, type, flags, rrlist ? &rr : (DNS_RR **) 0, status = dns_lookup_r(name, type, flags, rrlist ? &rr : (DNS_RR **) 0,
fqdn, why); fqdn, why, rcode);
if (status == DNS_OK) { if (status == DNS_OK) {
non_err = 1; non_err = 1;
if (rrlist) if (rrlist)
@ -719,11 +763,11 @@ int dns_lookup_l(const char *name, unsigned flags, DNS_RR **rrlist,
return (non_err ? DNS_OK : soft_err ? DNS_RETRY : status); return (non_err ? DNS_OK : soft_err ? DNS_RETRY : status);
} }
/* dns_lookup_v - DNS lookup interface with types vector */ /* dns_lookup_rv - DNS lookup interface with types vector */
int dns_lookup_v(const char *name, unsigned flags, DNS_RR **rrlist, int dns_lookup_rv(const char *name, unsigned flags, DNS_RR **rrlist,
VSTRING *fqdn, VSTRING *why, int lflags, VSTRING *fqdn, VSTRING *why, int *rcode,
unsigned *types) int lflags, unsigned *types)
{ {
unsigned type; unsigned type;
int status = DNS_NOTFOUND; int status = DNS_NOTFOUND;
@ -737,8 +781,8 @@ int dns_lookup_v(const char *name, unsigned flags, DNS_RR **rrlist,
if (msg_verbose) if (msg_verbose)
msg_info("lookup %s type %s flags %d", msg_info("lookup %s type %s flags %d",
name, dns_strtype(type), flags); name, dns_strtype(type), flags);
status = dns_lookup(name, type, flags, rrlist ? &rr : (DNS_RR **) 0, status = dns_lookup_r(name, type, flags, rrlist ? &rr : (DNS_RR **) 0,
fqdn, why); fqdn, why, rcode);
if (status == DNS_OK) { if (status == DNS_OK) {
non_err = 1; non_err = 1;
if (rrlist) if (rrlist)

View File

@ -102,6 +102,7 @@ int main(int argc, char **argv)
char *name; char *name;
VSTRING *fqdn = vstring_alloc(100); VSTRING *fqdn = vstring_alloc(100);
VSTRING *why = vstring_alloc(100); VSTRING *why = vstring_alloc(100);
int rcode;
DNS_RR *rr; DNS_RR *rr;
int i; int i;
@ -117,10 +118,10 @@ int main(int argc, char **argv)
argv_free(types_argv); argv_free(types_argv);
name = argv[2]; name = argv[2];
msg_verbose = 1; msg_verbose = 1;
switch (dns_lookup_v(name, RES_DEBUG | RES_USE_DNSSEC, &rr, fqdn, why, switch (dns_lookup_rv(name, RES_DEBUG | RES_USE_DNSSEC, &rr, fqdn, why,
DNS_REQ_FLAG_NONE, types)) { &rcode, DNS_REQ_FLAG_NONE, types)) {
default: default:
msg_fatal("%s", vstring_str(why)); msg_fatal("%s (rcode=%d)", vstring_str(why), rcode);
case DNS_OK: case DNS_OK:
printf("%s: fqdn: %s\n", name, vstring_str(fqdn)); printf("%s: fqdn: %s\n", name, vstring_str(fqdn));
print_rr(rr); print_rr(rr);

View File

@ -574,10 +574,29 @@ DICT *dict_memcache_open(const char *name, int open_flags, int dict_flags)
(char *) 0, 0, 0); (char *) 0, 0, 0);
if (backup) { if (backup) {
dict_mc->backup = dict_open(backup, open_flags, dict_flags); 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); myfree(backup);
} else } else
dict_mc->backup = 0; 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 * Parse templates and common database parameters. Maps that use
* substring keys should only be used with the full input key. * substring keys should only be used with the full input key.

View File

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

View File

@ -244,9 +244,7 @@ static int random_interval(int interval)
static void command(VSTREAM *stream, char *fmt,...) static void command(VSTREAM *stream, char *fmt,...)
{ {
VSTRING *buf;
va_list ap; va_list ap;
va_list ap2;
va_start(ap, fmt); va_start(ap, fmt);
@ -255,12 +253,11 @@ static void command(VSTREAM *stream, char *fmt,...)
* what the program is trying to do. * what the program is trying to do.
*/ */
if (msg_verbose) { if (msg_verbose) {
buf = vstring_alloc(100); va_list ap2;
VA_COPY(ap2, ap); VA_COPY(ap2, ap);
vstring_vsprintf(buf, fmt, ap2); vmsg_info(fmt, ap2);
va_end(ap2); va_end(ap2);
msg_info("%s", vstring_str(buf));
vstring_free(buf);
} }
smtp_vprintf(stream, fmt, ap); smtp_vprintf(stream, fmt, ap);
va_end(ap); va_end(ap);

View File

@ -57,7 +57,8 @@ typedef struct DICT {
int (*sequence) (struct DICT *, int, const char **, const char **); int (*sequence) (struct DICT *, int, const char **, const char **);
int (*lock) (struct DICT *, int); int (*lock) (struct DICT *, int);
void (*close) (struct DICT *); void (*close) (struct DICT *);
int lock_fd; /* for dict_update() lock */ int lock_type; /* for read/write lock */
int lock_fd; /* for read/write lock */
int stat_fd; /* change detection */ int stat_fd; /* change detection */
time_t mtime; /* mod time at open */ time_t mtime; /* mod time at open */
VSTRING *fold_buf; /* key folding buffer */ VSTRING *fold_buf; /* key folding buffer */

View File

@ -28,7 +28,8 @@
/* /*
/* One exception is the default lock function. When the /* One exception is the default lock function. When the
/* dictionary provides a file handle for locking, the default /* dictionary provides a file handle for locking, the default
/* lock function returns the result from myflock(), otherwise /* lock function returns the result from myflock with the
/* locking method specified in the lock_type member, otherwise
/* it returns 0. Presently, the lock function is used only to /* it returns 0. Presently, the lock function is used only to
/* implement the DICT_FLAG_OPEN_LOCK feature (lock the database /* implement the DICT_FLAG_OPEN_LOCK feature (lock the database
/* exclusively after it is opened) for databases that are not /* exclusively after it is opened) for databases that are not
@ -115,7 +116,7 @@ static int dict_default_sequence(DICT *dict, int unused_function,
static int dict_default_lock(DICT *dict, int operation) static int dict_default_lock(DICT *dict, int operation)
{ {
if (dict->lock_fd >= 0) { if (dict->lock_fd >= 0) {
return (myflock(dict->lock_fd, INTERNAL_LOCK, operation)); return (myflock(dict->lock_fd, dict->lock_type, operation));
} else { } else {
return (0); return (0);
} }
@ -144,6 +145,7 @@ DICT *dict_alloc(const char *dict_type, const char *dict_name, ssize_t size)
dict->sequence = dict_default_sequence; dict->sequence = dict_default_sequence;
dict->close = dict_default_close; dict->close = dict_default_close;
dict->lock = dict_default_lock; dict->lock = dict_default_lock;
dict->lock_type = INTERNAL_LOCK;
dict->lock_fd = -1; dict->lock_fd = -1;
dict->stat_fd = -1; dict->stat_fd = -1;
dict->mtime = 0; dict->mtime = 0;

View File

@ -646,6 +646,7 @@ DICT *dict_lmdb_open(const char *path, int open_flags, int dict_flags)
if (fstat(db_fd, &st) < 0) if (fstat(db_fd, &st) < 0)
msg_fatal("dict_lmdb_open: fstat: %m"); msg_fatal("dict_lmdb_open: fstat: %m");
dict_lmdb->dict.lock_fd = dict_lmdb->dict.stat_fd = db_fd; dict_lmdb->dict.lock_fd = dict_lmdb->dict.stat_fd = db_fd;
dict_lmdb->dict.lock_type = MYFLOCK_STYLE_FCNTL;
dict_lmdb->dict.mtime = st.st_mtime; dict_lmdb->dict.mtime = st.st_mtime;
dict_lmdb->dict.owner.uid = st.st_uid; dict_lmdb->dict.owner.uid = st.st_uid;
dict_lmdb->dict.owner.status = (st.st_uid != 0); dict_lmdb->dict.owner.status = (st.st_uid != 0);
@ -672,6 +673,12 @@ DICT *dict_lmdb_open(const char *path, int open_flags, int dict_flags)
if (dict_flags & DICT_FLAG_BULK_UPDATE) if (dict_flags & DICT_FLAG_BULK_UPDATE)
dict_jmp_alloc(&dict_lmdb->dict); 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 * The following requests return an error result only if we have serious
* memory corruption problem. * memory corruption problem.

View File

@ -90,10 +90,15 @@
/* .IP DICT_FLAG_LOCK /* .IP DICT_FLAG_LOCK
/* With maps where this is appropriate, acquire an exclusive lock /* With maps where this is appropriate, acquire an exclusive lock
/* before writing, and acquire a shared lock before reading. /* before writing, and acquire a shared lock before reading.
/* Release the lock when the operation completes.
/* .IP DICT_FLAG_OPEN_LOCK /* .IP DICT_FLAG_OPEN_LOCK
/* With databases that are not multi-writer safe, request that /* With databases that are not multi-writer safe, request that
/* dict_open() acquires an exclusive lock, or that it terminates /* dict_open() acquires an exclusive lock, or that it terminates
/* with a fatal run-time error. /* with a fatal run-time error.
/*
/* With databases that are multi-writer safe, downgrade from
/* DICT_FLAG_OPEN_LOCK (persistent lock) to DICT_FLAG_LOCK
/* (temporary lock).
/* .IP DICT_FLAG_FOLD_FIX /* .IP DICT_FLAG_FOLD_FIX
/* With databases whose lookup fields are fixed-case strings, /* With databases whose lookup fields are fixed-case strings,
/* fold the search string to lower case before accessing the /* fold the search string to lower case before accessing the
@ -384,9 +389,10 @@ DICT *dict_open3(const char *dict_type, const char *dict_name,
"cannot open %s:%s: %m", dict_type, dict_name)); "cannot open %s:%s: %m", dict_type, dict_name));
if (msg_verbose) if (msg_verbose)
msg_info("%s: %s:%s", myname, dict_type, dict_name); msg_info("%s: %s:%s", myname, dict_type, dict_name);
/* XXX the choice between wait-for-lock or no-wait is hard-coded. */ /* Write-share safe maps may downgrade a persistent lock to temporary. */
if (dict_flags & DICT_FLAG_OPEN_LOCK) { /* XXX The choice between wait-for-lock or no-wait is hard-coded. */
if (dict_flags & DICT_FLAG_LOCK) 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", msg_panic("%s: attempt to open %s:%s with both \"open\" lock and \"access\" lock",
myname, dict_type, dict_name); myname, dict_type, dict_name);
if (dict->lock(dict, MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT) < 0) if (dict->lock(dict, MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT) < 0)