not hurt to do this also for HTML. Files: proto/Makefile.in,
proto/MULTI_INSTANCE_README.html.
-20121104
+20131104
Feature: ${queue_id} macro support for the pipe(8) delivery
agent by Andreas Schulze. File: pipe/pipe.c.
+
+20131107
+
+ Cleanup: after 16 years the SKIP() and TRIM() macros were
+ triggering compiler warnings. Files: global/mail_params.c,
+ smtpstone/smtp-sink.c, util/mac_parse.c, util/split_nameval.c.
+
+20131110
+
+ Bugfix (introduced Oct 26 1997): don't clobber errno before
+ expanding %m. File: util/vbuf_print.c.
+
+20131114
+
+ Cleanup: LMDB >= 0.9.10 does not need the MDB_WRITEMAP
+ workaround to avoid heap memory information leaks. File:
+ util/dict_lmdb.c.
+
+20131114
+
+ Cleanup: Coverity found a harmless memory leak in the
+ postconf master.cf parser. Reported by Christos Zoulas,
+ NetBSD. File: postconf/postconf_master.c.
+
+ Cleanup: graceful degradation after database open() error.
+ Several instances of that code introduced a harmless memory
+ leak, and Coverity complained about one of them (Christos
+ Zoulas, NetBSD). Instead of adding random code in random
+ places, restructured dict_foo_open() routines with consistent
+ code to dispose of memory or file handles. Files: dict_thash.c,
+ dict_sockmap.c, dict_regexp.c, dict_pcre.c, dict_lmdb.c,
+ dict_dbm.c, dict_cidr.c, dict_cdb.c.
+
+ Cleanup: warning message after canonical/virtal/etc.
+ table lookup error. Files: cleanup/cleanup_addr.c,
+ cleanup/cleanup_map11.c, cleanup/cleanup_map1n.c,
+ cleanup/cleanup_masquerade.c, cleanup/cleanup_message.c,
+ cleanup/cleanup_milter.c.
If you must store encrypted passwords, you cannot use the ldapdb auxprop
plugin. Instead, you can use "saslauthd -a ldap" to query the LDAP database
- directly, with appropriate configuration in saslauthd.conf. This may be
- documented in a later version of this document. You will not be able to use
- any of the methods that require access to plaintext passwords, such as the
- shared-secret methods CRAM-MD5 and DIGEST-MD5.
+ directly, with appropriate configuration in saslauthd.conf, as described
+ here. You will not be able to use any of the methods that require access to
+ plaintext passwords, such as the shared-secret methods CRAM-MD5 and DIGEST-
+ MD5.
The ldapdb plugin implements proxy authorization. This means that the ldapdb
plugin uses its own username and password to authenticate with the LDAP server,
Wish list:
+ Un-break "make tests" under src/smtpd.
+
+ Make been_here flag BH_FLAG_FOLD configurable for masochists.
+
+ Preserve case in smtpd_resolve_addr() and add a structure
+ member for the case-folded address.
+
Per SASL account rate limits.
- Add watchdog timer to postmap/postalias.
+ Watchdog timer to postmap/postalias.
+
+ C99 va_copy() support.
Things to do before the stable release:
<p> If you must store encrypted passwords, you cannot use the ldapdb
auxprop plugin. Instead, you can use "<code>saslauthd -a ldap</code>"
to query the LDAP database directly, with appropriate configuration
-in <code>saslauthd.conf</code>. This may be documented in a later
-version of this document. You will not be able to use any of the
+in <code>saslauthd.conf</code>, <a
+href="http://git.cyrusimap.org/cyrus-sasl/tree/saslauthd/LDAP_SASLAUTHD">as
+described here</a>. You will not be able to use any of the
methods that require access to plaintext passwords, such as the
shared-secret methods CRAM-MD5 and DIGEST-MD5. </p>
trolled with the <b><a href="postconf.5.html#queue_directory">queue_directory</a></b> configura-
tion parameter in <a href="postconf.5.html">main.cf</a>).
- On Solaris systems the <b>unix</b> type is imple-
- mented with streams sockets.
+ On Solaris 8 and earlier systems the <b>unix</b>
+ type is implemented with streams sockets.
<b>fifo</b> The service listens on a FIFO (named pipe)
and is accessible for local clients only.
trolled with the <b><a href="postconf.5.html#queue_directory">queue_directory</a></b> configura-
tion parameter in <a href="postconf.5.html">main.cf</a>).
- On Solaris systems the <b>pass</b> type is imple-
- mented with streams sockets.
+ On Solaris 8 and earlier systems the <b>pass</b>
+ type is implemented with streams sockets.
This feature is available as of Postfix ver-
sion 2.5.
to understand and maintain. At a certain
point, it might be easier to configure mul-
tiple instances of Postfix, instead of con-
- figuring multiple personalities via mas-
- ter.cf.
+ figuring multiple personalities via <a href="master.5.html">mas-
+ ter.cf</a>.
<b>-v</b> Increase the verbose logging level. Specify
multiple <b>-v</b> options to make a Postfix daemon
<b>SYNOPSIS</b>
<b>smtp-sink</b> [<i>options</i>] [<b>inet:</b>][<i>host</i>]:<i>port backlog</i>
- <b>smtp-sink</b> [<i>options</i>] <b>unix:</b><i>pathname backlog</i>
+ <b>smtp-sink</b> [<i>options</i>] <b>unix:<i></b>pathname backlog</i>
<b>DESCRIPTION</b>
<b>smtp-sink</b> listens on the named host (or address) and port.
<b>-a</b> Do not announce SASL authentication support.
- <b>-A</b> <i>delay</i>
+ <b>-A <i></b>delay\e[0m
Wait <i>delay</i> seconds after responding to DATA, then
abort prematurely with a 550 reply status. Do not
read further input from the client; this is an
attempt to block the client before it sends ".".
Specify a zero delay value to abort immediately.
- <b>-b</b> <i>soft-bounce-reply</i>
+ <b>-b <i></b>soft-bounce-reply\e[0m
Use <i>soft-bounce-reply</i> for soft reject responses.
The default reply is "450 4.3.0 Error: command
failed".
- <b>-B</b> <i>hard-bounce-reply</i>
+ <b>-B <i></b>hard-bounce-reply\e[0m
Use <i>hard-bounce-reply</i> for hard reject responses.
The default reply is "500 5.3.0 Error: command
failed".
<b>-C</b> Disable XCLIENT support.
- <b>-d</b> <i>dump-template</i>
+ <b>-d <i></b>dump-template\e[0m
Dump each mail transaction to a single-message file
whose name is created by expanding the <i>dump-tem-</i>
<i>plate</i> via strftime(3) and appending a pseudo-random
Note: this option keeps one capture file open for
every mail transaction in progress.
- <b>-D</b> <i>dump-template</i>
+ <b>-D <i></b>dump-template\e[0m
Append mail transactions to a multi-message dump
file whose name is created by expanding the <i>dump-</i>
<i>template</i> via strftime(3). If the template contains
<b>-E</b> Do not announce ENHANCEDSTATUSCODES support.
- <b>-f</b> <i>command,command,...</i>
+ <b>-f <i></b>command,command,...\e[0m
Reject the specified commands with a hard (5xx)
error code. This option implies <b>-p</b>.
<b>-F</b> Disable XFORWARD support.
- <b>-h</b> <i>hostname</i>
+ <b>-h <i></b>hostname\e[0m
Use <i>hostname</i> in the SMTP greeting, in the HELO
response, and in the EHLO response. The default
hostname is "smtp-sink".
<b>-L</b> Enable LMTP instead of SMTP.
- <b>-m</b> <i>count</i> (default: 256)
+ <b>-m <i></b>count</i> (default: 256)
An upper bound on the maximal number of simultane-
ous connections that <b>smtp-sink</b> will handle. This
prevents the process from running out of file
descriptors. Excess connections will stay queued in
the TCP/IP stack.
- <b>-M</b> <i>count</i>
+ <b>-M <i></b>count\e[0m
Terminate after receiving <i>count</i> messages.
- <b>-n</b> <i>count</i>
+ <b>-n <i></b>count\e[0m
Terminate after <i>count</i> sessions.
<b>-p</b> Do not announce support for ESMTP command pipelin-
<b>-P</b> Change the server greeting so that it appears to
come through a CISCO PIX system. Implies <b>-e</b>.
- <b>-q</b> <i>command,command,...</i>
+ <b>-q <i></b>command,command,...\e[0m
Disconnect (without replying) after receiving one
of the specified commands.
and use quotes to protect white space from the
shell. Command names are case-insensitive.
- <b>-Q</b> <i>command,command,...</i>
+ <b>-Q <i></b>command,command,...\e[0m
Send a 421 reply and disconnect after receiving one
of the specified commands.
and use quotes to protect white space from the
shell. Command names are case-insensitive.
- <b>-r</b> <i>command,command,...</i>
+ <b>-r <i></b>command,command,...\e[0m
Reject the specified commands with a soft (4xx)
error code. This option implies <b>-p</b>.
and use quotes to protect white space from the
shell. Command names are case-insensitive.
- <b>-R</b> <i>root-directory</i>
+ <b>-R <i></b>root-directory\e[0m
Change the process root directory to the specified
location. This option requires super-user privi-
leges. See also the <b>-u</b> option.
- <b>-s</b> <i>command,command,...</i>
+ <b>-s <i></b>command,command,...\e[0m
Log the named commands to syslogd.
Examples of commands are CONNECT, HELO, EHLO, LHLO,
tab), \<i>ddd</i> (up to three octal digits) and \\ (the
backslash character).
- <b>-t</b> <i>timeout</i> (default: 100)
+ <b>-t <i></b>timeout</i> (default: 100)
Limit the time for receiving a command or sending a
response. The time limit is specified in seconds.
- <b>-T</b> <i>windowsize</i>
+ <b>-T <i></b>windowsize\e[0m
Override the default TCP window size. To work
around broken TCP window scaling implementations,
specify a value > 0 and < 65536.
- <b>-u</b> <i>username</i>
+ <b>-u <i></b>username\e[0m
Switch to the specified user privileges after open-
ing the network socket and optionally changing the
process root directory. This option is required
<b>-v</b> Show the SMTP conversations.
- <b>-w</b> <i>delay</i>
+ <b>-w <i></b>delay\e[0m
Wait <i>delay</i> seconds before responding to a DATA com-
mand.
- <b>-W</b> <i>command:delay[:odds]</i>
+ <b>-W <i></b>command:delay[:odds]\e[0m
Wait <i>delay</i> seconds before responding to <i>command</i>.
If <i>odds</i> is also specified (a number between 1-99
inclusive), wait for a random multiple of <i>delay</i>.
interface) TCP port <i>port</i>. Both <i>host</i> and <i>port</i> may be
specified in numeric or symbolic form.
- <b>unix:</b><i>pathname</i>
+ <b>unix:<i></b>pathname\e[0m
Listen on the UNIX-domain socket at <i>pathname</i>.
<i>backlog</i>
The format of the <b>smtp-sink</b> generated headers is as fol-
lows:
- <b>X-Client-Addr:</b> <i>text</i>
+ <b>X-Client-Addr: <i></b>text\e[0m
The client IP address without enclosing []. An IPv6
address is prefixed with "ipv6:". This record is
always present.
- <b>X-Client-Proto:</b> <i>text</i>
+ <b>X-Client-Proto: <i></b>text\e[0m
The client protocol: SMTP, ESMTP or LMTP. This
record is always present.
- <b>X-Helo-Args:</b> <i>text</i>
+ <b>X-Helo-Args: <i></b>text\e[0m
The arguments of the last HELO or EHLO command
before this mail delivery transaction. This record
is present only if the client sent a recognizable
HELO or EHLO command before the DATA command.
- <b>X-Mail-Args:</b> <i>text</i>
+ <b>X-Mail-Args: <i></b>text\e[0m
The arguments of the MAIL command that started this
mail delivery transaction. This record is present
exactly once.
- <b>X-Rcpt-Args:</b> <i>text</i>
+ <b>X-Rcpt-Args: <i></b>text\e[0m
The arguments of an RCPT command within this mail
delivery transaction. There is one record for each
RCPT command, and they are in the order as sent by
the client.
- <b>Received:</b> <i>text</i>
+ <b>Received: <i></b>text\e[0m
A message header for compatibility with mail pro-
cessing software. This three-line header marks the
end of the headers provided by <b>smtp-sink</b>, and is
formatted as follows:
- <b>from</b> <i>helo</i> <b>([</b><i>addr</i><b>])</b>
+ <b>from <i></b>helo</i> <b>([<i></b>addr</i><b>])</b>
The HELO or EHLO command argument and client
IP address. If the client did not send HELO
or EHLO, the client IP address is used
instead.
- <b>by</b> <i>host</i> <b>(smtp-sink) with</b> <i>proto</i> <b>id</b> <i>random</i><b>;</b>
+ <b>by <i></b>host</i> <b>(smtp-sink) with <i></b>proto</i> <b>id <i></b>random</i><b>;</b>
The hostname specified with the <b>-h</b> option,
the client protocol (see <b>X-Client-Proto</b>
above), and the pseudo-random portion of the
queue directory (pathname controlled with the \fBqueue_directory\fR
configuration parameter in main.cf).
.sp
-On Solaris systems the \fBunix\fR type is implemented with
-streams sockets.
+On Solaris 8 and earlier systems the \fBunix\fR type is
+implemented with streams sockets.
.IP \fBfifo\fR
The service listens on a FIFO (named pipe) and is accessible
for local clients only.
queue directory (pathname controlled with the \fBqueue_directory\fR
configuration parameter in main.cf).
.sp
-On Solaris systems the \fBpass\fR type is implemented with
-streams sockets.
+On Solaris 8 and earlier systems the \fBpass\fR type is
+implemented with streams sockets.
This feature is available as of Postfix version 2.5.
.RE
<p> If you must store encrypted passwords, you cannot use the ldapdb
auxprop plugin. Instead, you can use "<code>saslauthd -a ldap</code>"
to query the LDAP database directly, with appropriate configuration
-in <code>saslauthd.conf</code>. This may be documented in a later
-version of this document. You will not be able to use any of the
+in <code>saslauthd.conf</code>, <a
+href="http://git.cyrusimap.org/cyrus-sasl/tree/saslauthd/LDAP_SASLAUTHD">as
+described here</a>. You will not be able to use any of the
methods that require access to plaintext passwords, such as the
shared-secret methods CRAM-MD5 and DIGEST-MD5. </p>
# queue directory (pathname controlled with the \fBqueue_directory\fR
# configuration parameter in main.cf).
# .sp
-# On Solaris systems the \fBunix\fR type is implemented with
-# streams sockets.
+# On Solaris 8 and earlier systems the \fBunix\fR type is
+# implemented with streams sockets.
# .IP \fBfifo\fR
# The service listens on a FIFO (named pipe) and is accessible
# for local clients only.
# queue directory (pathname controlled with the \fBqueue_directory\fR
# configuration parameter in main.cf).
# .sp
-# On Solaris systems the \fBpass\fR type is implemented with
-# streams sockets.
+# On Solaris 8 and earlier systems the \fBpass\fR type is
+# implemented with streams sockets.
#
# This feature is available as of Postfix version 2.5.
# .RE
IGNORE_EXTENSION)) != 0) {
cleanup_addr_bcc(state, bcc);
} else if (cleanup_send_bcc_maps->error) {
- msg_warn("%s: %s lookup problem",
+ msg_warn("%s: %s map lookup problem -- "
+ "message not accepted, try again later",
state->queue_id, cleanup_send_bcc_maps->title);
state->errs |= CLEANUP_STAT_WRITE;
}
IGNORE_EXTENSION)) != 0) {
cleanup_addr_bcc(state, bcc);
} else if (cleanup_rcpt_bcc_maps->error) {
- msg_warn("%s: %s lookup problem",
+ msg_warn("%s: %s map lookup problem -- "
+ "message not accepted, try again later",
state->queue_id, cleanup_rcpt_bcc_maps->title);
state->errs |= CLEANUP_STAT_WRITE;
}
if (expand_to_self)
return (did_rewrite);
} else if (maps->error != 0) {
- msg_warn("%s: %s map lookup problem for %s",
+ msg_warn("%s: %s map lookup problem for %s -- "
+ "message not accepted, try again later",
state->queue_id, maps->title, STR(addr));
state->errs |= CLEANUP_STAT_WRITE;
return (did_rewrite);
return (did_rewrite);
}
}
- msg_warn("%s: unreasonable %s map nesting for %s",
+ msg_warn("%s: unreasonable %s map nesting for %s -- "
+ "message not accepted, try again later",
state->queue_id, maps->title, STR(addr));
return (did_rewrite);
}
for (arg = 0; arg < argv->argc; arg++) {
if (argv->argc > var_virt_expan_limit) {
msg_warn("%s: unreasonable %s map expansion size for %s -- "
- "deferring delivery",
+ "message not accepted, try again later",
state->queue_id, maps->title, addr);
state->errs |= CLEANUP_STAT_DEFER;
UPDATE(state->reason, "4.6.0 Alias expansion error");
break;
if (count >= var_virt_recur_limit) {
msg_warn("%s: unreasonable %s map nesting for %s -- "
- "deferring delivery",
+ "message not accepted, try again later",
state->queue_id, maps->title, addr);
state->errs |= CLEANUP_STAT_DEFER;
UPDATE(state->reason, "4.6.0 Alias expansion error");
argv_free(lookup);
} else if (maps->error != 0) {
msg_warn("%s: %s map lookup problem for %s -- "
- "deferring delivery",
+ "message not accepted, try again later",
state->queue_id, maps->title, addr);
state->errs |= CLEANUP_STAT_WRITE;
UPDATE(state->reason, "4.6.0 Alias expansion error");
excluded = (string_list_match(cleanup_masq_exceptions, lowercase(name)) != 0);
myfree(name);
if (cleanup_masq_exceptions->error) {
- msg_info("%s: %s lookup error -- deferring delivery",
+ msg_info("%s: %s map lookup problem -- "
+ "message not accepted, try again later",
state->queue_id, VAR_MASQ_EXCEPTIONS);
state->errs |= CLEANUP_STAT_WRITE;
}
myfree((char *) result);
}
} else if (checks->error) {
- msg_warn("%s: %s map lookup problem -- deferring delivery",
+ msg_warn("%s: %s map lookup problem -- "
+ "message not accepted, try again later",
state->queue_id, checks->title);
state->errs |= CLEANUP_STAT_WRITE;
}
return;
}
} else if (cleanup_body_checks->error) {
- msg_warn("%s: %s map lookup problem -- deferring delivery",
+ msg_warn("%s: %s map lookup problem -- "
+ "message not accepted, try again later",
state->queue_id, cleanup_body_checks->title);
state->errs |= CLEANUP_STAT_WRITE;
}
if (ret == 0) {
return (0);
} else if (ret == HBC_CHECKS_STAT_ERROR) {
- msg_warn("%s: %s lookup error -- deferring delivery",
+ msg_warn("%s: %s map lookup problem -- "
+ "message not accepted, try again later",
state->queue_id, VAR_MILT_HEAD_CHECKS);
state->errs |= CLEANUP_STAT_WRITE;
return (0);
&& cleanup_milter_apply(state, "RCPT", resp) != 0) {
msg_warn("%s: milter configuration error: can't reject recipient "
"in non-smtpd(8) submission", state->queue_id);
- msg_warn("%s: deferring delivery of this message", state->queue_id);
+ msg_warn("%s: message not accepted, try again later", state->queue_id);
CLEANUP_MILTER_SET_REASON(state, "4.3.5 Server configuration error");
state->errs |= CLEANUP_STAT_DEFER;
}
/*
* Ugly macros to make complex expressions less unreadable.
*/
-#define SKIP(start, var, cond) \
- for (var = start; *var && (cond); var++);
+#define SKIP(start, var, cond) do { \
+ for (var = start; *var && (cond); var++) \
+ /* void */; \
+ } while (0)
-#define TRIM(s) { \
+#define TRIM(s) do { \
char *p; \
- for (p = (s) + strlen(s); p > (s) && ISSPACE(p[-1]); p--); \
+ for (p = (s) + strlen(s); p > (s) && ISSPACE(p[-1]); p--) \
+ /* void */; \
*p = 0; \
- }
+ } while (0)
fp = safe_open(path, O_RDONLY, 0, (struct stat *) 0, -1, -1, why);
if (fp == 0)
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20131105"
+#define MAIL_RELEASE_DATE "20131114"
#define MAIL_VERSION_NUMBER "2.11"
#ifdef SNAPSHOT
/* Terminate after \fIcount\fR connections.
/* .IP "\fB-d\fI level\fR"
/* Enable libmilter debugging at the specified level.
+/* .IP "\fB-D\fI address\fR"
+/* Delete the specified recipient address. Multiple -D options
+/* are supported.
/* .IP "\fB-f \fIsender\fR
/* Replace the sender by the specified address.
/* .IP "\fB-h \fI'index header-label header-value'\fR"
#endif
#define MAX_RCPT 10
-int rcpt_count = 0;
-char *rcpt_addr[MAX_RCPT];
+int add_rcpt_count = 0;
+char *add_rcpt[MAX_RCPT];
+int del_rcpt_count = 0;
+char *del_rcpt[MAX_RCPT];
static const char *macro_names[] = {
"_",
{
int count;
- for (count = 0; count < rcpt_count; count++)
- if (smfi_addrcpt(ctx, rcpt_addr[count]) == MI_FAILURE)
- fprintf(stderr, "smfi_addrcpt `%s' failed\n", rcpt_addr[count]);
+ for (count = 0; count < add_rcpt_count; count++)
+ if (smfi_addrcpt(ctx, add_rcpt[count]) == MI_FAILURE)
+ fprintf(stderr, "smfi_addrcpt `%s' failed\n", add_rcpt[count]);
+
+ for (count = 0; count < del_rcpt_count; count++)
+ if (smfi_delrcpt(ctx, del_rcpt[count]) == MI_FAILURE)
+ fprintf(stderr, "smfi_delrcpt `%s' failed\n", del_rcpt[count]);
}
return (test_reply(ctx, test_eom_reply));
}
char *noreply = 0;
const struct noproto_map *np;
- while ((ch = getopt(argc, argv, "a:A:b:c:C:d:f:h:i:lm:M:n:N:p:rv")) > 0) {
+ while ((ch = getopt(argc, argv, "a:A:b:c:C:d:D:f:h:i:lm:M:n:N:p:rv")) > 0) {
switch (ch) {
case 'a':
action = optarg;
break;
case 'A':
- if (rcpt_count >= MAX_RCPT) {
+ if (add_rcpt_count >= MAX_RCPT) {
fprintf(stderr, "too many -A options\n");
exit(1);
}
- rcpt_addr[rcpt_count++] = optarg;
+ add_rcpt[add_rcpt_count++] = optarg;
break;
case 'b':
#ifdef SMFIR_REPLBODY
exit(1);
}
break;
+ case 'D':
+ if (del_rcpt_count >= MAX_RCPT) {
+ fprintf(stderr, "too many -D options\n");
+ exit(1);
+ }
+ del_rcpt[del_rcpt_count++] = optarg;
+ break;
case 'f':
#ifdef SMFIR_CHGFROM
if (chg_from) {
#define MASTER_BLANKS " \t\r\n" /* XXX */
argv = argv_split(buf, MASTER_BLANKS);
- if (argv->argc < PC_MASTER_MIN_FIELDS)
+ if (argv->argc < PC_MASTER_MIN_FIELDS) {
+ argv_free(argv); /* Coverity 201311 */
return ("bad field count");
+ }
normalize_options(argv);
masterp->name_space =
concatenate(argv->argv[0], ".", argv->argv[1], (char *) 0);
cp $(PROG) ../../libexec
SMTPD_CHECK_OBJ = smtpd_state.o smtpd_peer.o smtpd_xforward.o smtpd_dsn_fix.o \
- smtpd_resolve.o smtpd_expand.o
+ smtpd_resolve.o smtpd_expand.o smtpd_proxy.o smtpd_haproxy.o
smtpd_token: smtpd_token.c $(LIBS)
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIBS) $(SYSLIBS)
char *var_client_checks = "";
char *var_helo_checks = "";
char *var_mail_checks = "";
+char *var_relay_checks = "";
char *var_rcpt_checks = "";
char *var_etrn_checks = "";
char *var_data_checks = "";
char *var_eod_checks = "";
char *var_relay_domains = "";
+char *var_smtpd_uproxy_proto = "";
+int var_smtpd_uproxy_tmout = 0;
#ifdef USE_TLS
char *var_relay_ccerts = "";
"client_restrictions", &client_restrctions,
"helo_restrictions", &helo_restrctions,
"sender_restrictions", &mail_restrctions,
+ "relay_restrictions", &relay_restrctions,
"recipient_restrictions", &rcpt_restrctions,
"etrn_restrictions", &etrn_restrctions,
0,
#
sender_restrictions permit_mynetworks,reject_unknown_client
client unknown 131.155.210.17
-mail foo@watson.ibm.com
+mail foo@ibm.com
client unknown 168.100.189.13
-mail foo@watson.ibm.com
+mail foo@ibm.com
client foo 123.123.123.123
-mail foo@watson.ibm.com
+mail foo@ibm.com
sender_restrictions reject_unknown_address
-mail foo@watson.ibm.com
+mail foo@ibm.com
mail foo@bad.domain
sender_restrictions hash:./smtpd_check_access
mail bad-sender@any.domain
#
recipient_restrictions permit_mynetworks,reject_unknown_client,check_relay_domains
client unknown 131.155.210.17
-rcpt foo@watson.ibm.com
+rcpt foo@ibm.com
client unknown 168.100.189.13
-rcpt foo@watson.ibm.com
+rcpt foo@ibm.com
client foo 123.123.123.123
-rcpt foo@watson.ibm.com
+rcpt foo@ibm.com
rcpt foo@porcupine.org
recipient_restrictions check_relay_domains
client foo.porcupine.org 168.100.189.13
-rcpt foo@watson.ibm.com
+rcpt foo@ibm.com
rcpt foo@porcupine.org
client foo 123.123.123.123
-rcpt foo@watson.ibm.com
+rcpt foo@ibm.com
rcpt foo@porcupine.org
recipient_restrictions hash:./smtpd_check_access
mail bad-sender@any.domain
#
recipient_restrictions check_relay_domains
client foo 131.155.210.17
-rcpt foo@watson.ibm.com
+rcpt foo@ibm.com
recipient_restrictions check_client_access,hash:./smtpd_check_access,check_relay_domains
client foo 131.155.210.17
rcpt foo@porcupine.org
#
sender_restrictions permit_mynetworks,reject_unknown_client
client unknown 131.155.210.17
-mail foo@watson.ibm.com
+mail foo@ibm.com
client unknown 168.100.189.13
-mail foo@watson.ibm.com
+mail foo@ibm.com
client foo 123.123.123.123
-mail foo@watson.ibm.com
+mail foo@ibm.com
sender_restrictions reject_unknown_address
-mail foo@watson.ibm.com
+mail foo@ibm.com
mail foo@bad.domain
sender_restrictions check_sender_access,hash:./smtpd_check_access
mail bad-sender@any.domain
#
recipient_restrictions permit_mynetworks,reject_unknown_client,check_relay_domains
client unknown 131.155.210.17
-rcpt foo@watson.ibm.com
+rcpt foo@ibm.com
client unknown 168.100.189.13
-rcpt foo@watson.ibm.com
+rcpt foo@ibm.com
client foo 123.123.123.123
-rcpt foo@watson.ibm.com
+rcpt foo@ibm.com
rcpt foo@porcupine.org
recipient_restrictions check_relay_domains
client foo.porcupine.org 168.100.189.13
-rcpt foo@watson.ibm.com
+rcpt foo@ibm.com
rcpt foo@porcupine.org
client foo 123.123.123.123
-rcpt foo@watson.ibm.com
+rcpt foo@ibm.com
rcpt foo@porcupine.org
recipient_restrictions check_recipient_access,hash:./smtpd_check_access
mail bad-sender@any.domain
OK
>>> client unknown 131.155.210.17
OK
->>> mail foo@watson.ibm.com
-./smtpd_check: <queue id>: reject: MAIL from unknown[131.155.210.17]: 450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]; from=<foo@watson.ibm.com> proto=SMTP helo=<123.123.123.123>
+>>> mail foo@ibm.com
+./smtpd_check: <queue id>: reject: MAIL from unknown[131.155.210.17]: 450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]; from=<foo@ibm.com> proto=SMTP helo=<123.123.123.123>
450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client unknown 168.100.189.13
OK
->>> mail foo@watson.ibm.com
+>>> mail foo@ibm.com
OK
>>> client foo 123.123.123.123
OK
->>> mail foo@watson.ibm.com
+>>> mail foo@ibm.com
OK
>>> sender_restrictions reject_unknown_address
OK
->>> mail foo@watson.ibm.com
+>>> mail foo@ibm.com
OK
>>> mail foo@bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 450 4.1.8 <foo@bad.domain>: Sender address rejected: Domain not found; from=<foo@bad.domain> proto=SMTP helo=<123.123.123.123>
OK
>>> client unknown 131.155.210.17
OK
->>> rcpt foo@watson.ibm.com
-./smtpd_check: <queue id>: reject: RCPT from unknown[131.155.210.17]: 450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com> proto=SMTP helo=<123.123.123.123>
+>>> rcpt foo@ibm.com
+./smtpd_check: <queue id>: reject: RCPT from unknown[131.155.210.17]: 450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]; from=<foo@friend.bad.domain> to=<foo@ibm.com> proto=SMTP helo=<123.123.123.123>
450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client unknown 168.100.189.13
OK
->>> rcpt foo@watson.ibm.com
+>>> rcpt foo@ibm.com
OK
>>> client foo 123.123.123.123
OK
->>> rcpt foo@watson.ibm.com
+>>> rcpt foo@ibm.com
./smtpd_check: warning: support for restriction "check_relay_domains" will be removed from Postfix; use "reject_unauth_destination" instead
-./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 5.7.1 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com> proto=SMTP helo=<123.123.123.123>
-554 5.7.1 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
+./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 5.7.1 <foo@ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@ibm.com> proto=SMTP helo=<123.123.123.123>
+554 5.7.1 <foo@ibm.com>: Recipient address rejected: Relay access denied
>>> rcpt foo@porcupine.org
OK
>>> recipient_restrictions check_relay_domains
OK
>>> client foo.porcupine.org 168.100.189.13
OK
->>> rcpt foo@watson.ibm.com
+>>> rcpt foo@ibm.com
OK
>>> rcpt foo@porcupine.org
OK
>>> client foo 123.123.123.123
OK
->>> rcpt foo@watson.ibm.com
-./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 5.7.1 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com> proto=SMTP helo=<123.123.123.123>
-554 5.7.1 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
+>>> rcpt foo@ibm.com
+./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 5.7.1 <foo@ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@ibm.com> proto=SMTP helo=<123.123.123.123>
+554 5.7.1 <foo@ibm.com>: Recipient address rejected: Relay access denied
>>> rcpt foo@porcupine.org
OK
>>> recipient_restrictions hash:./smtpd_check_access
OK
>>> client foo 131.155.210.17
OK
->>> rcpt foo@watson.ibm.com
-./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 554 5.7.1 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com> proto=SMTP helo=<123.123.123.123>
-554 5.7.1 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
+>>> rcpt foo@ibm.com
+./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 554 5.7.1 <foo@ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@ibm.com> proto=SMTP helo=<123.123.123.123>
+554 5.7.1 <foo@ibm.com>: Recipient address rejected: Relay access denied
>>> recipient_restrictions check_client_access,hash:./smtpd_check_access,check_relay_domains
OK
>>> client foo 131.155.210.17
OK
>>> client unknown 131.155.210.17
OK
->>> mail foo@watson.ibm.com
-./smtpd_check: <queue id>: reject: MAIL from unknown[131.155.210.17]: 450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]; from=<foo@watson.ibm.com> proto=SMTP helo=<friend.bad.domain>
+>>> mail foo@ibm.com
+./smtpd_check: <queue id>: reject: MAIL from unknown[131.155.210.17]: 450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]; from=<foo@ibm.com> proto=SMTP helo=<friend.bad.domain>
450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client unknown 168.100.189.13
OK
->>> mail foo@watson.ibm.com
+>>> mail foo@ibm.com
OK
>>> client foo 123.123.123.123
OK
->>> mail foo@watson.ibm.com
+>>> mail foo@ibm.com
OK
>>> sender_restrictions reject_unknown_address
OK
->>> mail foo@watson.ibm.com
+>>> mail foo@ibm.com
OK
>>> mail foo@bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 450 4.1.8 <foo@bad.domain>: Sender address rejected: Domain not found; from=<foo@bad.domain> proto=SMTP helo=<friend.bad.domain>
OK
>>> client unknown 131.155.210.17
OK
->>> rcpt foo@watson.ibm.com
-./smtpd_check: <queue id>: reject: RCPT from unknown[131.155.210.17]: 450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com> proto=SMTP helo=<friend.bad.domain>
+>>> rcpt foo@ibm.com
+./smtpd_check: <queue id>: reject: RCPT from unknown[131.155.210.17]: 450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]; from=<foo@friend.bad.domain> to=<foo@ibm.com> proto=SMTP helo=<friend.bad.domain>
450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client unknown 168.100.189.13
OK
->>> rcpt foo@watson.ibm.com
+>>> rcpt foo@ibm.com
OK
>>> client foo 123.123.123.123
OK
->>> rcpt foo@watson.ibm.com
+>>> rcpt foo@ibm.com
./smtpd_check: warning: support for restriction "check_relay_domains" will be removed from Postfix; use "reject_unauth_destination" instead
-./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 5.7.1 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com> proto=SMTP helo=<friend.bad.domain>
-554 5.7.1 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
+./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 5.7.1 <foo@ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@ibm.com> proto=SMTP helo=<friend.bad.domain>
+554 5.7.1 <foo@ibm.com>: Recipient address rejected: Relay access denied
>>> rcpt foo@porcupine.org
OK
>>> recipient_restrictions check_relay_domains
OK
>>> client foo.porcupine.org 168.100.189.13
OK
->>> rcpt foo@watson.ibm.com
+>>> rcpt foo@ibm.com
OK
>>> rcpt foo@porcupine.org
OK
>>> client foo 123.123.123.123
OK
->>> rcpt foo@watson.ibm.com
-./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 5.7.1 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com> proto=SMTP helo=<friend.bad.domain>
-554 5.7.1 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
+>>> rcpt foo@ibm.com
+./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 5.7.1 <foo@ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@ibm.com> proto=SMTP helo=<friend.bad.domain>
+554 5.7.1 <foo@ibm.com>: Recipient address rejected: Relay access denied
>>> rcpt foo@porcupine.org
OK
>>> recipient_restrictions check_recipient_access,hash:./smtpd_check_access
static void ehlo_response(SINK_STATE *state, const char *args)
{
-#define SKIP(cp, cond) for (/* void */; *cp && (cond); cp++)
+#define SKIP(cp, cond) do { \
+ for (/* void */; *cp && (cond); cp++) \
+ /* void */; \
+ } while (0)
/* EHLO aborts a mail transaction in progress. */
mail_cmd_reset(state);
/* ticket_cb - configure tls session ticket encrypt/decrypt context */
+#if defined(SSL_OP_NO_TICKET) \
+ && !defined(OPENSSL_NO_TLSEXT) \
+ && OPENSSL_VERSION_NUMBER >= 0x0090808fL
+
static int ticket_cb(SSL *con, unsigned char name[], unsigned char iv[],
EVP_CIPHER_CTX * ctx, HMAC_CTX * hctx, int create)
{
return (TLS_TKT_ACCEPT);
}
+#endif
+
/* tls_server_init - initialize the server-side TLS engine */
TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props)
unix_recv_fd unix_send_fd stream_recv_fd stream_send_fd hex_code \
myaddrinfo myaddrinfo4 inet_proto sane_basename format_tv \
valid_utf_8 ip_match base32_code msg_rate_delay netstring \
- vstream
+ vstream timecmp
LIB_DIR = ../../lib
INC_DIR = ../../include
char *cdb_path;
int fd;
+ /*
+ * Let the optimizer worry about eliminating redundant code.
+ */
+#define DICT_CDBQ_OPEN_RETURN(d) { \
+ DICT *__d = (d); \
+ myfree(cdb_path); \
+ return (__d); \
+ } while (0)
+
cdb_path = concatenate(path, CDB_SUFFIX, (char *) 0);
if ((fd = open(cdb_path, O_RDONLY)) < 0)
- return (dict_surrogate(DICT_TYPE_CDB, path, O_RDONLY, dict_flags,
- "open database %s: %m", cdb_path));
+ DICT_CDBQ_OPEN_RETURN(dict_surrogate(DICT_TYPE_CDB, path,
+ O_RDONLY, dict_flags,
+ "open database %s: %m", cdb_path));
dict_cdbq = (DICT_CDBQ *) dict_alloc(DICT_TYPE_CDB,
cdb_path, sizeof(*dict_cdbq));
if (dict_flags & DICT_FLAG_FOLD_FIX)
dict_cdbq->dict.fold_buf = vstring_alloc(10);
- myfree(cdb_path);
- return (&dict_cdbq->dict);
+ DICT_CDBQ_OPEN_RETURN(DICT_DEBUG (&dict_cdbq->dict));
}
/* dict_cdbm_update - add database entry, create mode */
int fd;
struct stat st0, st1;
+ /*
+ * Let the optimizer worry about eliminating redundant code.
+ */
+#define DICT_CDBM_OPEN_RETURN(d) { \
+ DICT *__d = (d); \
+ if (cdb_path) \
+ myfree(cdb_path); \
+ if (tmp_path) \
+ myfree(tmp_path); \
+ return (__d); \
+ } while (0)
+
cdb_path = concatenate(path, CDB_SUFFIX, (char *) 0);
tmp_path = concatenate(path, CDB_TMP_SUFFIX, (char *) 0);
*/
for (;;) {
if ((fd = open(tmp_path, O_RDWR | O_CREAT, 0644)) < 0)
- return (dict_surrogate(DICT_TYPE_CDB, path, O_RDWR, dict_flags,
- "open database %s: %m", tmp_path));
+ DICT_CDBM_OPEN_RETURN(dict_surrogate(DICT_TYPE_CDB, path,
+ O_RDWR, dict_flags,
+ "open database %s: %m",
+ tmp_path));
if (fstat(fd, &st0) < 0)
msg_fatal("fstat(%s): %m", tmp_path);
dict_cdbm->dict.update = dict_cdbm_update;
dict_cdbm->cdb_path = cdb_path;
dict_cdbm->tmp_path = tmp_path;
+ cdb_path = tmp_path = 0; /* DICT_CDBM_OPEN_RETURN() */
dict_cdbm->dict.owner.uid = st1.st_uid;
dict_cdbm->dict.owner.status = (st1.st_uid != 0);
close_on_exec(fd, CLOSE_ON_EXEC);
if (dict_flags & DICT_FLAG_FOLD_FIX)
dict_cdbm->dict.fold_buf = vstring_alloc(10);
- return (&dict_cdbm->dict);
+ DICT_CDBM_OPEN_RETURN(DICT_DEBUG (&dict_cdbm->dict));
}
/* dict_cdb_open - open data base for query mode or create mode */
DICT *dict_cidr_open(const char *mapname, int open_flags, int dict_flags)
{
DICT_CIDR *dict_cidr;
- VSTREAM *map_fp;
+ VSTREAM *map_fp = 0;
struct stat st;
- VSTRING *line_buffer;
- VSTRING *why;
+ VSTRING *line_buffer = 0;
+ VSTRING *why = 0;
DICT_CIDR_ENTRY *rule;
DICT_CIDR_ENTRY *last_rule = 0;
int lineno = 0;
+ /*
+ * Let the optimizer worry about eliminating redundant code.
+ */
+#define DICT_CIDR_OPEN_RETURN(d) do { \
+ DICT *__d = (d); \
+ if (map_fp != 0 && vstream_fclose(map_fp)) \
+ msg_fatal("cidr map %s: read error: %m", mapname); \
+ if (line_buffer != 0) \
+ vstring_free(line_buffer); \
+ if (why != 0) \
+ vstring_free(why); \
+ return (__d); \
+ } while (0)
+
/*
* Sanity checks.
*/
if (open_flags != O_RDONLY)
- return (dict_surrogate(DICT_TYPE_CIDR, mapname, open_flags, dict_flags,
- "%s:%s map requires O_RDONLY access mode",
- DICT_TYPE_CIDR, mapname));
+ DICT_CIDR_OPEN_RETURN(dict_surrogate(DICT_TYPE_CIDR, mapname,
+ open_flags, dict_flags,
+ "%s:%s map requires O_RDONLY access mode",
+ DICT_TYPE_CIDR, mapname));
/*
* Open the configuration file.
*/
if ((map_fp = vstream_fopen(mapname, O_RDONLY, 0)) == 0)
- return (dict_surrogate(DICT_TYPE_CIDR, mapname, open_flags, dict_flags,
- "open %s: %m", mapname));
+ DICT_CIDR_OPEN_RETURN(dict_surrogate(DICT_TYPE_CIDR, mapname,
+ open_flags, dict_flags,
+ "open %s: %m", mapname));
if (fstat(vstream_fileno(map_fp), &st) < 0)
msg_fatal("fstat %s: %m", mapname);
- /*
- * No early returns without memory leaks.
- */
line_buffer = vstring_alloc(100);
why = vstring_alloc(100);
last_rule = rule;
}
- /*
- * Clean up.
- */
- if (vstream_fclose(map_fp))
- msg_fatal("cidr map %s: read error: %m", mapname);
- vstring_free(line_buffer);
- vstring_free(why);
-
- return (DICT_DEBUG (&dict_cidr->dict));
+ DICT_CIDR_OPEN_RETURN(DICT_DEBUG (&dict_cidr->dict));
}
DICT_DBM *dict_dbm;
struct stat st;
DBM *dbm;
- char *dbm_path;
+ char *dbm_path = 0;
int lock_fd;
+ /*
+ * Let the optimizer worry about eliminating redundant code.
+ */
+#define DICT_DBM_OPEN_RETURN(d) { \
+ DICT *__d = (d); \
+ if (dbm_path != 0) \
+ myfree(dbm_path); \
+ return (__d); \
+ } while (0)
+
/*
* Note: DICT_FLAG_LOCK is used only by programs that do fine-grained (in
* the time domain) locking while accessing individual database records.
if (dict_flags & DICT_FLAG_LOCK) {
dbm_path = concatenate(path, ".dir", (char *) 0);
if ((lock_fd = open(dbm_path, open_flags, 0644)) < 0)
- return (dict_surrogate(DICT_TYPE_DBM, path, open_flags, dict_flags,
- "open database %s: %m", dbm_path));
+ DICT_DBM_OPEN_RETURN(dict_surrogate(DICT_TYPE_DBM, path,
+ open_flags, dict_flags,
+ "open database %s: %m",
+ dbm_path));
if (myflock(lock_fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) < 0)
msg_fatal("shared-lock database %s for open: %m", dbm_path);
}
* XXX SunOS 5.x has no const in dbm_open() prototype.
*/
if ((dbm = dbm_open((char *) path, open_flags, 0644)) == 0)
- return (dict_surrogate(DICT_TYPE_DBM, path, open_flags, dict_flags,
- "open database %s.{dir,pag}: %m", path));
+ DICT_DBM_OPEN_RETURN(dict_surrogate(DICT_TYPE_DBM, path,
+ open_flags, dict_flags,
+ "open database %s.{dir,pag}: %m",
+ path));
if (dict_flags & DICT_FLAG_LOCK) {
if (myflock(lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
dict_dbm->key_buf = 0;
dict_dbm->val_buf = 0;
- if ((dict_flags & DICT_FLAG_LOCK))
- myfree(dbm_path);
-
- return (DICT_DEBUG (&dict_dbm->dict));
+ DICT_DBM_OPEN_RETURN(DICT_DEBUG (&dict_dbm->dict));
}
#endif
int mdb_flags, slmdb_flags, status;
int db_fd;
+ /*
+ * Let the optimizer worry about eliminating redundant code.
+ */
+#define DICT_LMDB_OPEN_RETURN(d) { \
+ DICT *__d = (d); \
+ myfree(mdb_path); \
+ return (__d); \
+ } while (0)
+
mdb_path = concatenate(path, "." DICT_TYPE_LMDB, (char *) 0);
/*
* 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 do not need this workaround: those databases are maintained
- * by Postfix daemon processes, and are accessible only by the postfix
- * user.
+ * databases are maintained by Postfix daemon processes, and 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)
mdb_flags |= MDB_WRITEMAP;
+#endif
/*
* Gracefully handle most database open errors.
slmdb_flags)) != 0) {
dict = dict_surrogate(DICT_TYPE_LMDB, path, open_flags, dict_flags,
"open database %s: %s", mdb_path, mdb_strerror(status));
- myfree(mdb_path);
- return (dict);
+ DICT_LMDB_OPEN_RETURN(dict);
}
/*
*/
dict_lmdb->slmdb = slmdb;
- myfree(mdb_path);
-
- return (DICT_DEBUG (&dict_lmdb->dict));
+ DICT_LMDB_OPEN_RETURN(DICT_DEBUG (&dict_lmdb->dict));
}
#endif
DICT *dict_pcre_open(const char *mapname, int open_flags, int dict_flags)
{
DICT_PCRE *dict_pcre;
- VSTREAM *map_fp;
+ VSTREAM *map_fp = 0;
struct stat st;
- VSTRING *line_buffer;
+ VSTRING *line_buffer = 0;
DICT_PCRE_RULE *last_rule = 0;
DICT_PCRE_RULE *rule;
int lineno = 0;
int nesting = 0;
char *p;
+ /*
+ * Let the optimizer worry about eliminating redundant code.
+ */
+#define DICT_PCRE_OPEN_RETURN(d) { \
+ DICT *__d = (d); \
+ if (map_fp != 0) \
+ vstream_fclose(map_fp); \
+ if (line_buffer != 0) \
+ vstring_free(line_buffer); \
+ return (__d); \
+ } while (0)
+
/*
* Sanity checks.
*/
if (open_flags != O_RDONLY)
- return (dict_surrogate(DICT_TYPE_PCRE, mapname, open_flags, dict_flags,
- "%s:%s map requires O_RDONLY access mode",
- DICT_TYPE_PCRE, mapname));
+ DICT_PCRE_OPEN_RETURN(dict_surrogate(DICT_TYPE_PCRE, mapname,
+ open_flags, dict_flags,
+ "%s:%s map requires O_RDONLY access mode",
+ DICT_TYPE_PCRE, mapname));
/*
* Open the configuration file.
*/
if ((map_fp = vstream_fopen(mapname, O_RDONLY, 0)) == 0)
- return (dict_surrogate(DICT_TYPE_PCRE, mapname, open_flags, dict_flags,
- "open %s: %m", mapname));
+ DICT_PCRE_OPEN_RETURN(dict_surrogate(DICT_TYPE_PCRE, mapname,
+ open_flags, dict_flags,
+ "open %s: %m", mapname));
if (fstat(vstream_fileno(map_fp), &st) < 0)
msg_fatal("fstat %s: %m", mapname);
msg_warn("pcre map %s, line %d: more IFs than ENDIFs",
mapname, lineno);
- vstring_free(line_buffer);
- vstream_fclose(map_fp);
-
- return (DICT_DEBUG (&dict_pcre->dict));
+ DICT_PCRE_OPEN_RETURN(DICT_DEBUG (&dict_pcre->dict));
}
#endif /* HAS_PCRE */
DICT *dict_regexp_open(const char *mapname, int open_flags, int dict_flags)
{
DICT_REGEXP *dict_regexp;
- VSTREAM *map_fp;
+ VSTREAM *map_fp = 0;
struct stat st;
- VSTRING *line_buffer;
+ VSTRING *line_buffer = 0;
DICT_REGEXP_RULE *rule;
DICT_REGEXP_RULE *last_rule = 0;
int lineno = 0;
int nesting = 0;
char *p;
+ /*
+ * Let the optimizer worry about eliminating redundant code.
+ */
+#define DICT_REGEXP_OPEN_RETURN(d) { \
+ DICT *__d = (d); \
+ if (line_buffer != 0) \
+ vstring_free(line_buffer); \
+ if (map_fp != 0) \
+ vstream_fclose(map_fp); \
+ return (__d); \
+ } while (0)
+
/*
* Sanity checks.
*/
if (open_flags != O_RDONLY)
- return (dict_surrogate(DICT_TYPE_REGEXP, mapname, open_flags, dict_flags,
- "%s:%s map requires O_RDONLY access mode",
- DICT_TYPE_REGEXP, mapname));
+ DICT_REGEXP_OPEN_RETURN(dict_surrogate(DICT_TYPE_REGEXP,
+ mapname, open_flags, dict_flags,
+ "%s:%s map requires O_RDONLY access mode",
+ DICT_TYPE_REGEXP, mapname));
/*
* Open the configuration file.
*/
if ((map_fp = vstream_fopen(mapname, O_RDONLY, 0)) == 0)
- return (dict_surrogate(DICT_TYPE_REGEXP, mapname, open_flags, dict_flags,
- "open %s: %m", mapname));
+ DICT_REGEXP_OPEN_RETURN(dict_surrogate(DICT_TYPE_REGEXP, mapname,
+ open_flags, dict_flags,
+ "open %s: %m", mapname));
if (fstat(vstream_fileno(map_fp), &st) < 0)
msg_fatal("fstat %s: %m", mapname);
dict_regexp->pmatch =
(regmatch_t *) mymalloc(sizeof(regmatch_t) * (max_sub + 1));
- /*
- * Clean up.
- */
- vstring_free(line_buffer);
- vstream_fclose(map_fp);
-
- return (DICT_DEBUG (&dict_regexp->dict));
+ DICT_REGEXP_OPEN_RETURN(DICT_DEBUG (&dict_regexp->dict));
}
#endif
DICT *dict_sockmap_open(const char *mapname, int open_flags, int dict_flags)
{
DICT_SOCKMAP *dp;
- char *saved_name;
+ char *saved_name = 0;
char *sockmap;
DICT_SOCKMAP_REFC_HANDLE *ref_handle;
HTABLE_INFO *client_info;
+ /*
+ * Let the optimizer worry about eliminating redundant code.
+ */
+#define DICT_SOCKMAP_OPEN_RETURN(d) { \
+ DICT *__d = (d); \
+ if (saved_name != 0) \
+ myfree(saved_name); \
+ return (__d); \
+ } while (0)
+
/*
* Sanity checks.
*/
if (open_flags != O_RDONLY)
- return (dict_surrogate(DICT_TYPE_SOCKMAP, mapname,
- open_flags, dict_flags,
- "%s:%s map requires O_RDONLY access mode",
- DICT_TYPE_SOCKMAP, mapname));
+ DICT_SOCKMAP_OPEN_RETURN(dict_surrogate(DICT_TYPE_SOCKMAP, mapname,
+ open_flags, dict_flags,
+ "%s:%s map requires O_RDONLY access mode",
+ DICT_TYPE_SOCKMAP, mapname));
if (dict_flags & DICT_FLAG_NO_UNAUTH)
- return (dict_surrogate(DICT_TYPE_SOCKMAP, mapname,
- open_flags, dict_flags,
+ DICT_SOCKMAP_OPEN_RETURN(dict_surrogate(DICT_TYPE_SOCKMAP, mapname,
+ open_flags, dict_flags,
"%s:%s map is not allowed for security-sensitive data",
- DICT_TYPE_SOCKMAP, mapname));
+ DICT_TYPE_SOCKMAP, mapname));
/*
* Separate the socketmap name from the socketmap server name.
*/
saved_name = mystrdup(mapname);
if ((sockmap = split_at_right(saved_name, ':')) == 0)
- return (dict_surrogate(DICT_TYPE_SOCKMAP, mapname,
- open_flags, dict_flags,
- "%s requires server:socketmap argument",
- DICT_TYPE_SOCKMAP));
+ DICT_SOCKMAP_OPEN_RETURN(dict_surrogate(DICT_TYPE_SOCKMAP, mapname,
+ open_flags, dict_flags,
+ "%s requires server:socketmap argument",
+ DICT_TYPE_SOCKMAP));
/*
* Use one reference-counted client handle for all socketmaps with the
/* Don't look up parent domains or network superblocks. */
dp->dict.flags = dict_flags | DICT_FLAG_PATTERN;
- /*
- * Clean up.
- */
- myfree(saved_name);
-
- return (DICT_DEBUG (&dp->dict));
+ DICT_SOCKMAP_OPEN_RETURN(DICT_DEBUG (&dp->dict));
}
DICT *dict_thash_open(const char *path, int open_flags, int dict_flags)
{
DICT_THASH *dict_thash;
- VSTREAM *fp;
+ VSTREAM *fp = 0;
struct stat st;
time_t before;
time_t after;
HTABLE *table;
HTABLE_INFO *ht;
+ /*
+ * Let the optimizer worry about eliminating redundant code.
+ */
+#define DICT_THASH_OPEN_RETURN(d) { \
+ DICT *__d = (d); \
+ if (fp != 0) \
+ vstream_fclose(fp); \
+ if (line_buffer != 0) \
+ vstring_free(line_buffer); \
+ return (__d); \
+ } while (0)
+
/*
* Sanity checks.
*/
if (open_flags != O_RDONLY)
- return (dict_surrogate(DICT_TYPE_THASH, path, open_flags, dict_flags,
- "%s:%s map requires O_RDONLY access mode",
- DICT_TYPE_THASH, path));
+ DICT_THASH_OPEN_RETURN(dict_surrogate(DICT_TYPE_THASH, path,
+ open_flags, dict_flags,
+ "%s:%s map requires O_RDONLY access mode",
+ DICT_TYPE_THASH, path));
/*
* Read the flat text file into in-memory hash. Read the file again if it
*/
for (before = time((time_t *) 0); /* see below */ ; before = after) {
if ((fp = vstream_fopen(path, open_flags, 0644)) == 0) {
- return (dict_surrogate(DICT_TYPE_THASH, path, open_flags, dict_flags,
- "open database %s: %m", path));
+ DICT_THASH_OPEN_RETURN(dict_surrogate(DICT_TYPE_THASH, path,
+ open_flags, dict_flags,
+ "open database %s: %m", path));
}
if (line_buffer == 0)
line_buffer = vstring_alloc(100);
msg_fatal("fstat %s: %m", path);
if (vstream_fclose(fp))
msg_fatal("read %s: %m", path);
+ fp = 0; /* DICT_THASH_OPEN_RETURN() */
after = time((time_t *) 0);
if (st.st_mtime < before - 1 || st.st_mtime > after)
break;
msg_info("pausing to let file %s cool down", path);
doze(300000);
}
- vstring_free(line_buffer);
/*
* Create the in-memory table.
dict_thash->dict.owner.uid = st.st_uid;
dict_thash->dict.owner.status = (st.st_uid != 0);
- return (DICT_DEBUG (&dict_thash->dict));
+ DICT_THASH_OPEN_RETURN(DICT_DEBUG (&dict_thash->dict));
}
int level;
int status = 0;
-#define SKIP(start, var, cond) \
- for (var = start; *var && (cond); var++);
+#define SKIP(start, var, cond) do { \
+ for (var = start; *var && (cond); var++) \
+ /* void */; \
+ } while (0)
if (msg_verbose > 1)
msg_info("%s: %s", myname, value);
/*
* Ugly macros to make complex expressions less unreadable.
*/
-#define SKIP(start, var, cond) \
- for (var = start; *var && (cond); var++);
+#define SKIP(start, var, cond) do { \
+ for (var = start; *var && (cond); var++) \
+ /* void */; \
+ } while (0)
-#define TRIM(s) { \
+#define TRIM(s) do { \
char *p; \
- for (p = (s) + strlen(s); p > (s) && ISSPACE(p[-1]); p--); \
+ for (p = (s) + strlen(s); p > (s) && ISSPACE(p[-1]); p--) \
+ /* void */; \
*p = 0; \
- }
+ } while (0)
SKIP(buf, np, ISSPACE(*np)); /* find name begin */
if (*np == 0)
unsigned long_flag; /* long or plain integer */
int ch;
char *s;
+ int saved_errno = errno; /* VBUF_SPACE() may clobber it */
/*
* Assume that format strings are short.
VBUF_SKIP(bp);
break;
case 'm':
- VBUF_STRCAT(bp, strerror(errno));
+ VBUF_STRCAT(bp, strerror(saved_errno));
break;
case 'p':
if (VBUF_SPACE(bp, (width > prec ? width : prec) + PTR_SPACE))