]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.2.5 v2.2.5
authorWietse Venema <wietse@porcupine.org>
Tue, 19 Jul 2005 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Sat, 10 Feb 2018 21:11:43 +0000 (16:11 -0500)
22 files changed:
postfix/HISTORY
postfix/README_FILES/SMTPD_POLICY_README
postfix/README_FILES/TUNING_README
postfix/html/SMTPD_POLICY_README.html
postfix/html/TUNING_README.html
postfix/html/postconf.5.html
postfix/man/man5/postconf.5
postfix/mantools/postconf2man
postfix/proto/SMTPD_POLICY_README.html
postfix/proto/TUNING_README.html
postfix/proto/postconf.proto
postfix/src/global/mail_version.h
postfix/src/global/scache_clnt.c
postfix/src/scache/scache.c
postfix/src/smtpstone/qmqp-source.c
postfix/src/tls/tls_scache.c
postfix/src/util/clean_env.c
postfix/src/util/sys_defs.h
postfix/src/util/unix_recv_fd.c
postfix/src/util/unix_send_fd.c
postfix/src/util/vstring.c
postfix/src/util/vstring.h

index 897522f447947685fca9b3ac951eaeacd1e639ba..4cfc645a1eeb0a7213074457bedc6c01a2111d31 100644 (file)
@@ -10609,3 +10609,33 @@ Apologies for any names omitted.
        no SMTP connection caching for those platforms.  Albert
        Chin.  File: util/sys_defs.h.
 
+20050630
+
+       Portability: the connection caching code broke on LP64
+       systems (inherited from Stevens Network Programming).  Files:
+       util/unix_send_fd.c, util/unix_recv_fd.c. This code is
+       back-ported from the Postfix 2.3 snapshot release.
+
+20050706
+
+       Robustness: the SMTP client now disables caching when it
+       is unable to communicate with the scache(8) connection
+       caching server, instead of looping forever and not delivering
+       mail. File: global/scache_clnt.c.  This code is back-ported
+       from the Postfix 2.3 snapshot release.
+
+       Portability: after sending a socket, the scache(8) server
+       now waits for an ACK from the connection cache client before
+       closing the socket that it just sent. Files: scache/scache.c,
+       global/scache_clnt.c. This code is back-ported from the
+       Postfix 2.3 snapshot release.
+
+20050711-3
+
+       Portability: on LP64 systems, integer expressions are int,
+       but sizeof() and pointer difference expressions are larger.
+       Point fixes for a few discrepancies with variadic functions
+       that expect int (the permanent fix is to change the receiving
+       modules, but that results in too much change, and is not
+       allowed in the stable release).  Files: tls/tls_scache.c,
+       util/clean_env.c, util/vstring.h, smtpstone/qmqp-source.c.
index 4cdca8b4b60290c7d139869000dc49bff4d65023..3f0a2cafc9abac170e564416b53f8b68f055a33f 100644 (file)
@@ -96,7 +96,7 @@ The following is specific to SMTPD delegated policy requests:
 
   * Protocol names are ESMTP or SMTP.
 
-  * Protocol states are CONNECT, EHLO, HELO, MAIL, RCPT, DATA, END-OF-DATA,
+  * Protocol states are CONNECT, EHLO, HELO, MAIL, RCPT, DATA, END-OF-MESSAGE,
     VRFY or ETRN; these are the SMTP protocol states where the Postfix SMTP
     server makes an OK/REJECT/HOLD/etc. decision.
 
index 58e5edd98a5fb8b3fb7889b3d62a67aa87a35659..c544ffc2a9287588003cbb34b2cb7f1638cb1f77 100644 (file)
@@ -157,12 +157,18 @@ will suffer grotesque delays if you do so.
     simultaneous connections (default: 50). This is half the default process
     limit.
 
+  * An SMTP client may make up to $smtpd_client_message_rate_limit message
+    delivery requests per unit time (default: no limit).
+
+  * An SMTP client may send up to $smtpd_client_recipient_rate_limit recipient
+    addresses per unit time (default: no limit).
+
   * An SMTP client may make up to $smtpd_client_connection_rate_limit
     connections per unit time (default: no limit).
 
   * These limits are not applied to SMTP clients in the networks specified with
-    $smtpd_client_connection_limit_exceptions (default: clients in $mynetworks
-    may make an unlimited number of connections).
+    $smtpd_client_event_limit_exceptions (default: clients in $mynetworks may
+    make an unlimited number of connections).
 
   * The anvil_rate_time_unit parameter specifies the time unit over which
     client connection rates are computed (default: 60s).
index 18d5bc225d7cf4c4577c771d4c030821208ec1f3..8cb3d4f4be05d5f2a16318c27742b56c434c9cc0 100644 (file)
@@ -146,7 +146,7 @@ size=12345
     <li> <p> Protocol names are ESMTP or SMTP. </p>
 
     <li> <p> Protocol states are CONNECT, EHLO, HELO, MAIL, RCPT,
-    DATA, END-OF-DATA, VRFY or ETRN; these are the SMTP protocol
+    DATA, END-OF-MESSAGE, VRFY or ETRN; these are the SMTP protocol
     states where
     the Postfix SMTP server makes an OK/REJECT/HOLD/etc. decision.
     </p>
index f0911ee9840e7f38c3dfe8bb354bcd8f409549af..cf7e2a3eab0dc26357be4ee35df8308adb12da2c 100644 (file)
@@ -242,11 +242,17 @@ traffic: mail will suffer grotesque delays if you do so. </p>
 simultaneous connections (default: 50). This is half the default
 process limit. </p>
 
+<li> <p> An SMTP client may make up to $<a href="postconf.5.html#smtpd_client_message_rate_limit">smtpd_client_message_rate_limit</a>
+message delivery requests per unit time (default: no limit). </p>
+
+<li> <p> An SMTP client may send up to $<a href="postconf.5.html#smtpd_client_recipient_rate_limit">smtpd_client_recipient_rate_limit</a>
+recipient addresses per unit time (default: no limit). </p>
+
 <li> <p> An SMTP client may make up to $<a href="postconf.5.html#smtpd_client_connection_rate_limit">smtpd_client_connection_rate_limit</a>
 connections per unit time (default: no limit). </p>
 
 <li> <p> These limits are not applied to SMTP clients in the networks
-specified with $smtpd_client_connection_limit_exceptions (default:
+specified with $<a href="postconf.5.html#smtpd_client_event_limit_exceptions">smtpd_client_event_limit_exceptions</a> (default:
 clients in $<a href="postconf.5.html#mynetworks">mynetworks</a> may make an unlimited number of connections).
 
 <li> <p> The <a href="postconf.5.html#anvil_rate_time_unit">anvil_rate_time_unit</a> parameter specifies the time
index 71800a22ced3007602110077d120534491a73926..c9d1260c148c929ca4398041bb09218921be0ecd 100644 (file)
@@ -2546,7 +2546,7 @@ home directory.
 </p>
 
 <p>
-Specify a pathname ending "/" for qmail-style delivery.
+Specify a pathname ending in "/" for qmail-style delivery.
 </p>
 
 <p>
index 4e3570cd50711438377e1990a9a0940a92cad99e..3447ab77f1d71a819a0b83e8b5085b77a3e65c60 100644 (file)
@@ -514,7 +514,7 @@ result is ignored).  Continue long lines by starting the next line
 with whitespace.
 .PP
 Note: IP version 6 address information must be specified inside
-<tt>[]</tt> in the authorized_verp_clients value, and in files
+[] in the authorized_verp_clients value, and in files
 specified with "/file/name".  IP version 6 addresses contain the
 ":" character, and would otherwise be confused with a "type:table"
 pattern.
@@ -1180,7 +1180,7 @@ is unavailable.
 In main.cf specify "relay_transport = relay",
 .IP \(bu
 In master.cf specify "-o fallback_relay =" (i.e., empty) at
-the end of the <tt>relay</tt> entry.
+the end of the relay entry.
 .IP \(bu
 In transport maps, specify "relay:\fInexthop...\fR"
 as the right-hand side for backup or primary MX domain entries.
@@ -1326,7 +1326,7 @@ This feature is available in Postfix 2.0 and later.
 Optional pathname of a mailbox file relative to a \fBlocal\fR(8) user's
 home directory.
 .PP
-Specify a pathname ending "/" for qmail-style delivery.
+Specify a pathname ending in "/" for qmail-style delivery.
 .PP
 The precedence of \fBlocal\fR(8) delivery features from high to low is:
 aliases, .forward files, mailbox_transport, mailbox_command_maps,
@@ -1389,11 +1389,11 @@ The network interface addresses that this mail system receives
 mail on. Specify "all" to receive mail on all network
 interfaces (default), and "loopback-only" to receive mail
 on loopback network interfaces only (Postfix 2.2 and later).  The
-parameter also controls delivery of mail to <tt>user@[ip.address]</tt>.
+parameter also controls delivery of mail to user@[ip.address].
 .PP
 Note 1: you need to stop and start Postfix when this parameter changes.
 .PP
-Note 2: address information may be enclosed inside <tt>[]</tt>,
+Note 2: address information may be enclosed inside [],
 but this form is not recommended here.
 .PP
 When inet_interfaces specifies just one IPv4 and/or IPv6 address
@@ -2347,7 +2347,7 @@ first match.  Specify "!pattern" to exclude an address or network
 block from the list.
 .PP
 Note: IP version 6 address information must be specified inside
-<tt>[]</tt> in the mynetworks value, and in files specified with
+[] in the mynetworks value, and in files specified with
 "/file/name".  IP version 6 addresses contain the ":" character,
 and would otherwise be confused with a "type:table" pattern.
 .PP
@@ -3166,7 +3166,7 @@ automatically used as the smtp_bind_address.  This supports virtual
 IP hosting, but can be a problem on multi-homed firewalls. See the
 inet_interfaces documentation for more detail.
 .PP
-Note 2: address information may be enclosed inside <tt>[]</tt>,
+Note 2: address information may be enclosed inside [],
 but this form is not recommended here.
 .SH smtp_bind_address6 (default: empty)
 An optional numerical network address that the SMTP client should
@@ -3193,7 +3193,7 @@ automatically used as the smtp_bind_address6.  This supports virtual
 IP hosting, but can be a problem on multi-homed firewalls. See the
 inet_interfaces documentation for more detail.
 .PP
-Note 2: address information may be enclosed inside <tt>[]</tt>,
+Note 2: address information may be enclosed inside [],
 but this form is not recommended here.
 .SH smtp_connect_timeout (default: 30s)
 The SMTP client time limit for completing a TCP connection, or
@@ -3839,7 +3839,7 @@ result is ignored).  Continue long lines by starting the next line
 with whitespace.
 .PP
 Note: IP version 6 address information must be specified inside
-<tt>[]</tt> in the smtpd_authorized_verp_clients value, and in
+[] in the smtpd_authorized_verp_clients value, and in
 files specified with "/file/name".  IP version 6 addresses contain
 the ":" character, and would otherwise be confused with a "type:table"
 pattern.
@@ -3865,7 +3865,7 @@ result is ignored).  Continue long lines by starting the next line
 with whitespace.
 .PP
 Note: IP version 6 address information must be specified inside
-<tt>[]</tt> in the smtpd_authorized_xclient_hosts value, and in
+[] in the smtpd_authorized_xclient_hosts value, and in
 files specified with "/file/name".  IP version 6 addresses contain
 the ":" character, and would otherwise be confused with a "type:table"
 pattern.
@@ -3890,7 +3890,7 @@ result is ignored).  Continue long lines by starting the next line
 with whitespace.
 .PP
 Note: IP version 6 address information must be specified inside
-<tt>[]</tt> in the smtpd_authorized_xforward_hosts value, and in
+[] in the smtpd_authorized_xforward_hosts value, and in
 files specified with "/file/name".  IP version 6 addresses contain
 the ":" character, and would otherwise be confused with a "type:table"
 pattern.
@@ -3955,7 +3955,7 @@ list of network blocks, hostnames or .domain names (the initial
 dot causes the domain to match any name below it).
 .PP
 Note: IP version 6 address information must be specified inside
-<tt>[]</tt> in the smtpd_client_event_limit_exceptions value, and
+[] in the smtpd_client_event_limit_exceptions value, and
 in files specified with "/file/name".  IP version 6 addresses
 contain the ":" character, and would otherwise be confused with a
 "type:table" pattern.
@@ -4733,7 +4733,7 @@ matches a lookup string (the lookup result is ignored).  Continue
 long lines by starting the next line with whitespace.
 .PP
 Note: IP version 6 address information must be specified inside
-<tt>[]</tt> in the smtpd_sasl_exceptions_networks value, and in
+[] in the smtpd_sasl_exceptions_networks value, and in
 files specified with "/file/name".  IP version 6 addresses contain
 the ":" character, and would otherwise be confused with a "type:table"
 pattern.
index acb182f35319e42663c39c3198175d4928df7aab..4b83cb5199af136392667d9ab3d0acf1473690a9 100755 (executable)
@@ -63,6 +63,8 @@ while(<>) {
     $block =~ s/<li>\s*/\n.IP \\(bu\n/g;
     $block =~ s/<dt>\s*/\n.IP "/g;
     $block =~ s/\s*<\/dt>/"/g;
+    $block =~ s/<tt>\s*//g;
+    $block =~ s/\s*<\/tt>//g;
     $block =~ s/<blockquote>/\n.na\n.nf\n.in +4\n/g;
     $block =~ s/<\/blockquote>/\n.in -4\n.fi\n.ad\n/g;
     $block =~ s/\n<br>/\n.br\n/g;
index dade4b8fc29b1beabdc190bbea7e67e7fcfa8359..d745a08fbad29e9e36acc6c72e3203ed75d212f0 100644 (file)
@@ -146,7 +146,7 @@ size=12345
     <li> <p> Protocol names are ESMTP or SMTP. </p>
 
     <li> <p> Protocol states are CONNECT, EHLO, HELO, MAIL, RCPT,
-    DATA, END-OF-DATA, VRFY or ETRN; these are the SMTP protocol
+    DATA, END-OF-MESSAGE, VRFY or ETRN; these are the SMTP protocol
     states where
     the Postfix SMTP server makes an OK/REJECT/HOLD/etc. decision.
     </p>
index 43eb87784e162156cc23a233f06fe0ecc98326eb..9882044aa7dd273ab59c7dff7ec52d89f3619a67 100644 (file)
@@ -242,11 +242,17 @@ traffic: mail will suffer grotesque delays if you do so. </p>
 simultaneous connections (default: 50). This is half the default
 process limit. </p>
 
+<li> <p> An SMTP client may make up to $smtpd_client_message_rate_limit
+message delivery requests per unit time (default: no limit). </p>
+
+<li> <p> An SMTP client may send up to $smtpd_client_recipient_rate_limit
+recipient addresses per unit time (default: no limit). </p>
+
 <li> <p> An SMTP client may make up to $smtpd_client_connection_rate_limit
 connections per unit time (default: no limit). </p>
 
 <li> <p> These limits are not applied to SMTP clients in the networks
-specified with $smtpd_client_connection_limit_exceptions (default:
+specified with $smtpd_client_event_limit_exceptions (default:
 clients in $mynetworks may make an unlimited number of connections).
 
 <li> <p> The anvil_rate_time_unit parameter specifies the time
index 83eedcddafbeb0230d9862dd9206950f71b7c4a9..3ab5bd2c3a549fa202eaab272e864f10d8932f74 100644 (file)
@@ -1524,7 +1524,7 @@ home directory.
 </p>
 
 <p>
-Specify a pathname ending "/" for qmail-style delivery.
+Specify a pathname ending in "/" for qmail-style delivery.
 </p>
 
 <p>
index d11dbc9a6224dc0d2591ca3c04a2833886ae3163..5fcf512bc018cbc557df929d42e9b2a7f72a6fe8 100644 (file)
@@ -20,8 +20,8 @@
   * Patches change the patchlevel and the release date. Snapshots change the
   * release date only.
   */
-#define MAIL_RELEASE_DATE      "20050621"
-#define MAIL_VERSION_NUMBER    "2.2.4"
+#define MAIL_RELEASE_DATE      "20050719"
+#define MAIL_VERSION_NUMBER    "2.2.5"
 
 #define VAR_MAIL_VERSION       "mail_version"
 #ifdef SNAPSHOT
index 9c1e482df7ef62d9d2c08e947a3e337045f14aed..f8098eea3c73d0b03f429d88e31544b5592c8dbe 100644 (file)
@@ -25,6 +25,7 @@
 /*     Upper bound on the time that a connection is allowed to persist.
 /* DIAGNOSTICS
 /*     Fatal error: memory allocation problem;
+/*     warning: communication error;
 /*     panic: internal consistency failure.
 /* SEE ALSO
 /*     scache(3), generic session cache API
@@ -73,6 +74,8 @@ typedef struct {
 
 #define STR(x) vstring_str(x)
 
+#define SCACHE_MAX_TRIES       2
+
 /* scache_clnt_save_endp - save endpoint */
 
 static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl,
@@ -83,6 +86,7 @@ static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl,
     const char *myname = "scache_clnt_save_endp";
     VSTREAM *stream;
     int     status;
+    int     tries;
 
     if (msg_verbose)
        msg_info("%s: endp=%s prop=%s fd=%d",
@@ -95,11 +99,11 @@ static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl,
        msg_panic("%s: bad endp_ttl: %d", myname, endp_ttl);
 
     /*
-     * Keep trying until we get a complete response. The session cache
-     * service is CPU bound and making the client asynchronous would just
-     * complicate the code.
+     * Try a few times before disabling the cache. We use synchronous calls;
+     * the session cache service is CPU bound and making the client
+     * asynchronous would just complicate the code.
      */
-    for (;;) {
+    for (tries = 0; sp->clnt_stream != 0 ; tries++) {
        stream = clnt_stream_access(sp->clnt_stream);
        errno = 0;
        if (attr_print(stream, ATTR_FLAG_NONE,
@@ -121,14 +125,26 @@ static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl,
            if (msg_verbose || (errno != EPIPE && errno != ENOENT))
                msg_warn("problem talking to service %s: %m",
                         VSTREAM_PATH(stream));
+           /* Give up or recover. */
        } else {
-           if (close(fd) < 0)
-               msg_warn("%s: close(%d): %m", myname, fd);
+           if (msg_verbose && status != 0)
+               msg_warn("%s: descriptor save failed with status %d",
+                        myname, status);
+           break;
+       }
+       /* Give up or recover. */
+       if (tries >= SCACHE_MAX_TRIES - 1) {
+           msg_warn("disabling connection caching");
+           clnt_stream_free(sp->clnt_stream);
+           sp->clnt_stream = 0;
            break;
        }
        sleep(1);                               /* XXX make configurable */
        clnt_stream_recover(sp->clnt_stream);
     }
+    /* Always close the descriptor before returning. */
+    if (close(fd) < 0)
+       msg_warn("%s: close(%d): %m", myname, fd);
 }
 
 /* scache_clnt_find_endp - look up cached session */
@@ -140,14 +156,15 @@ static int scache_clnt_find_endp(SCACHE *scache, const char *endp_label,
     const char *myname = "scache_clnt_find_endp";
     VSTREAM *stream;
     int     status;
+    int     tries;
     int     fd;
 
     /*
-     * Keep trying until we get a complete response. The session cache
-     * service is CPU bound and making the client asynchronous would just
-     * complicate the code.
+     * Try a few times before disabling the cache. We use synchronous calls;
+     * the session cache service is CPU bound and making the client
+     * asynchronous would just complicate the code.
      */
-    for (;;) {
+    for (tries = 0; sp->clnt_stream != 0 ; tries++) {
        stream = clnt_stream_access(sp->clnt_stream);
        errno = 0;
        if (attr_print(stream, ATTR_FLAG_NONE,
@@ -158,36 +175,51 @@ static int scache_clnt_find_endp(SCACHE *scache, const char *endp_label,
            || attr_scan(stream, ATTR_FLAG_STRICT,
                         ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status,
                         ATTR_TYPE_STR, MAIL_ATTR_PROP, endp_prop,
-                        ATTR_TYPE_END) != 2
-           || (status == 0
-               && (
+                        ATTR_TYPE_END) != 2) {
+           if (msg_verbose || (errno != EPIPE && errno != ENOENT))
+               msg_warn("problem talking to service %s: %m",
+                        VSTREAM_PATH(stream));
+           /* Give up or recover. */
+       } else if (status != 0) {
+           if (msg_verbose)
+               msg_info("%s: not found: %s", myname, endp_label);
+           return (-1);
+       } else if (
 #ifdef CANT_WRITE_BEFORE_SENDING_FD
-                   attr_print(stream, ATTR_FLAG_NONE,
-                              ATTR_TYPE_STR, MAIL_ATTR_DUMMY, "",
-                              ATTR_TYPE_END) != 0
-                   || vstream_fflush(stream) != 0
-                   || read_wait(vstream_fileno(stream),
-                                stream->timeout) < 0 ||        /* XXX */
+                  attr_print(stream, ATTR_FLAG_NONE,
+                             ATTR_TYPE_STR, MAIL_ATTR_DUMMY, "",
+                             ATTR_TYPE_END) != 0
+                  || vstream_fflush(stream) != 0
+                  || read_wait(vstream_fileno(stream),
+                               stream->timeout) < 0 || /* XXX */
 #endif
-                   (fd = LOCAL_RECV_FD(vstream_fileno(stream))) < 0))) {
+                  (fd = LOCAL_RECV_FD(vstream_fileno(stream))) < 0) {
            if (msg_verbose || (errno != EPIPE && errno != ENOENT))
                msg_warn("problem talking to service %s: %m",
                         VSTREAM_PATH(stream));
+           /* Give up or recover. */
        } else {
-           break;
+#ifdef MUST_READ_AFTER_SENDING_FD
+           (void) attr_print(stream, ATTR_FLAG_NONE,
+                             ATTR_TYPE_STR, MAIL_ATTR_DUMMY, "",
+                             ATTR_TYPE_END);
+           (void) vstream_fflush(stream);
+#endif
+           if (msg_verbose)
+               msg_info("%s: endp=%s prop=%s fd=%d",
+                        myname, endp_label, STR(endp_prop), fd);
+           return (fd);
+       }
+       /* Give up or recover. */
+       if (tries >= SCACHE_MAX_TRIES - 1) {
+           msg_warn("disabling connection caching");
+           clnt_stream_free(sp->clnt_stream);
+           sp->clnt_stream = 0;
+           return (-1);
        }
        sleep(1);                               /* XXX make configurable */
        clnt_stream_recover(sp->clnt_stream);
     }
-
-    if (status == 0) {
-       if (msg_verbose)
-           msg_info("%s: endp=%s prop=%s fd=%d",
-                    myname, endp_label, STR(endp_prop), fd);
-       return (fd);
-    }
-    if (msg_verbose)
-       msg_info("%s: not found: %s", myname, endp_label);
     return (-1);
 }
 
@@ -202,6 +234,7 @@ static void scache_clnt_save_dest(SCACHE *scache, int dest_ttl,
     const char *myname = "scache_clnt_save_dest";
     VSTREAM *stream;
     int     status;
+    int     tries;
 
     if (msg_verbose)
        msg_info("%s: dest_label=%s dest_prop=%s endp_label=%s",
@@ -214,11 +247,11 @@ static void scache_clnt_save_dest(SCACHE *scache, int dest_ttl,
        msg_panic("%s: bad dest_ttl: %d", myname, dest_ttl);
 
     /*
-     * Keep trying until we get a complete response. The session cache
-     * service is CPU bound and making the client asynchronous would just
-     * complicate the code.
+     * Try a few times before disabling the cache. We use synchronous calls;
+     * the session cache service is CPU bound and making the client
+     * asynchronous would just complicate the code.
      */
-    for (;;) {
+    for (tries = 0; sp->clnt_stream != 0 ; tries++) {
        stream = clnt_stream_access(sp->clnt_stream);
        errno = 0;
        if (attr_print(stream, ATTR_FLAG_NONE,
@@ -235,7 +268,18 @@ static void scache_clnt_save_dest(SCACHE *scache, int dest_ttl,
            if (msg_verbose || (errno != EPIPE && errno != ENOENT))
                msg_warn("problem talking to service %s: %m",
                         VSTREAM_PATH(stream));
+           /* Give up or recover. */
        } else {
+           if (msg_verbose && status != 0)
+               msg_warn("%s: destination save failed with status %d",
+                        myname, status);
+           break;
+       }
+       /* Give up or recover. */
+       if (tries >= SCACHE_MAX_TRIES - 1) {
+           msg_warn("disabling connection caching");
+           clnt_stream_free(sp->clnt_stream);
+           sp->clnt_stream = 0;
            break;
        }
        sleep(1);                               /* XXX make configurable */
@@ -253,14 +297,15 @@ static int scache_clnt_find_dest(SCACHE *scache, const char *dest_label,
     const char *myname = "scache_clnt_find_dest";
     VSTREAM *stream;
     int     status;
+    int     tries;
     int     fd;
 
     /*
-     * Keep trying until we get a complete response. The session cache
-     * service is CPU bound and making the client asynchronous would just
-     * complicate the code.
+     * Try a few times before disabling the cache. We use synchronous calls;
+     * the session cache service is CPU bound and making the client
+     * asynchronous would just complicate the code.
      */
-    for (;;) {
+    for (tries = 0; sp->clnt_stream != 0 ; tries++) {
        stream = clnt_stream_access(sp->clnt_stream);
        errno = 0;
        if (attr_print(stream, ATTR_FLAG_NONE,
@@ -272,37 +317,51 @@ static int scache_clnt_find_dest(SCACHE *scache, const char *dest_label,
                         ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status,
                         ATTR_TYPE_STR, MAIL_ATTR_PROP, dest_prop,
                         ATTR_TYPE_STR, MAIL_ATTR_PROP, endp_prop,
-                        ATTR_TYPE_END) != 3
-           || (status == 0
-               && (
+                        ATTR_TYPE_END) != 3) {
+           if (msg_verbose || (errno != EPIPE && errno != ENOENT))
+               msg_warn("problem talking to service %s: %m",
+                        VSTREAM_PATH(stream));
+           /* Give up or recover. */
+       } else if (status != 0) {
+           if (msg_verbose)
+               msg_info("%s: not found: %s", myname, dest_label);
+           return (-1);
+       } else if (
 #ifdef CANT_WRITE_BEFORE_SENDING_FD
-                   attr_print(stream, ATTR_FLAG_NONE,
-                              ATTR_TYPE_STR, MAIL_ATTR_DUMMY, "",
-                              ATTR_TYPE_END) != 0
-                   || vstream_fflush(stream) != 0
-                   || read_wait(vstream_fileno(stream),
-                                stream->timeout) < 0 ||        /* XXX */
+                  attr_print(stream, ATTR_FLAG_NONE,
+                             ATTR_TYPE_STR, MAIL_ATTR_DUMMY, "",
+                             ATTR_TYPE_END) != 0
+                  || vstream_fflush(stream) != 0
+                  || read_wait(vstream_fileno(stream),
+                               stream->timeout) < 0 || /* XXX */
 #endif
-                   (fd = LOCAL_RECV_FD(vstream_fileno(stream))) < 0))) {
+                  (fd = LOCAL_RECV_FD(vstream_fileno(stream))) < 0) {
            if (msg_verbose || (errno != EPIPE && errno != ENOENT))
                msg_warn("problem talking to service %s: %m",
                         VSTREAM_PATH(stream));
+           /* Give up or recover. */
        } else {
-           break;
+#ifdef MUST_READ_AFTER_SENDING_FD
+           (void) attr_print(stream, ATTR_FLAG_NONE,
+                             ATTR_TYPE_STR, MAIL_ATTR_DUMMY, "",
+                             ATTR_TYPE_END);
+           (void) vstream_fflush(stream);
+#endif
+           if (msg_verbose)
+               msg_info("%s: dest=%s dest_prop=%s endp_prop=%s fd=%d",
+                   myname, dest_label, STR(dest_prop), STR(endp_prop), fd);
+           return (fd);
+       }
+       /* Give up or recover. */
+       if (tries >= SCACHE_MAX_TRIES - 1) {
+           msg_warn("disabling connection caching");
+           clnt_stream_free(sp->clnt_stream);
+           sp->clnt_stream = 0;
+           return (-1);
        }
        sleep(1);                               /* XXX make configurable */
        clnt_stream_recover(sp->clnt_stream);
     }
-
-    if (status == 0) {
-       if (msg_verbose)
-           msg_info("%s: dest=%s dest_prop=%s endp_prop=%s fd=%d",
-                    myname, dest_label, STR(dest_prop), STR(endp_prop), fd);
-       return (fd);
-    }
-    if (msg_verbose)
-       msg_info("%s: not found: %s", myname, dest_label);
-
     return (-1);
 }
 
@@ -322,7 +381,8 @@ static void scache_clnt_free(SCACHE *scache)
 {
     SCACHE_CLNT *sp = (SCACHE_CLNT *) scache;
 
-    clnt_stream_free(sp->clnt_stream);
+    if (sp->clnt_stream)
+       clnt_stream_free(sp->clnt_stream);
 #ifdef CANT_WRITE_BEFORE_SENDING_FD
     vstring_free(sp->dummy);
 #endif
@@ -342,6 +402,7 @@ SCACHE *scache_clnt_create(const char *server, int idle_limit, int ttl_limit)
     sp->scache->size = scache_clnt_size;
     sp->scache->free = scache_clnt_free;
 
+    /* XXX Need flags to stop looping on ECONNREFUSED errors. */
     sp->clnt_stream = clnt_stream_create(MAIL_CLASS_PRIVATE, server,
                                         idle_limit, ttl_limit);
 #ifdef CANT_WRITE_BEFORE_SENDING_FD
index f3d27fa62ed35f13f65d7959a4d20ec36fc399f1..deb6f0dad5da671e30a0b7d8aae846784344b3e5 100644 (file)
@@ -240,18 +240,18 @@ static void scache_save_endp_service(VSTREAM *client_stream)
               ||
 #endif
               (fd = LOCAL_RECV_FD(vstream_fileno(client_stream))) < 0) {
-       msg_warn("%s: unable to receive file descriptor", myname);
-       attr_print(client_stream, ATTR_FLAG_NONE,
-                  ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_FAIL,
-                  ATTR_TYPE_END);
+       msg_warn("%s: unable to receive file descriptor: %m", myname);
+       (void) attr_print(client_stream, ATTR_FLAG_NONE,
+                         ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_FAIL,
+                         ATTR_TYPE_END);
        return;
     } else {
        scache_save_endp(scache,
                         ttl > var_scache_ttl_lim ? var_scache_ttl_lim : ttl,
                         STR(scache_endp_label), STR(scache_endp_prop), fd);
-       attr_print(client_stream, ATTR_FLAG_NONE,
-                  ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_OK,
-                  ATTR_TYPE_END);
+       (void) attr_print(client_stream, ATTR_FLAG_NONE,
+                         ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_OK,
+                         ATTR_TYPE_END);
        scache_size(scache, &size);
        if (size.endp_count > scache_endp_count)
            scache_endp_count = size.endp_count;
@@ -297,7 +297,13 @@ static void scache_find_endp_service(VSTREAM *client_stream)
                         ATTR_TYPE_STR, MAIL_ATTR_DUMMY, scache_dummy,
                         ATTR_TYPE_END) != 1
 #endif
-           || LOCAL_SEND_FD(vstream_fileno(client_stream), fd) < 0)
+           || LOCAL_SEND_FD(vstream_fileno(client_stream), fd) < 0
+#ifdef MUST_READ_AFTER_SENDING_FD
+           || attr_scan(client_stream, ATTR_FLAG_STRICT,
+                        ATTR_TYPE_STR, MAIL_ATTR_DUMMY, scache_dummy,
+                        ATTR_TYPE_END) != 1
+#endif
+           )
            msg_warn("%s: cannot send file descriptor: %m", myname);
        if (close(fd) < 0)
            msg_warn("close(%d): %m", fd);
@@ -384,7 +390,13 @@ static void scache_find_dest_service(VSTREAM *client_stream)
                         ATTR_TYPE_STR, MAIL_ATTR_DUMMY, scache_dummy,
                         ATTR_TYPE_END) != 1
 #endif
-           || LOCAL_SEND_FD(vstream_fileno(client_stream), fd) < 0)
+           || LOCAL_SEND_FD(vstream_fileno(client_stream), fd) < 0
+#ifdef MUST_READ_AFTER_SENDING_FD
+           || attr_scan(client_stream, ATTR_FLAG_STRICT,
+                        ATTR_TYPE_STR, MAIL_ATTR_DUMMY, scache_dummy,
+                        ATTR_TYPE_END) != 1
+#endif
+           )
            msg_warn("%s: cannot send file descriptor: %m", myname);
        if (close(fd) < 0)
            msg_warn("close(%d): %m", fd);
index 367de51bd93259b6a180d3d3efbfeda1cac54b3f..360b312b794e163e1dc74ebf595f684c720fc1ca 100644 (file)
@@ -372,7 +372,7 @@ static void send_data(SESSION *session)
                        STR(message_buffer), LEN(message_buffer),
                        STR(sender_buffer), LEN(sender_buffer),
                        STR(recipient_buffer), LEN(recipient_buffer),
-                       0);
+                       (char *) 0);
     netstring_fflush(session->stream);
 
     /*
index c00789cc37641f2e900790baaf442a4c970a0ac9..3cc2abb4b4ba1c65e29eb66449030b98e1e8c2d5 100644 (file)
@@ -316,7 +316,7 @@ static int tls_scache_decode(TLS_SCACHE *cp, const char *cache_id,
                 cp->cache_label, cache_id, (long) entry->scache_db_version,
                 (long) entry->openssl_version, (long) entry->timestamp,
                 entry->flags,
-                LEN(bin_data) - offsetof(TLS_SCACHE_ENTRY, session));
+              (int) (LEN(bin_data) - offsetof(TLS_SCACHE_ENTRY, session)));
 
     /*
      * Other mandatory restrictions.
index 14023dfe2eb5802d163443a56a700461bfa408b0..888f7bab2e3145f8a2773a7ac99ebd85cf0c7923 100644 (file)
@@ -56,7 +56,7 @@ void    clean_env(char **preserve_list)
     /*
      * Preserve or specify selected environment variables.
      */
-#define STRING_AND_LENGTH(x, y) (x), (y)
+#define STRING_AND_LENGTH(x, y) (x), (int) (y)
 
     save_list = argv_alloc(10);
     for (cpp = preserve_list; *cpp; cpp++)
index 463dbf4e7361c5e585665c689c7040165fcc9daf..c358db320750e9831b52c02f85c8a0934988577d 100644 (file)
@@ -1303,6 +1303,15 @@ typedef int pid_t;
   */
 #ifndef CAN_WRITE_BEFORE_SENDING_FD
 #define CANT_WRITE_BEFORE_SENDING_FD
+#endif
+
+ /*
+  * FreeBSD sendmsg(2) says that after sending a file descriptor, the sender
+  * must not immediately close the descriptor, otherwise it may close the
+  * descriptor before it is actually sent.
+  */
+#ifndef DONT_WAIT_AFTER_SENDING_FD
+#define MUST_READ_AFTER_SENDING_FD
 #endif
 
  /*
index 3fdc5bfcc3e6a9b124db9e404c26631626e25d31..d7fbb7ebab7e0fb7664660a788b5788b7eec7380 100644 (file)
@@ -61,17 +61,18 @@ int     unix_recv_fd(int fd)
 
     /*
      * Adapted from: W. Richard Stevens, UNIX Network Programming, Volume 1,
-     * Second edition.
+     * Second edition. Except that we use CMSG_LEN instead of CMSG_SPACE, for
+     * portability to LP64 environments.
      */
 #if defined(CMSG_SPACE) && !defined(NO_MSGHDR_MSG_CONTROL)
     union {
-       struct msghdr just_for_alignment;
+       struct cmsghdr just_for_alignment;
        char    control[CMSG_SPACE(sizeof(newfd))];
     }       control_un;
     struct cmsghdr *cmptr;
 
     msg.msg_control = control_un.control;
-    msg.msg_controllen = sizeof(control_un.control);
+    msg.msg_controllen = CMSG_LEN(sizeof(newfd));      /* Fix 200506 */
 #else
     msg.msg_accrights = (char *) &newfd;
     msg.msg_accrightslen = sizeof(newfd);
@@ -123,6 +124,8 @@ int     unix_recv_fd(int fd)
   * unix_send_fd test program) and copy its content until EOF.
   */
 #include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
 #include <split_at.h>
 #include <listen.h>
 
index 7c555b77a846ea8ea73903d4cd17017e46cace0f..f913de53e4a5ba7cbdfc6222b05676082330b370 100644 (file)
@@ -63,17 +63,18 @@ int     unix_send_fd(int fd, int sendfd)
 
     /*
      * Adapted from: W. Richard Stevens, UNIX Network Programming, Volume 1,
-     * Second edition.
+     * Second edition. Except that we use CMSG_LEN instead of CMSG_SPACE; the
+     * latter breaks on LP64 systems.
      */
 #if defined(CMSG_SPACE) && !defined(NO_MSGHDR_MSG_CONTROL)
     union {
-       struct msghdr just_for_alignment;
+       struct cmsghdr just_for_alignment;
        char    control[CMSG_SPACE(sizeof(sendfd))];
     }       control_un;
     struct cmsghdr *cmptr;
 
     msg.msg_control = control_un.control;
-    msg.msg_controllen = sizeof(control_un.control);
+    msg.msg_controllen = CMSG_LEN(sizeof(sendfd));     /* Fix 200506 */
 
     cmptr = CMSG_FIRSTHDR(&msg);
     cmptr->cmsg_len = CMSG_LEN(sizeof(sendfd));
@@ -109,6 +110,8 @@ int     unix_send_fd(int fd, int sendfd)
   * to the unix_recv_fd test program.
   */
 #include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
 #include <fcntl.h>
 #include <split_at.h>
 #include <connect.h>
index 53d36601710d9cdb617ae51e66b68d3bbc40e6e9..ddc66302aaa61b70b369f83888a8d9994560b658 100644 (file)
@@ -19,7 +19,7 @@
 /*     char    *vstring_str(vp)
 /*     VSTRING *vp;
 /*
-/*     VSTRING *VSTRING_LEN(vp)
+/*     int     VSTRING_LEN(vp)
 /*     VSTRING *vp;
 /*
 /*     char    *vstring_end(vp)
index b1b81bb8acd8eccc740e551c70ee56e12748d9a9..0c1b2394411610973ed4f2b02626c5e871c7cfb5 100644 (file)
@@ -53,7 +53,7 @@ extern VSTRING *vstring_import(char *);
   */
 #define VSTRING_SPACE(vp, len) ((vp)->vbuf.space(&(vp)->vbuf, len))
 #define vstring_str(vp)                ((char *) (vp)->vbuf.data)
-#define VSTRING_LEN(vp)                ((vp)->vbuf.ptr - (vp)->vbuf.data)
+#define VSTRING_LEN(vp)                ((int) ((vp)->vbuf.ptr - (vp)->vbuf.data))
 #define vstring_end(vp)                ((char *) (vp)->vbuf.ptr)
 #define VSTRING_TERMINATE(vp)  { if ((vp)->vbuf.cnt <= 0) \
                                        VSTRING_SPACE((vp),1); \