Safety net: append a null byte to vstring buffers, so that
C-style string operations won't scribble past the end. File:
vstring.[hc].
+
+20170505
+
+ Workaround for a current problem where some destination
+ announces primarily IPv6 MX addresses, the smtp_address_limit
+ eliminates most or all IPv4 addresses, and the destination
+ is not reachable over IPv6. This workaround is enabled with
+ "smtp_balance_mx_inet_protocols = yes", which is the default.
+ Files: smtp/smtp.c, smtp/smtp_params.c, smtp/smtp_addr.c,
+ global/mail_params.h, proto/postconf.proto.
+
<b><a href="postconf.5.html#smtp_dns_reply_filter">smtp_dns_reply_filter</a> (empty)</b>
Optional filter for Postfix SMTP client DNS lookup results.
+ Available in Postfix version 3.3 and later:
+
+ <b><a href="postconf.5.html#smtp_balance_inet_protocols">smtp_balance_inet_protocols</a> (yes)</b>
+ When a remote destination resolves to a combination of IPv4 and
+ IPv6 addresses, ensure that the Postfix SMTP client can try both
+ address types before it runs into the <a href="postconf.5.html#smtp_mx_address_limit">smtp_mx_address_limit</a>.
+
<b>MIME PROCESSING CONTROLS</b>
Available in Postfix version 2.0 and later:
existing LMTP-based content filters. </p>
+</DD>
+
+<DT><b><a name="lmtp_balance_inet_protocols">lmtp_balance_inet_protocols</a>
+(default: yes)</b></DT><DD>
+
+<p> The LMTP-specific version of the <a href="postconf.5.html#smtp_balance_inet_protocols">smtp_balance_inet_protocols</a>
+configuration parameter. See there for details. </p>
+
+<p> This feature is available in Postfix 3.3 and later. </p>
+
+
</DD>
<DT><b><a name="lmtp_bind_address">lmtp_bind_address</a>
</p>
+</DD>
+
+<DT><b><a name="smtp_balance_inet_protocols">smtp_balance_inet_protocols</a>
+(default: yes)</b></DT><DD>
+
+<p> When a remote destination resolves to a combination of IPv4 and
+IPv6 addresses, ensure that the Postfix SMTP client can try both
+address types before it runs into the <a href="postconf.5.html#smtp_mx_address_limit">smtp_mx_address_limit</a>. </p>
+
+<p> This avoids an interoperability problem when a destination resolves
+to primarily IPv6 addresses, the smtp_address_limit feature eliminates
+most or all IPv4 addresses, and the destination is not reachable over
+IPv6. </p>
+
+<p> This feature is available in Postfix 3.3 and later. </p>
+
+
</DD>
<DT><b><a name="smtp_bind_address">smtp_bind_address</a>
<b><a href="postconf.5.html#smtp_dns_reply_filter">smtp_dns_reply_filter</a> (empty)</b>
Optional filter for Postfix SMTP client DNS lookup results.
+ Available in Postfix version 3.3 and later:
+
+ <b><a href="postconf.5.html#smtp_balance_inet_protocols">smtp_balance_inet_protocols</a> (yes)</b>
+ When a remote destination resolves to a combination of IPv4 and
+ IPv6 addresses, ensure that the Postfix SMTP client can try both
+ address types before it runs into the <a href="postconf.5.html#smtp_mx_address_limit">smtp_mx_address_limit</a>.
+
<b>MIME PROCESSING CONTROLS</b>
Available in Postfix version 2.0 and later:
notifications instead of "relayed". The default setting is backwards
compatible to avoid the infinitesimal possibility of breaking
existing LMTP\-based content filters.
+.SH lmtp_balance_inet_protocols (default: yes)
+The LMTP\-specific version of the smtp_balance_inet_protocols
+configuration parameter. See there for details.
+.PP
+This feature is available in Postfix 3.3 and later.
.SH lmtp_bind_address (default: empty)
The LMTP\-specific version of the smtp_bind_address configuration
parameter. See there for details.
EHLO only when
the word "ESMTP" appears in the server greeting banner (example:
220 spike.porcupine.org ESMTP Postfix).
+.SH smtp_balance_inet_protocols (default: yes)
+When a remote destination resolves to a combination of IPv4 and
+IPv6 addresses, ensure that the Postfix SMTP client can try both
+address types before it runs into the smtp_mx_address_limit.
+.PP
+This avoids an interoperability problem when a destination resolves
+to primarily IPv6 addresses, the smtp_address_limit feature eliminates
+most or all IPv4 addresses, and the destination is not reachable over
+IPv6.
+.PP
+This feature is available in Postfix 3.3 and later.
.SH smtp_bind_address (default: empty)
An optional numerical network address that the Postfix SMTP client
should bind to when making an IPv4 connection.
deliveries.
.IP "\fBsmtp_dns_reply_filter (empty)\fR"
Optional filter for Postfix SMTP client DNS lookup results.
+.PP
+Available in Postfix version 3.3 and later:
+.IP "\fBsmtp_balance_inet_protocols (yes)\fR"
+When a remote destination resolves to a combination of IPv4 and
+IPv6 addresses, ensure that the Postfix SMTP client can try both
+address types before it runs into the smtp_mx_address_limit.
.SH "MIME PROCESSING CONTROLS"
.na
.nf
s;\blmtp_reply_filter\b;<a href="postconf.5.html#lmtp_reply_filter">$&</a>;g;
s;\blmtp_sasl_password_maps\b;<a href="postconf.5.html#lmtp_sasl_password_maps">$&</a>;g;
s;\blmtp_send_dummy_mail_auth\b;<a href="postconf.5.html#lmtp_send_dummy_mail_auth">$&</a>;g;
+ s;\blmtp_balance_inet_protocols\b;<a href="postconf.5.html#lmtp_balance_inet_protocols">$&</a>;g;
s;\blmtp_sender_dependent_authentication\b;<a href="postconf.5.html#lmtp_sender_dependent_authentication">$&</a>;g;
s;\blmtp_bind_address\b;<a href="postconf.5.html#lmtp_bind_address">$&</a>;g;
s;\blmtp_bind_address6\b;<a href="postconf.5.html#lmtp_bind_address6">$&</a>;g;
s;\bsmtp_address_preference\b;<a href="postconf.5.html#smtp_address_preference">$&</a>;g;
s;\bsmtp_per_record_deadline\b;<a href="postconf.5.html#smtp_per_record_deadline">$&</a>;g;
s;\bsmtp_send_dummy_mail_auth\b;<a href="postconf.5.html#smtp_send_dummy_mail_auth">$&</a>;g;
+ s;\bsmtp_balance_inet_protocols\b;<a href="postconf.5.html#smtp_balance_inet_protocols">$&</a>;g;
s;\bsmtpd_enforce_tls\b;<a href="postconf.5.html#smtpd_enforce_tls">$&</a>;g;
s;\bsmtpd_sasl_tls_security_options\b;<a href="postconf.5.html#smtpd_sasl_tls_security_options">$&</a>;g;
s;\bsmtpd_sasl_type\b;<a href="postconf.5.html#smtpd_sasl_type">$&</a>;g;
</p>
<p> This feature is available in Postfix 3.2 and later. </p>
+
+%PARAM smtp_balance_inet_protocols yes
+
+<p> When a remote destination resolves to a combination of IPv4 and
+IPv6 addresses, ensure that the Postfix SMTP client can try both
+address types before it runs into the smtp_mx_address_limit. </p>
+
+<p> This avoids an interoperability problem when a destination resolves
+to primarily IPv6 addresses, the smtp_address_limit feature eliminates
+most or all IPv4 addresses, and the destination is not reachable over
+IPv6. </p>
+
+<p> This feature is available in Postfix 3.3 and later. </p>
+
+%PARAM lmtp_balance_inet_protocols yes
+
+<p> The LMTP-specific version of the smtp_balance_inet_protocols
+configuration parameter. See there for details. </p>
+
+<p> This feature is available in Postfix 3.3 and later. </p>
#define DEF_SMTP_DUMMY_MAIL_AUTH 0
extern bool var_smtp_dummy_mail_auth;
+#define VAR_LMTP_BALANCE_INET_PROTO "lmtp_balance_inet_protocols"
+#define DEF_LMTP_BALANCE_INET_PROTO DEF_SMTP_BALANCE_INET_PROTO
+#define VAR_SMTP_BALANCE_INET_PROTO "smtp_balance_inet_protocols"
+#define DEF_SMTP_BALANCE_INET_PROTO 1
+extern bool var_smtp_balance_inet_proto;
+
/*
* LMTP server. The soft error limit determines how many errors an LMTP
* client may make before we start to slow down; the hard error limit
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20170502"
+#define MAIL_RELEASE_DATE "20170505"
#define MAIL_VERSION_NUMBER "3.3"
#ifdef SNAPSHOT
VAR_LMTP_ASSUME_FINAL, DEF_LMTP_ASSUME_FINAL, &var_lmtp_assume_final,
VAR_LMTP_REC_DEADLINE, DEF_LMTP_REC_DEADLINE, &var_smtp_rec_deadline,
VAR_LMTP_DUMMY_MAIL_AUTH, DEF_LMTP_DUMMY_MAIL_AUTH, &var_smtp_dummy_mail_auth,
+ VAR_LMTP_BALANCE_INET_PROTO, DEF_LMTP_BALANCE_INET_PROTO, &var_smtp_balance_inet_proto,
0,
};
/* deliveries.
/* .IP "\fBsmtp_dns_reply_filter (empty)\fR"
/* Optional filter for Postfix SMTP client DNS lookup results.
+/* .PP
+/* Available in Postfix version 3.3 and later:
+/* .IP "\fBsmtp_balance_inet_protocols (yes)\fR"
+/* When a remote destination resolves to a combination of IPv4 and
+/* IPv6 addresses, ensure that the Postfix SMTP client can try both
+/* address types before it runs into the smtp_mx_address_limit.
/* MIME PROCESSING CONTROLS
/* .ad
/* .fi
bool var_smtp_dummy_mail_auth;
char *var_smtp_dsn_filter;
char *var_smtp_dns_re_filter;
+bool var_smtp_balance_inet_proto;
/* Special handling of 535 AUTH errors. */
char *var_smtp_sasl_auth_cache_name;
return (addr_list);
}
+/* smtp_balance_inet_proto - balance IPv4/6 protocols within address limit */
+
+static DNS_RR *smtp_balance_inet_proto(DNS_RR *addr_list, int misc_flags,
+ int addr_limit)
+{
+ const char myname[] = "smtp_balance_inet_proto";
+ DNS_RR *rr;
+ DNS_RR *result_list;
+ DNS_RR *next;
+ int v6_count;
+ int v4_count;
+ int v6_target, v4_target;
+ int *p;
+
+ /*
+ * Precondition: the input is sorted by MX preference (not necessarily IP
+ * address family preference), and addresses with the same or worse
+ * preference than 'myself' have been eliminated. Postcondition: the
+ * relative list order is unchanged, but some elements are removed.
+ */
+
+ /*
+ * Count the number of IPv6 and IPv4 addresses.
+ */
+ for (v4_count = v6_count = 0, rr = addr_list; rr != 0; rr = rr->next) {
+ if (rr->type == T_A) {
+ v4_count++;
+ } else if (rr->type == T_AAAA) {
+ v6_count++;
+ } else {
+ msg_panic("%s: unexpected record type: %s",
+ myname, dns_strtype(rr->type));
+ }
+ }
+
+ /*
+ * Ensure that one address type will not out-crowd the other, while
+ * enforcing the address count limit. This works around a current problem
+ * where some destination announces primarily IPv6 MX addresses, the
+ * smtp_address_limit eliminates most or all IPv4 addresses, and the
+ * destination is not reachable over IPv6.
+ *
+ * Maybe: do all smtp_mx_address_limit enforcement here, and remove
+ * pre-existing enforcement elsewhere. That would obsolete the
+ * smtp_balance_inet_protocols configuration parameter.
+ */
+ if (v4_count > 0 && v6_count > 0 && v4_count + v6_count > addr_limit) {
+
+ /*-
+ * Decide how many IPv6 and IPv4 addresses to keep. The code below
+ * has three branches, corresponding to the regions R1, R2 and R3
+ * in the figure.
+ *
+ * L = addr_limit
+ * X = excluded by condition (v4_count + v6_count > addr_limit)
+ *
+ * v4_count
+ * ^
+ * |
+ * L \ R1
+ * |X\ |
+ * |XXX\ |
+ * |XXXXX\ | R2
+ * L/2 +-------\-------
+ * |XXXXXXX|X\
+ * |XXXXXXX|XXX\ R3
+ * |XXXXXXX|XXXXX\
+ * 0 +-------+-------\--> v6_count
+ * 0 L/2 L
+ */
+ if (v6_count <= addr_limit / 2) { /* Region R1 */
+ v6_target = v6_count;
+ v4_target = addr_limit - v6_target;
+ } else if (v4_count <= addr_limit / 2) {/* Region R3 */
+ v4_target = v4_count;
+ v6_target = addr_limit - v4_target;
+ } else { /* Region R2 */
+ /* v4_count > addr_limit / 2 && v6_count > addr_limit / 2 */
+ v4_target = (addr_limit + (addr_list->type == T_A)) / 2;
+ v6_target = addr_limit - v4_target;
+ }
+ if (msg_verbose)
+ msg_info("v6_target=%d, v4_target=%d", v6_target, v4_target);
+
+ /* Enforce the address count targets. */
+ result_list = 0;
+ for (rr = addr_list; rr != 0; rr = next) {
+ next = rr->next;
+ rr->next = 0;
+ if (rr->type == T_A) {
+ p = &v4_target;
+ } else if (rr->type == T_AAAA) {
+ p = &v6_target;
+ } else {
+ msg_panic("%s: unexpected record type: %s",
+ myname, dns_strtype(rr->type));
+ }
+ if (*p > 0) {
+ result_list = dns_rr_append(result_list, rr);
+ *p -= 1;
+ } else {
+ dns_rr_free(rr);
+ }
+ }
+ if (v4_target > 0 || v6_target > 0)
+ msg_panic("%s: bad target count: v4_target=%d, v6_target=%d",
+ myname, v4_target, v6_target);
+ if (msg_verbose)
+ smtp_print_addr("smtp_balance_inet_proto result", result_list);
+ }
+ return (result_list);
+}
+
/* smtp_domain_addr - mail exchanger address lookup */
DNS_RR *smtp_domain_addr(const char *name, DNS_RR **mxrr, int misc_flags,
((flags) & SMTP_MISC_FLAG_PREF_IPV4) ? dns_rr_compare_pref_ipv4 : \
dns_rr_compare_pref_any)
- if (addr_list && addr_list->next && var_smtp_rand_addr) {
- addr_list = dns_rr_shuffle(addr_list);
+ if (addr_list && addr_list->next) {
+ if (var_smtp_rand_addr)
+ addr_list = dns_rr_shuffle(addr_list);
addr_list = dns_rr_sort(addr_list, SMTP_COMPARE_ADDR(misc_flags));
+ if (var_smtp_balance_inet_proto)
+ addr_list = smtp_balance_inet_proto(addr_list, misc_flags,
+ var_smtp_mxaddr_limit);
}
break;
case DNS_NOTFOUND:
/* The following changes the order of equal-preference hosts. */
if (inet_proto_info()->ai_family_list[1] != 0)
addr_list = dns_rr_sort(addr_list, SMTP_COMPARE_ADDR(misc_flags));
+ if (var_smtp_balance_inet_proto)
+ addr_list = smtp_balance_inet_proto(addr_list, misc_flags,
+ var_smtp_mxaddr_limit);
}
if (msg_verbose)
smtp_print_addr(host, addr_list);
VAR_LMTP_ASSUME_FINAL, DEF_LMTP_ASSUME_FINAL, &var_lmtp_assume_final,
VAR_SMTP_REC_DEADLINE, DEF_SMTP_REC_DEADLINE, &var_smtp_rec_deadline,
VAR_SMTP_DUMMY_MAIL_AUTH, DEF_SMTP_DUMMY_MAIL_AUTH, &var_smtp_dummy_mail_auth,
+ VAR_SMTP_BALANCE_INET_PROTO, DEF_SMTP_BALANCE_INET_PROTO, &var_smtp_balance_inet_proto,
0,
};