]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.3-20170505
authorWietse Venema <wietse@porcupine.org>
Fri, 5 May 2017 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Mon, 8 May 2017 03:06:14 +0000 (23:06 -0400)
14 files changed:
postfix/HISTORY
postfix/html/lmtp.8.html
postfix/html/postconf.5.html
postfix/html/smtp.8.html
postfix/man/man5/postconf.5
postfix/man/man8/smtp.8
postfix/mantools/postlink
postfix/proto/postconf.proto
postfix/src/global/mail_params.h
postfix/src/global/mail_version.h
postfix/src/smtp/lmtp_params.c
postfix/src/smtp/smtp.c
postfix/src/smtp/smtp_addr.c
postfix/src/smtp/smtp_params.c

index f7f806d8e851b581218b9f571caaf59600c1c343..51f1b08eeed1cf4ea0be9f55d93b31f161df85a2 100644 (file)
@@ -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.
+
index ee0ec5f62bb5729c2080f319effaead161e85aad..6ea8f76390d43b80e7177ae0538104b1da5a2739 100644 (file)
@@ -303,6 +303,13 @@ SMTP(8)                                                                SMTP(8)
        <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:
 
index bdeffc8d58f614eefd70441475a39b0f0ef56480..24ca39583a1e3acac1542ca6ed6e962a1f81197a 100644 (file)
@@ -4147,6 +4147,17 @@ compatible to avoid the infinitesimal possibility of breaking
 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>
@@ -10144,6 +10155,23 @@ the word "ESMTP" appears in the server greeting banner (example:
 </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>
index ee0ec5f62bb5729c2080f319effaead161e85aad..6ea8f76390d43b80e7177ae0538104b1da5a2739 100644 (file)
@@ -303,6 +303,13 @@ SMTP(8)                                                                SMTP(8)
        <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:
 
index ffecdf307b8ea79568aa181036fca79ab1d11123..c2a4e70182bc9147d67f68221e1962e3af7d17b8 100644 (file)
@@ -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.
index c755fccd7395a89540523fb7fa6c3355406212ff..5c65b0b32a6907db9f0773db7b14d3b731d8b7b0 100644 (file)
@@ -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
index 76d260ad7dd708d84979e5db6b2b0f1599ad2b74..eef4c0e7044a9096c6346bba34d56b5bdeef200d 100755 (executable)
@@ -227,6 +227,7 @@ while (<>) {
     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;
@@ -687,6 +688,7 @@ while (<>) {
     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;
index 8394f75c6f28396198c89927a2ccdf3e7c4078fc..f8595a4e046496f4e4aeafd6f92ef7486cfb2f49 100644 (file)
@@ -16685,3 +16685,23 @@ See http://unicode.org/cldr/utility/idna.jsp for more examples.
 </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>
index 3cc94a02bcdbc072b9e3ee520ed1b92cd3109d2f..be6970a282a8bf8b6987e18e84676d8331bb642c 100644 (file)
@@ -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
index 8b99fb8c664b0831dc3f2283471fcccca4229f32..9ab7a1874bd490de5f5625c39a7077f8585c30fc 100644 (file)
@@ -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
index 732d55434dc6ad9b9ec1757380d217789558a155..68d611e265b77c2628b2cc8138bf077e2cbc63fa 100644 (file)
        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,
     };
index fd90bd13dcf3e5371df1a4dbc7f7e2922b10a590..a93fa01b58bfe698d439d6bd37efd230cbef2995 100644 (file)
 /*     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;
index 789a2180679556596bb7c934735f114cb0d4c619..46652a5e6179928f3134cfc89dad7a5c4c968189 100644 (file)
@@ -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);
index d8628831d92674d0df9a21f18c69eb6953635958..ed5ea455ba7079e3c0e8b3aa498ada33dc7ee353 100644 (file)
        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,
     };