From: Wietse Venema Date: Fri, 5 May 2017 05:00:00 +0000 (-0500) Subject: postfix-3.3-20170505 X-Git-Tag: v3.3.0-RC1~25 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=16de2a99fda2138b0a91a32756016b680c2ea7c7;p=thirdparty%2Fpostfix.git postfix-3.3-20170505 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index f7f806d8e..51f1b08ee 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -22969,3 +22969,14 @@ Apologies for any names omitted. 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. + diff --git a/postfix/html/lmtp.8.html b/postfix/html/lmtp.8.html index ee0ec5f62..6ea8f7639 100644 --- a/postfix/html/lmtp.8.html +++ b/postfix/html/lmtp.8.html @@ -303,6 +303,13 @@ SMTP(8) SMTP(8) smtp_dns_reply_filter (empty) Optional filter for Postfix SMTP client DNS lookup results. + Available in Postfix version 3.3 and later: + + smtp_balance_inet_protocols (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. + MIME PROCESSING CONTROLS Available in Postfix version 2.0 and later: diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index bdeffc8d5..24ca39583 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -4147,6 +4147,17 @@ compatible to avoid the infinitesimal possibility of breaking existing LMTP-based content filters.

+ + +
lmtp_balance_inet_protocols +(default: yes)
+ +

The LMTP-specific version of the smtp_balance_inet_protocols +configuration parameter. See there for details.

+ +

This feature is available in Postfix 3.3 and later.

+ +
lmtp_bind_address @@ -10144,6 +10155,23 @@ the word "ESMTP" appears in the server greeting banner (example:

+ + +
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.

+ +

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.

+ +

This feature is available in Postfix 3.3 and later.

+ +
smtp_bind_address diff --git a/postfix/html/smtp.8.html b/postfix/html/smtp.8.html index ee0ec5f62..6ea8f7639 100644 --- a/postfix/html/smtp.8.html +++ b/postfix/html/smtp.8.html @@ -303,6 +303,13 @@ SMTP(8) SMTP(8) smtp_dns_reply_filter (empty) Optional filter for Postfix SMTP client DNS lookup results. + Available in Postfix version 3.3 and later: + + smtp_balance_inet_protocols (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. + MIME PROCESSING CONTROLS Available in Postfix version 2.0 and later: diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index ffecdf307..c2a4e7018 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -2561,6 +2561,11 @@ server performs final delivery, and send "delivered" delivery status 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. @@ -6306,6 +6311,17 @@ With "smtp_always_send_ehlo = no", the Postfix SMTP client sends 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. diff --git a/postfix/man/man8/smtp.8 b/postfix/man/man8/smtp.8 index c755fccd7..5c65b0b32 100644 --- a/postfix/man/man8/smtp.8 +++ b/postfix/man/man8/smtp.8 @@ -285,6 +285,12 @@ delivery status code or explanatory text of successful or unsuccessful 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 diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink index 76d260ad7..eef4c0e70 100755 --- a/postfix/mantools/postlink +++ b/postfix/mantools/postlink @@ -227,6 +227,7 @@ while (<>) { s;\blmtp_reply_filter\b;$&;g; s;\blmtp_sasl_password_maps\b;$&;g; s;\blmtp_send_dummy_mail_auth\b;$&;g; + s;\blmtp_balance_inet_protocols\b;$&;g; s;\blmtp_sender_dependent_authentication\b;$&;g; s;\blmtp_bind_address\b;$&;g; s;\blmtp_bind_address6\b;$&;g; @@ -687,6 +688,7 @@ while (<>) { s;\bsmtp_address_preference\b;$&;g; s;\bsmtp_per_record_deadline\b;$&;g; s;\bsmtp_send_dummy_mail_auth\b;$&;g; + s;\bsmtp_balance_inet_protocols\b;$&;g; s;\bsmtpd_enforce_tls\b;$&;g; s;\bsmtpd_sasl_tls_security_options\b;$&;g; s;\bsmtpd_sasl_type\b;$&;g; diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index 8394f75c6..f8595a4e0 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -16685,3 +16685,23 @@ See http://unicode.org/cldr/utility/idna.jsp for more examples.

This feature is available in Postfix 3.2 and later.

+ +%PARAM smtp_balance_inet_protocols 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.

+ +

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.

+ +

This feature is available in Postfix 3.3 and later.

+ +%PARAM lmtp_balance_inet_protocols yes + +

The LMTP-specific version of the smtp_balance_inet_protocols +configuration parameter. See there for details.

+ +

This feature is available in Postfix 3.3 and later.

diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 3cc94a02b..be6970a28 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -1704,6 +1704,12 @@ extern char *var_smtp_sasl_tlsv_opts; #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 diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 8b99fb8c6..9ab7a1874 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 "20170502" +#define MAIL_RELEASE_DATE "20170505" #define MAIL_VERSION_NUMBER "3.3" #ifdef SNAPSHOT diff --git a/postfix/src/smtp/lmtp_params.c b/postfix/src/smtp/lmtp_params.c index 732d55434..68d611e26 100644 --- a/postfix/src/smtp/lmtp_params.c +++ b/postfix/src/smtp/lmtp_params.c @@ -121,5 +121,6 @@ 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, }; diff --git a/postfix/src/smtp/smtp.c b/postfix/src/smtp/smtp.c index fd90bd13d..a93fa01b5 100644 --- a/postfix/src/smtp/smtp.c +++ b/postfix/src/smtp/smtp.c @@ -263,6 +263,12 @@ /* 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 @@ -934,6 +940,7 @@ bool var_smtp_rec_deadline; 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; diff --git a/postfix/src/smtp/smtp_addr.c b/postfix/src/smtp/smtp_addr.c index 789a21806..46652a5e6 100644 --- a/postfix/src/smtp/smtp_addr.c +++ b/postfix/src/smtp/smtp_addr.c @@ -354,6 +354,119 @@ static DNS_RR *smtp_truncate_self(DNS_RR *addr_list, unsigned pref) 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, @@ -498,9 +611,13 @@ 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: @@ -558,6 +675,9 @@ DNS_RR *smtp_host_addr(const char *host, int misc_flags, DSN_BUF *why) /* 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); diff --git a/postfix/src/smtp/smtp_params.c b/postfix/src/smtp/smtp_params.c index d8628831d..ed5ea455b 100644 --- a/postfix/src/smtp/smtp_params.c +++ b/postfix/src/smtp/smtp_params.c @@ -125,5 +125,6 @@ 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, };