20220403
+ (Rolled back because there was too much collateral damage)
Cleanup: milter_hader_checks maps are now opened before the
cleanup server enters the chroot jail. Files: cleanup/cleanup.h,
cleanup/cleanup_init.c, cleanup/cleanup_milter.c,
global/header_body_checks.c, global/header_body_checks.h,
global/maps.c, global/maps.h, smtp/smtp.c.
+
+20220404
+
+ Bugfix: in an internal client module, "host or service not
+ found" was a fatal error, causing the milter_default_action
+ setting to be ignored. It is now a non-fatal error. The
+ same client is used by many Postfix clients (smtpd_proxy,
+ dovecot auth, tcp_table, memcache, socketmap, and so on).
+ File: util/inet_connect.c.
+
+20220407
+
+ Documentation: updated the firewall/gateway example to use
+ the "relay" transport to forward inbound messages. File:
+ proto/STANDARD_CONFIGURATION_README.html
+
+ Documentation: updated smtp_fallback_relay description.
+ The text was based on an early Postfix implementation.
+ File: proto/postconf.proto.
+
+ Cleanup: milter_hader_checks maps are now opened before the
+ cleanup server enters the chroot jail. Files: cleanup/cleanup.h,
+ cleanup/cleanup_init.c, cleanup/cleanup_milter.c,
+ cleanup/cleanup_state.c.
17 . . .
18
19 /etc/postfix/transport:
- 20 example.com smtp:[inside-gateway.example.com]
+ 20 example.com relay:[inside-gateway.example.com]
Translation:
"@example.com x" 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.
+ 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.
Specify d\bdb\bbm\bm instead of h\bha\bas\bsh\bh if your system uses d\bdb\bbm\bm files instead of d\bdb\bb files.
To find out what lookup tables Postfix supports, use the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
Disable -DSNAPSHOT and -DNONPROD in makedefs.
+ Can tests use LD_PRELOAD to inject fake modules such
+ as fake_dns(3), fake_msg(3), fake_myaddrinfo() and so on?
+ One limitation is that functions etc. in a preloaded object
+ always take precedence.
+
+ '%l' support. ef7c661c-d86a-2366-6a73-ec8d51d75012@dev.snart.me
+
+ WARN_IF_REJECT like prefix that disables the error counter increment.
+
+ Send the Postfix version in a policy server request.
+
postscreen_dnsbl_sites is evaluated in the reverse order, breaking
expectations when different reply patterns have different weights.
We need a compatibility_level feature to correct this.
17 . . .
18
19 /etc/postfix/transport:
-20 example.com <a href="smtp.8.html">smtp</a>:[inside-gateway.example.com]
+20 example.com relay:[inside-gateway.example.com]
</pre>
</blockquote>
<li> <p> Lines 12, 19-20: Route mail for "example.com" to the inside
gateway machine. The <tt>[]</tt> forces Postfix to do no MX lookup.
-</p>
+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. </p>
</ul>
<DT><b><a name="smtp_fallback_relay">smtp_fallback_relay</a>
(default: $<a href="postconf.5.html#fallback_relay">fallback_relay</a>)</b></DT><DD>
-<p>
-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 <a href="postconf.5.html#fallback_relay">fallback_relay</a>. </p>
-
-<p>
-By default, mail is returned to the sender when a destination is
-not found, and delivery is deferred when a destination is unreachable.
-</p>
+<p> 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 <a href="postconf.5.html#fallback_relay">fallback_relay</a>. </p>
+
+<p> By default, <a href="postconf.5.html#smtp_fallback_relay">smtp_fallback_relay</a> 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. </p>
<p> 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
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
17 . . .
18
19 /etc/postfix/transport:
-20 example.com smtp:[inside-gateway.example.com]
+20 example.com relay:[inside-gateway.example.com]
</pre>
</blockquote>
<li> <p> Lines 12, 19-20: Route mail for "example.com" to the inside
gateway machine. The <tt>[]</tt> forces Postfix to do no MX lookup.
-</p>
+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. </p>
</ul>
%PARAM smtp_fallback_relay $fallback_relay
-<p>
-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. </p>
-
-<p>
-By default, mail is returned to the sender when a destination is
-not found, and delivery is deferred when a destination is unreachable.
-</p>
+<p> 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. </p>
+
+<p> 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. </p>
<p> 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
XXX XXX
int compar DNS_RR DNS_RR
USE_FNV_32BIT USE_FNV_32BIT
+void void cleanup_milter_receive state count
stackexchange
stdint
Noll
+deinit
+reinit
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 */
/*
/*
* Milters.
*/
-extern MAPS *cleanup_milt_head_checks;
extern MILTERS *cleanup_milters;
/*
/*
* 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 *);
/*
* Milter support.
*/
-MAPS *cleanup_milt_head_checks;
MILTERS *cleanup_milters;
/*
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,
var_milt_eod_macros,
var_milt_unk_macros,
var_milt_macro_deflts);
+ if (*var_milt_head_checks)
+ cleanup_milter_header_checks_init();
flush_init();
}
/* SYNOPSIS
/* #include <cleanup.h>
/*
+/* void cleanup_milter_header_checks_init(void)
+/*
/* void cleanup_milter_receive(state, count)
/* CLEANUP_STATE *state;
/* int count;
/* 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
/*#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 *);
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)) {
}
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);
* 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) {
/* 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,
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;
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))
*/
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);
* 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.
* 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);
*/
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.
* 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);
/*
/*
* 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
/*
* Epilogue: finalize Milter header/body checks.
*/
- if (cleanup_milt_head_checks)
+ if (*var_milt_head_checks)
cleanup_milter_hbc_finish(state);
if (msg_verbose)
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. */
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] : "",
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) {
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);
}
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;
/* } 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)
/*
/* 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
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"
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);
{
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));
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));
{
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);
/* 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;
/*
* 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;
/*
* 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);
}
}
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);
}
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";
/*
* 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);
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);
* 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
/* const char *key;
/* int flags;
/*
-/* const char *maps_title(maps)
-/* MAPS *maps;
-/*
/* MAPS *maps_free(maps)
/* MAPS *maps;
/* DESCRIPTION
/* 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.
/*
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
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.
/*
* 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);
/*
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) {