-Optional list of relay hosts for SMTP destinations that can't be
-found or that are unreachable. With Postfix 2.2 and earlier this
-parameter is called fallback_relay.
-
-
-By default, mail is returned to the sender when a destination is
-not found, and delivery is deferred when a destination is unreachable.
-
+ Optional list of relay destinations that will be used when an
+SMTP destination is not found, or when delivery fails due to a
+non-permanent error. With Postfix 2.2 and earlier this parameter
+is called fallback_relay.
+
+ With bulk email deliveries, it can be beneficial to run the
fallback relay MTA on the same host, so that it can reuse the sender
diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5
index 58cfe3648..4ad946652 100644
--- a/postfix/man/man5/postconf.5
+++ b/postfix/man/man5/postconf.5
@@ -7382,12 +7382,14 @@ send all their email to a dedicated mailhub.
This feature is available in Postfix 2.2 and later. With
Postfix 2.3 and later use smtp_tls_security_level instead.
.SH smtp_fallback_relay (default: $fallback_relay)
-Optional list of relay hosts for SMTP destinations that can't be
-found or that are unreachable. With Postfix 2.2 and earlier this
-parameter is called fallback_relay.
-.PP
-By default, mail is returned to the sender when a destination is
-not found, and delivery is deferred when a destination is unreachable.
+Optional list of relay destinations that will be used when an
+SMTP destination is not found, or when delivery fails due to a
+non\-permanent error. With Postfix 2.2 and earlier this parameter
+is called fallback_relay.
+.PP
+By default, smtp_fallback_relay is empty, mail is returned to
+the sender when a destination is not found, and delivery is deferred
+after it fails due to a non\-permanent error.
.PP
With bulk email deliveries, it can be beneficial to run the
fallback relay MTA on the same host, so that it can reuse the sender
diff --git a/postfix/proto/STANDARD_CONFIGURATION_README.html b/postfix/proto/STANDARD_CONFIGURATION_README.html
index b4f4efcf5..3008cfda6 100644
--- a/postfix/proto/STANDARD_CONFIGURATION_README.html
+++ b/postfix/proto/STANDARD_CONFIGURATION_README.html
@@ -377,7 +377,7 @@ is the real purpose of the firewall email function.
17 . . .
18
19 /etc/postfix/transport:
-20 example.com smtp:[inside-gateway.example.com]
+20 example.com relay:[inside-gateway.example.com]
@@ -399,7 +399,12 @@ wild-card in the relay_recipients table.
Lines 12, 19-20: Route mail for "example.com" to the inside
gateway machine. The [] forces Postfix to do no MX lookup.
-
+This uses the "relay" delivery transport (a copy of the default
+"smtp" delivery transport) to forward inbound mail. This can improve
+performance of deliveries to internal domains because they will
+compete for SMTP clients from the "relay" delivery transport, instead
+of competing with other SMTP deliveries for SMTP clients from the
+default "smtp" delivery transport.
diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto
index 9b5a550d4..7dfb60548 100644
--- a/postfix/proto/postconf.proto
+++ b/postfix/proto/postconf.proto
@@ -1482,15 +1482,14 @@ export_environment = TZ PATH=/bin:/usr/bin
%PARAM smtp_fallback_relay $fallback_relay
-
-Optional list of relay hosts for SMTP destinations that can't be
-found or that are unreachable. With Postfix 2.2 and earlier this
-parameter is called fallback_relay.
-
-
-By default, mail is returned to the sender when a destination is
-not found, and delivery is deferred when a destination is unreachable.
-
+ Optional list of relay destinations that will be used when an
+SMTP destination is not found, or when delivery fails due to a
+non-permanent error. With Postfix 2.2 and earlier this parameter
+is called fallback_relay.
+
+ By default, smtp_fallback_relay is empty, mail is returned to
+the sender when a destination is not found, and delivery is deferred
+after it fails due to a non-permanent error.
With bulk email deliveries, it can be beneficial to run the
fallback relay MTA on the same host, so that it can reuse the sender
diff --git a/postfix/proto/stop.double-cc b/postfix/proto/stop.double-cc
index 1e9b3de22..6bdd97f3a 100644
--- a/postfix/proto/stop.double-cc
+++ b/postfix/proto/stop.double-cc
@@ -328,3 +328,4 @@ more more useful and more consistent
XXX XXX
int compar DNS_RR DNS_RR
USE_FNV_32BIT USE_FNV_32BIT
+void void cleanup_milter_receive state count
diff --git a/postfix/proto/stop.spell-cc b/postfix/proto/stop.spell-cc
index 916629853..10f22509a 100644
--- a/postfix/proto/stop.spell-cc
+++ b/postfix/proto/stop.spell-cc
@@ -1782,3 +1782,5 @@ softwareengineering
stackexchange
stdint
Noll
+deinit
+reinit
diff --git a/postfix/src/cleanup/cleanup.h b/postfix/src/cleanup/cleanup.h
index 9c557119f..baecaadb7 100644
--- a/postfix/src/cleanup/cleanup.h
+++ b/postfix/src/cleanup/cleanup.h
@@ -117,8 +117,6 @@ typedef struct CLEANUP_STATE {
VSTRING *milter_ext_from; /* externalized sender */
VSTRING *milter_ext_rcpt; /* externalized recipient */
VSTRING *milter_err_text; /* milter call-back reply */
- HBC_CHECKS *milter_hbc_checks; /* Milter header checks */
- VSTRING *milter_hbc_reply; /* Milter header checks reply */
VSTRING *milter_dsn_buf; /* Milter DSN parsing buffer */
/*
@@ -170,7 +168,6 @@ extern VSTRING *cleanup_strip_chars;
/*
* Milters.
*/
-extern MAPS *cleanup_milt_head_checks;
extern MILTERS *cleanup_milters;
/*
@@ -319,6 +316,7 @@ extern int cleanup_bounce(CLEANUP_STATE *);
/*
* cleanup_milter.c.
*/
+extern void cleanup_milter_header_checks_init(void);
extern void cleanup_milter_receive(CLEANUP_STATE *, int);
extern void cleanup_milter_inspect(CLEANUP_STATE *, MILTERS *);
extern void cleanup_milter_emul_mail(CLEANUP_STATE *, MILTERS *, const char *);
diff --git a/postfix/src/cleanup/cleanup_init.c b/postfix/src/cleanup/cleanup_init.c
index ffe40ba16..8c43a0212 100644
--- a/postfix/src/cleanup/cleanup_init.c
+++ b/postfix/src/cleanup/cleanup_init.c
@@ -278,7 +278,6 @@ int cleanup_ext_prop_mask;
/*
* Milter support.
*/
-MAPS *cleanup_milt_head_checks;
MILTERS *cleanup_milters;
/*
@@ -412,10 +411,6 @@ void cleanup_pre_jail(char *unused_name, char **unused_argv)
maps_create(VAR_RCPT_BCC_MAPS, var_rcpt_bcc_maps,
DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX
| DICT_FLAG_UTF8_REQUEST);
- if (*var_milt_head_checks)
- cleanup_milt_head_checks =
- maps_create(VAR_MILT_HEAD_CHECKS, var_milt_head_checks,
- DICT_FLAG_LOCK);
if (*var_cleanup_milters)
cleanup_milters = milter_create(var_cleanup_milters,
var_milt_conn_time,
@@ -432,6 +427,8 @@ void cleanup_pre_jail(char *unused_name, char **unused_argv)
var_milt_eod_macros,
var_milt_unk_macros,
var_milt_macro_deflts);
+ if (*var_milt_head_checks)
+ cleanup_milter_header_checks_init();
flush_init();
}
diff --git a/postfix/src/cleanup/cleanup_milter.c b/postfix/src/cleanup/cleanup_milter.c
index 6da61575c..673b59c3c 100644
--- a/postfix/src/cleanup/cleanup_milter.c
+++ b/postfix/src/cleanup/cleanup_milter.c
@@ -6,6 +6,8 @@
/* SYNOPSIS
/* #include
/*
+/* void cleanup_milter_header_checks_init(void)
+/*
/* void cleanup_milter_receive(state, count)
/* CLEANUP_STATE *state;
/* int count;
@@ -32,6 +34,9 @@
/* filter (milter) applications, including in-place queue file
/* modification.
/*
+/* cleanup_milter_header_checks_init() does pre-jail
+/* initializations.
+/*
/* cleanup_milter_receive() receives mail filter definitions,
/* typically from an smtpd(8) server process, and registers
/* local call-back functions for macro expansion and for queue
@@ -222,6 +227,8 @@
/*#define msg_verbose 2*/
+static HBC_CHECKS *cleanup_milter_hbc_checks;
+static VSTRING *cleanup_milter_hbc_reply;
static void cleanup_milter_set_error(CLEANUP_STATE *, int);
static const char *cleanup_add_rcpt_par(void *, const char *, const char *);
@@ -345,9 +352,9 @@ static char *cleanup_milter_hbc_extend(void *context, const char *command,
state->errs |= CLEANUP_STAT_CONT;
state->flags &= ~CLEANUP_FLAG_FILTER_ALL;
cleanup_milter_hbc_log(context, "reject", where, buf, state->reason);
- vstring_sprintf(state->milter_hbc_reply, "%d %s",
+ vstring_sprintf(cleanup_milter_hbc_reply, "%d %s",
detail->smtp, state->reason);
- STR(state->milter_hbc_reply)[0] = *state->reason;
+ STR(cleanup_milter_hbc_reply)[0] = *state->reason;
return ((char *) buf);
}
if (STREQUAL(command, "FILTER", cmd_len)) {
@@ -368,7 +375,7 @@ static char *cleanup_milter_hbc_extend(void *context, const char *command,
}
if (STREQUAL(command, "DISCARD", cmd_len)) {
cleanup_milter_hbc_log(context, "discard", where, buf, optional_text);
- vstring_strcpy(state->milter_hbc_reply, "D");
+ vstring_strcpy(cleanup_milter_hbc_reply, "D");
state->flags |= CLEANUP_FLAG_DISCARD;
state->flags &= ~CLEANUP_FLAG_FILTER_ALL;
return ((char *) buf);
@@ -409,7 +416,7 @@ static int cleanup_milter_header_checks(CLEANUP_STATE *state, VSTRING *buf)
* end-of-message stage, therefore all the header operations are relative
* to the primary message header.
*/
- ret = hbc_header_checks((void *) state, state->milter_hbc_checks,
+ ret = hbc_header_checks((void *) state, cleanup_milter_hbc_checks,
MIME_HDR_PRIMARY, (HEADER_OPTS *) 0,
buf, (off_t) 0);
if (ret == 0) {
@@ -504,10 +511,14 @@ static void cleanup_milter_hbc_add_meta_records(CLEANUP_STATE *state)
/* cleanup_milter_header_checks_init - initialize post-Milter header checks */
-static void cleanup_milter_header_checks_init(CLEANUP_STATE *state)
+void cleanup_milter_header_checks_init(void)
{
-#define NO_NESTED_HDR_MAPS ((MAPS *) 0)
-#define NO_MIME_HDR_MAPS ((MAPS *) 0)
+ static const char myname[] = "cleanup_milter_header_checks_init";
+
+#define NO_NESTED_HDR_NAME ""
+#define NO_NESTED_HDR_VALUE ""
+#define NO_MIME_HDR_NAME ""
+#define NO_MIME_HDR_VALUE ""
static /* XXX not const */ HBC_CALL_BACKS call_backs = {
cleanup_milter_hbc_log,
@@ -515,12 +526,47 @@ static void cleanup_milter_header_checks_init(CLEANUP_STATE *state)
cleanup_milter_hbc_extend,
};
- state->milter_hbc_checks =
- hbc_header_checks_create(cleanup_milt_head_checks,
- NO_MIME_HDR_MAPS,
- NO_NESTED_HDR_MAPS,
+ if (*var_milt_head_checks == 0)
+ msg_panic("%s: %s is empty", myname, VAR_MILT_HEAD_CHECKS);
+
+ if (cleanup_milter_hbc_checks)
+ msg_panic("%s: cleanup_milter_hbc_checks is not null", myname);
+ cleanup_milter_hbc_checks =
+ hbc_header_checks_create(VAR_MILT_HEAD_CHECKS, var_milt_head_checks,
+ NO_MIME_HDR_NAME, NO_MIME_HDR_VALUE,
+ NO_NESTED_HDR_NAME, NO_NESTED_HDR_VALUE,
&call_backs);
- state->milter_hbc_reply = vstring_alloc(100);
+
+ if (cleanup_milter_hbc_reply)
+ msg_panic("%s: cleanup_milter_hbc_reply is not null", myname);
+ cleanup_milter_hbc_reply = vstring_alloc(100);
+}
+
+#ifdef TEST
+
+/* cleanup_milter_header_checks_deinit - undo cleanup_milter_header_checks_init */
+
+static void cleanup_milter_header_checks_deinit(void)
+{
+ static const char myname[] = "cleanup_milter_header_checks_deinit";
+
+ if (cleanup_milter_hbc_checks == 0)
+ msg_panic("%s: cleanup_milter_hbc_checks is null", myname);
+ hbc_header_checks_free(cleanup_milter_hbc_checks);
+ cleanup_milter_hbc_checks = 0;
+
+ if (cleanup_milter_hbc_reply == 0)
+ msg_panic("%s: cleanup_milter_hbc_reply is null", myname);
+ vstring_free(cleanup_milter_hbc_reply);
+ cleanup_milter_hbc_reply = 0;
+}
+
+#endif
+
+/* cleanup_milter_header_checks_reinit - re-init post-Milter header checks */
+
+static void cleanup_milter_header_checks_reinit(CLEANUP_STATE *state)
+{
if (state->filter)
myfree(state->filter);
state->filter = 0;
@@ -533,12 +579,6 @@ static void cleanup_milter_header_checks_init(CLEANUP_STATE *state)
static void cleanup_milter_hbc_finish(CLEANUP_STATE *state)
{
- if (state->milter_hbc_checks)
- hbc_header_checks_free(state->milter_hbc_checks);
- state->milter_hbc_checks = 0;
- if (state->milter_hbc_reply)
- vstring_free(state->milter_hbc_reply);
- state->milter_hbc_reply = 0;
if (CLEANUP_OUT_OK(state)
&& !CLEANUP_MILTER_REJECTING_OR_DISCARDING_MESSAGE(state)
&& (state->filter || state->redirect))
@@ -642,7 +682,7 @@ static const char *cleanup_add_header(void *context, const char *name,
*/
buf = vstring_alloc(100);
vstring_sprintf(buf, "%s:%s%s", name, space, value);
- if (state->milter_hbc_checks) {
+ if (cleanup_milter_hbc_checks) {
if (cleanup_milter_header_checks(state, buf) == 0
|| (state->flags & CLEANUP_FLAG_DISCARD)) {
vstring_free(buf);
@@ -705,8 +745,8 @@ static const char *cleanup_add_header(void *context, const char *name,
* In case of error while doing record output.
*/
return (CLEANUP_OUT_OK(state) == 0 ? cleanup_milter_error(state, 0) :
- state->milter_hbc_reply && LEN(state->milter_hbc_reply) ?
- STR(state->milter_hbc_reply) : 0);
+ cleanup_milter_hbc_reply && LEN(cleanup_milter_hbc_reply) ?
+ STR(cleanup_milter_hbc_reply) : 0);
/*
* Note: state->append_hdr_pt_target never changes.
@@ -1030,7 +1070,7 @@ static const char *cleanup_patch_header(CLEANUP_STATE *state,
* be dropped.
*/
vstring_sprintf(buf, "%s:%s%s", new_hdr_name, hdr_space, new_hdr_value);
- if (state->milter_hbc_checks
+ if (cleanup_milter_hbc_checks
&& cleanup_milter_header_checks(state, buf) == 0)
CLEANUP_PATCH_HEADER_RETURN(0);
@@ -1099,8 +1139,8 @@ static const char *cleanup_patch_header(CLEANUP_STATE *state,
*/
CLEANUP_PATCH_HEADER_RETURN(
CLEANUP_OUT_OK(state) == 0 ? cleanup_milter_error(state, 0) :
- state->milter_hbc_reply && LEN(state->milter_hbc_reply) ?
- STR(state->milter_hbc_reply) : 0);
+ cleanup_milter_hbc_reply && LEN(cleanup_milter_hbc_reply) ?
+ STR(cleanup_milter_hbc_reply) : 0);
/*
* Note: state->append_hdr_pt_target never changes.
@@ -1982,8 +2022,8 @@ static const char *cleanup_milter_apply(CLEANUP_STATE *state, const char *event,
* Don't process our own milter_header/body checks replies. See comments
* in cleanup_milter_hbc_extend().
*/
- if (state->milter_hbc_reply &&
- strcmp(resp, STR(state->milter_hbc_reply)) == 0)
+ if (cleanup_milter_hbc_reply &&
+ strcmp(resp, STR(cleanup_milter_hbc_reply)) == 0)
return (0);
/*
@@ -2148,8 +2188,8 @@ void cleanup_milter_inspect(CLEANUP_STATE *state, MILTERS *milters)
/*
* Prologue: prepare for Milter header/body checks.
*/
- if (cleanup_milt_head_checks)
- cleanup_milter_header_checks_init(state);
+ if (*var_milt_head_checks)
+ cleanup_milter_header_checks_reinit(state);
/*
* Process mail filter replies. The reply format is verified by the mail
@@ -2162,7 +2202,7 @@ void cleanup_milter_inspect(CLEANUP_STATE *state, MILTERS *milters)
/*
* Epilogue: finalize Milter header/body checks.
*/
- if (cleanup_milt_head_checks)
+ if (*var_milt_head_checks)
cleanup_milter_hbc_finish(state);
if (msg_verbose)
@@ -2319,7 +2359,6 @@ char *var_milt_daemon_name = "host.example.com";
char *var_milt_v = DEF_MILT_V;
MILTERS *cleanup_milters = (MILTERS *) ((char *) sizeof(*cleanup_milters));
char *var_milt_head_checks = "";
-MAPS *cleanup_milt_head_checks;
/* Dummies to satisfy unused external references. */
@@ -2586,11 +2625,10 @@ int main(int unused_argc, char **argv)
cleanup_milter_hbc_finish(state);
myfree(var_milt_head_checks);
var_milt_head_checks = "";
- maps_free(cleanup_milt_head_checks);
- cleanup_milt_head_checks = 0;
+ cleanup_milter_header_checks_deinit();
}
close_queue_file(state);
- } else if (state->milter_hbc_reply && LEN(state->milter_hbc_reply)) {
+ } else if (cleanup_milter_hbc_reply && LEN(cleanup_milter_hbc_reply)) {
/* Postfix libmilter would skip further requests. */
msg_info("ignoring: %s %s %s", argv->argv[0],
argv->argc > 1 ? argv->argv[1] : "",
@@ -2695,9 +2733,7 @@ int main(int unused_argc, char **argv)
msg_warn("can't change header checks");
} else {
var_milt_head_checks = mystrdup(argv->argv[1]);
- cleanup_milt_head_checks = maps_create(VAR_MILT_HEAD_CHECKS,
- var_milt_head_checks, DICT_FLAG_LOCK);
- cleanup_milter_header_checks_init(state);
+ cleanup_milter_header_checks_init();
}
} else if (strcmp(argv->argv[0], "sender_bcc_maps") == 0) {
if (argv->argc != 2) {
@@ -2729,10 +2765,8 @@ int main(int unused_argc, char **argv)
msg_info("errs = %s", cleanup_strerror(state->errs));
}
cleanup_state_free(state);
- if (*var_milt_head_checks)
+ if (*var_milt_head_checks)
myfree(var_milt_head_checks);
- if (cleanup_milt_head_checks)
- maps_free(cleanup_milt_head_checks);
return (0);
}
diff --git a/postfix/src/cleanup/cleanup_state.c b/postfix/src/cleanup/cleanup_state.c
index 7790f1b51..99adf84b9 100644
--- a/postfix/src/cleanup/cleanup_state.c
+++ b/postfix/src/cleanup/cleanup_state.c
@@ -107,8 +107,6 @@ CLEANUP_STATE *cleanup_state_alloc(VSTREAM *src)
state->append_hdr_pt_target = -1;
state->append_meta_pt_offset = -1;
state->append_meta_pt_target = -1;
- state->milter_hbc_checks = 0;
- state->milter_hbc_reply = 0;
state->rcpt_count = 0;
state->reason = 0;
state->smtp_reply = 0;
diff --git a/postfix/src/global/header_body_checks.c b/postfix/src/global/header_body_checks.c
index 74a4f6f95..0252dd192 100644
--- a/postfix/src/global/header_body_checks.c
+++ b/postfix/src/global/header_body_checks.c
@@ -19,15 +19,23 @@
/* } HBC_CALL_BACKS;
/*
/* HBC_CHECKS *hbc_header_checks_create(
-/* header_checks_maps, mime_header_checks_maps,
-/* nested_header_checks_maps, call_backs)
-/* MAPS *header_checks_maps;
-/* MAPS *mime_header_checks_maps;
-/* MAPS *nested_header_checks_maps;
+/* header_checks_name, header_checks_value
+/* mime_header_checks_name, mime_header_checks_value,
+/* nested_header_checks_name, nested_header_checks_value,
+/* call_backs)
+/* const char *header_checks_name;
+/* const char *header_checks_value;
+/* const char *mime_header_checks_name;
+/* const char *mime_header_checks_value;
+/* const char *nested_header_checks_name;
+/* const char *nested_header_checks_value;
/* HBC_CALL_BACKS *call_backs;
/*
-/* HBC_CHECKS *hbc_body_checks_create(body_check_maps, call_backs)
-/* MAPS *body_check_maps;
+/* HBC_CHECKS *hbc_body_checks_create(
+/* body_checks_name, body_checks_value,
+/* call_backs)
+/* const char *body_checks_name;
+/* const char *body_checks_value;
/* HBC_CALL_BACKS *call_backs;
/*
/* char *hbc_header_checks(context, hbc, header_class, hdr_opts, header)
@@ -63,14 +71,11 @@
/*
/* hbc_header_checks_create() creates a context for header
/* inspection. This function is typically called once during
-/* program initialization. The result is a null pointer when
-/* all _maps arguments specify a null pointer; in this
+/* program initialization. The result is a null pointer when
+/* all _value arguments specify zero-length strings; in this
/* case, hbc_header_checks() and hbc_header_checks_free() must
/* not be called.
/*
-/* Note: hbc_header_checks_create() does not take ownership
-/* of its _maps arguments.
-/*
/* hbc_header_checks() inspects the specified logical header.
/* The result is either the original header, HBC_CHECKS_STAT_IGNORE
/* (meaning: discard the header), HBC_CHECKS_STAT_ERROR, or a
@@ -189,15 +194,27 @@ char hbc_checks_error;
const char hbc_checks_unknown;
/*
- * Header checks are stored as an array of MAPS pointers, one for each
- * header class (MIME_HDR_PRIMARY, MIME_HDR_MULTIPART, or MIME_HDR_NESTED).
+ * Header checks are stored as an array of HBC_MAP_INFO structures, one
+ * structure for each header class (MIME_HDR_PRIMARY, MIME_HDR_MULTIPART, or
+ * MIME_HDR_NESTED).
*
- * Body checks are stored as a single MAPS pointer, because we make no
- * distinction between body segments.
+ * Body checks are stored as one single HBC_MAP_INFO structure, because we make
+ * no distinction between body segments.
*/
#define HBC_HEADER_INDEX(class) ((class) - MIME_HDR_FIRST)
#define HBC_BODY_INDEX (0)
+#define HBC_INIT(hbc, index, name, value) do { \
+ HBC_MAP_INFO *_mp = (hbc)->map_info + (index); \
+ if (*(value) != 0) { \
+ _mp->map_class = (name); \
+ _mp->maps = maps_create((name), (value), DICT_FLAG_LOCK); \
+ } else { \
+ _mp->map_class = 0; \
+ _mp->maps = 0; \
+ } \
+ } while (0)
+
/* How does the action routine know where we are? */
#define HBC_CTXT_HEADER "header"
@@ -278,7 +295,7 @@ static char *hbc_action(void *context, HBC_CALL_BACKS *cb,
if (STREQUAL(cmd, "IGNORE", cmd_len))
/* XXX Not logged for compatibility with cleanup(8). */
return (HBC_CHECKS_STAT_IGNORE);
-
+
if (STREQUAL(cmd, "DUNNO", cmd_len) /* preferred */
||STREQUAL(cmd, "OK", cmd_len)) /* compatibility */
return ((char *) line);
@@ -295,7 +312,7 @@ char *hbc_header_checks(void *context, HBC_CHECKS *hbc, int header_class,
{
const char *myname = "hbc_header_checks";
const char *action;
- MAPS *mp;
+ HBC_MAP_INFO *mp;
if (msg_verbose)
msg_info("%s: '%.30s'", myname, STR(header));
@@ -306,13 +323,13 @@ char *hbc_header_checks(void *context, HBC_CHECKS *hbc, int header_class,
if (hdr_opts && (hdr_opts->flags & HDR_OPT_MIME))
header_class = MIME_HDR_MULTIPART;
- mp = hbc->map_info[HBC_HEADER_INDEX(header_class)];
+ mp = hbc->map_info + HBC_HEADER_INDEX(header_class);
- if (mp != 0 && (action = maps_find(mp, STR(header), 0)) != 0) {
+ if (mp->maps != 0 && (action = maps_find(mp->maps, STR(header), 0)) != 0) {
return (hbc_action(context, hbc->call_backs,
- maps_title(mp), HBC_CTXT_HEADER, action,
+ mp->map_class, HBC_CTXT_HEADER, action,
STR(header), LEN(header), offset));
- } else if (mp && mp->error) {
+ } else if (mp->maps && mp->maps->error) {
return (HBC_CHECKS_STAT_ERROR);
} else {
return (STR(header));
@@ -326,18 +343,18 @@ char *hbc_body_checks(void *context, HBC_CHECKS *hbc, const char *line,
{
const char *myname = "hbc_body_checks";
const char *action;
- MAPS *mp;
+ HBC_MAP_INFO *mp;
if (msg_verbose)
msg_info("%s: '%.30s'", myname, line);
- mp = hbc->map_info[0];
+ mp = hbc->map_info;
- if ((action = maps_find(mp, line, 0)) != 0) {
+ if ((action = maps_find(mp->maps, line, 0)) != 0) {
return (hbc_action(context, hbc->call_backs,
- maps_title(mp), HBC_CTXT_BODY, action,
+ mp->map_class, HBC_CTXT_BODY, action,
line, len, offset));
- } else if (mp->error) {
+ } else if (mp->maps->error) {
return (HBC_CHECKS_STAT_ERROR);
} else {
return ((char *) line);
@@ -346,9 +363,12 @@ char *hbc_body_checks(void *context, HBC_CHECKS *hbc, const char *line,
/* hbc_header_checks_create - create header checking context */
-HBC_CHECKS *hbc_header_checks_create(MAPS *header_checks_maps,
- MAPS *mime_header_checks_maps,
- MAPS *nested_header_checks_maps,
+HBC_CHECKS *hbc_header_checks_create(const char *header_checks_name,
+ const char *header_checks_value,
+ const char *mime_header_checks_name,
+ const char *mime_header_checks_value,
+ const char *nested_header_checks_name,
+ const char *nested_header_checks_value,
HBC_CALL_BACKS *call_backs)
{
HBC_CHECKS *hbc;
@@ -356,26 +376,27 @@ HBC_CHECKS *hbc_header_checks_create(MAPS *header_checks_maps,
/*
* Optimize for the common case.
*/
- if (header_checks_maps == 0 && mime_header_checks_maps == 0
- && nested_header_checks_maps == 0) {
+ if (*header_checks_value == 0 && *mime_header_checks_value == 0
+ && *nested_header_checks_value == 0) {
return (0);
} else {
hbc = (HBC_CHECKS *) mymalloc(sizeof(*hbc)
- + (MIME_HDR_LAST - MIME_HDR_FIRST) * sizeof(hbc->map_info));
+ + (MIME_HDR_LAST - MIME_HDR_FIRST) * sizeof(HBC_MAP_INFO));
hbc->call_backs = call_backs;
- hbc->map_info[HBC_HEADER_INDEX(MIME_HDR_PRIMARY)] =
- header_checks_maps;
- hbc->map_info[HBC_HEADER_INDEX(MIME_HDR_MULTIPART)] =
- mime_header_checks_maps;
- hbc->map_info[HBC_HEADER_INDEX(MIME_HDR_NESTED)] =
- nested_header_checks_maps;
+ HBC_INIT(hbc, HBC_HEADER_INDEX(MIME_HDR_PRIMARY),
+ header_checks_name, header_checks_value);
+ HBC_INIT(hbc, HBC_HEADER_INDEX(MIME_HDR_MULTIPART),
+ mime_header_checks_name, mime_header_checks_value);
+ HBC_INIT(hbc, HBC_HEADER_INDEX(MIME_HDR_NESTED),
+ nested_header_checks_name, nested_header_checks_value);
return (hbc);
}
}
/* hbc_body_checks_create - create body checking context */
-HBC_CHECKS *hbc_body_checks_create(MAPS *body_checks_maps,
+HBC_CHECKS *hbc_body_checks_create(const char *body_checks_name,
+ const char *body_checks_value,
HBC_CALL_BACKS *call_backs)
{
HBC_CHECKS *hbc;
@@ -383,12 +404,12 @@ HBC_CHECKS *hbc_body_checks_create(MAPS *body_checks_maps,
/*
* Optimize for the common case.
*/
- if (body_checks_maps == 0) {
+ if (*body_checks_value == 0) {
return (0);
} else {
hbc = (HBC_CHECKS *) mymalloc(sizeof(*hbc));
hbc->call_backs = call_backs;
- hbc->map_info[HBC_BODY_INDEX] = body_checks_maps;
+ HBC_INIT(hbc, HBC_BODY_INDEX, body_checks_name, body_checks_value);
return (hbc);
}
}
@@ -397,6 +418,11 @@ HBC_CHECKS *hbc_body_checks_create(MAPS *body_checks_maps,
void _hbc_checks_free(HBC_CHECKS *hbc, ssize_t len)
{
+ HBC_MAP_INFO *mp;
+
+ for (mp = hbc->map_info; mp < hbc->map_info + len; mp++)
+ if (mp->maps)
+ maps_free(mp->maps);
myfree((void *) hbc);
}
@@ -577,18 +603,13 @@ int main(int argc, char **argv)
body_out, body_end,
err_print,
(void *) &context);
-
-#define MAPS_OR_NULL(name, value) \
- (*(value) ? maps_create((name), (value), DICT_FLAG_LOCK) : (MAPS *) 0)
-
context.header_checks =
- hbc_header_checks_create(MAPS_OR_NULL("header_checks", argv[1]),
- MAPS_OR_NULL("mime_header_checks", argv[2]),
- MAPS_OR_NULL("nested_header_checks", argv[3]),
+ hbc_header_checks_create("header_checks", argv[1],
+ "mime_header_checks", argv[2],
+ "nested_header_checks", argv[3],
call_backs);
context.body_checks =
- hbc_body_checks_create(MAPS_OR_NULL("body_checks", argv[4]),
- call_backs);
+ hbc_body_checks_create("body_checks", argv[4], call_backs);
context.buf = vstring_alloc(100);
context.fp = VSTREAM_OUT;
context.queueid = "test-queueID";
diff --git a/postfix/src/global/header_body_checks.h b/postfix/src/global/header_body_checks.h
index abdfcc75e..7a2718e05 100644
--- a/postfix/src/global/header_body_checks.h
+++ b/postfix/src/global/header_body_checks.h
@@ -28,6 +28,11 @@
/*
* External interface.
*/
+typedef struct {
+ const char *map_class; /* parameter name */
+ MAPS *maps; /* map handle */
+} HBC_MAP_INFO;
+
typedef struct {
void (*logger) (void *, const char *, const char *, const char *, const char *);
void (*prepend) (void *, int, const char *, ssize_t, off_t);
@@ -36,16 +41,19 @@ typedef struct {
typedef struct {
HBC_CALL_BACKS *call_backs;
- MAPS *map_info[1]; /* actually, a bunch; NOT owned */
+ HBC_MAP_INFO map_info[1]; /* actually, a bunch */
} HBC_CHECKS;
#define HBC_CHECKS_STAT_IGNORE ((char *) 0)
#define HBC_CHECKS_STAT_ERROR (&hbc_checks_error)
#define HBC_CHECKS_STAT_UNKNOWN (&hbc_checks_unknown)
-extern HBC_CHECKS *hbc_header_checks_create(MAPS *, MAPS *, MAPS *,
+extern HBC_CHECKS *hbc_header_checks_create(const char *, const char *,
+ const char *, const char *,
+ const char *, const char *,
HBC_CALL_BACKS *);
-extern HBC_CHECKS *hbc_body_checks_create(MAPS *, HBC_CALL_BACKS *);
+extern HBC_CHECKS *hbc_body_checks_create(const char *, const char *,
+ HBC_CALL_BACKS *);
extern char *hbc_header_checks(void *, HBC_CHECKS *, int, const HEADER_OPTS *,
VSTRING *, off_t);
extern char *hbc_body_checks(void *, HBC_CHECKS *, const char *, ssize_t, off_t);
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index dc3a36f2d..a85e79a0c 100644
--- a/postfix/src/global/mail_version.h
+++ b/postfix/src/global/mail_version.h
@@ -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 "20220403"
+#define MAIL_RELEASE_DATE "20220407"
#define MAIL_VERSION_NUMBER "3.8"
#ifdef SNAPSHOT
diff --git a/postfix/src/global/maps.c b/postfix/src/global/maps.c
index 599d724f2..7c84e9aa0 100644
--- a/postfix/src/global/maps.c
+++ b/postfix/src/global/maps.c
@@ -21,9 +21,6 @@
/* const char *key;
/* int flags;
/*
-/* const char *maps_title(maps)
-/* MAPS *maps;
-/*
/* MAPS *maps_free(maps)
/* MAPS *maps;
/* DESCRIPTION
@@ -51,9 +48,6 @@
/* the base64 lookup result. This requires that the maps are
/* opened with DICT_FLAG_SRC_RHS_IS_FILE.
/*
-/* maps_title() returns a pointer to a copy of the title
-/* specified with maps_create().
-/*
/* maps_free() releases storage claimed by maps_create()
/* and conveniently returns a null pointer.
/*
diff --git a/postfix/src/global/maps.h b/postfix/src/global/maps.h
index bf12845f9..04ee6dc93 100644
--- a/postfix/src/global/maps.h
+++ b/postfix/src/global/maps.h
@@ -28,8 +28,6 @@ typedef struct MAPS {
extern MAPS *maps_create(const char *, const char *, int);
extern const char *maps_find(MAPS *, const char *, int);
extern const char *maps_file_find(MAPS *, const char *, int);
-
-#define maps_title(maps) ((const char *) ((maps)->title))
extern MAPS *maps_free(MAPS *);
/* LICENSE
diff --git a/postfix/src/smtp/smtp.c b/postfix/src/smtp/smtp.c
index 798a53b32..3ccbfe8c9 100644
--- a/postfix/src/smtp/smtp.c
+++ b/postfix/src/smtp/smtp.c
@@ -1090,7 +1090,7 @@ int var_smtp_sasl_auth_cache_time;
bool var_smtp_sasl_auth_soft_bounce;
char *var_hfrom_format;
-bool var_smtp_bind_addr_enforce;
+bool var_smtp_bind_addr_enforce;
/*
* Global variables.
@@ -1539,16 +1539,13 @@ static void pre_init(char *unused_name, char **unused_argv)
/*
* Header/body checks.
*/
-#define MAPS_OR_NULL(name, value) \
- (*(value) ? maps_create((name), (value), DICT_FLAG_LOCK) : (MAPS *) 0)
-
smtp_header_checks = hbc_header_checks_create(
- MAPS_OR_NULL(VAR_LMTP_SMTP(HEAD_CHKS), var_smtp_head_chks),
- MAPS_OR_NULL(VAR_LMTP_SMTP(MIME_CHKS), var_smtp_mime_chks),
- MAPS_OR_NULL(VAR_LMTP_SMTP(NEST_CHKS), var_smtp_nest_chks),
+ VAR_LMTP_SMTP(HEAD_CHKS), var_smtp_head_chks,
+ VAR_LMTP_SMTP(MIME_CHKS), var_smtp_mime_chks,
+ VAR_LMTP_SMTP(NEST_CHKS), var_smtp_nest_chks,
smtp_hbc_callbacks);
smtp_body_checks = hbc_body_checks_create(
- MAPS_OR_NULL(VAR_LMTP_SMTP(BODY_CHKS), var_smtp_body_chks),
+ VAR_LMTP_SMTP(BODY_CHKS), var_smtp_body_chks,
smtp_hbc_callbacks);
/*
diff --git a/postfix/src/util/inet_connect.c b/postfix/src/util/inet_connect.c
index 591283ef2..dded7e425 100644
--- a/postfix/src/util/inet_connect.c
+++ b/postfix/src/util/inet_connect.c
@@ -101,9 +101,13 @@ int inet_connect(const char *addr, int block_mode, int timeout)
if ((parse_err = host_port(buf, &host, "localhost", &port, (char *) 0)) != 0)
msg_fatal("%s: %s", addr, parse_err);
if ((aierr = hostname_to_sockaddr(host, port, SOCK_STREAM, &res0)) != 0)
- msg_fatal("host or service %s not found: %s",
- addr, MAI_STRERROR(aierr));
+ msg_warn("host or service %s not found: %s",
+ addr, MAI_STRERROR(aierr));
myfree(buf);
+ if (aierr) {
+ errno = EADDRNOTAVAIL; /* for up-stream "%m" */
+ return (-1);
+ }
proto_info = inet_proto_info();
for (sock = -1, found = 0, res = res0; res != 0; res = res->ai_next) {