]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.3-20050707
authorWietse Venema <wietse@porcupine.org>
Thu, 7 Jul 2005 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:31:20 +0000 (06:31 +0000)
16 files changed:
postfix/HISTORY
postfix/README_FILES/SMTPD_POLICY_README
postfix/README_FILES/TUNING_README
postfix/RELEASE_NOTES
postfix/html/SMTPD_POLICY_README.html
postfix/html/TUNING_README.html
postfix/html/pipe.8.html
postfix/man/man8/pipe.8
postfix/proto/SMTPD_POLICY_README.html
postfix/proto/TUNING_README.html
postfix/src/global/mail_version.h
postfix/src/global/scache_clnt.c
postfix/src/pipe/pipe.c
postfix/src/scache/scache.c
postfix/src/smtpd/smtpd_peer.c
postfix/src/util/sys_defs.h

index aba7fed550904dc76d70544780aff527741d825b..76b932dfdc47329bd7e009ac4ef3d8fdac8e0e82 100644 (file)
@@ -10967,6 +10967,17 @@ Apologies for any names omitted.
        systems (inherited from Stevens Network Programming).  Files:
        util/unix_send_fd.c, util/unix_recv_fd.c.
 
+20050706
+
+       Robustness: the connection cache client now disables caching
+       when it is unable to communicate with the scache(8) server,
+       instead of looping forever. File: global/scache_clnt.c.
+
+       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.
+        
 Open problems:
 
        Look for systems with XPG basename() declared in <libgen.h>,
index 27ddd95e9c1b95eb7f49aa743cf7fa0144aba5dc..c2c714c3644140f036d45c9d1e8866a385d57e2a 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 9e87262eef589883c183a289ee41c9202aa55525..a12abd678eb4fb133b39d8e4de2aa595ca004309 100644 (file)
@@ -17,6 +17,12 @@ Incompatibility with Postfix 2.1 and earlier
 If you upgrade from Postfix 2.1 or earlier, read RELEASE_NOTES-2.2
 before proceeding.
 
+Incompatibility with snapshot 20050707
+======================================
+
+The connection cache protocol is changed. You may need to "postfix
+reload" after upgrading.
+
 Incompatibility with snapshot 20050627
 ======================================
 
index df8f3ccd67e953e36cf2700a1ade2a47ae4e6540..e4ee237aab70905b2967937b85293ca5f5a189ec 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 abec1f67849ccdd92f2c357ceee6f48c3ff5e04a..05599514e16597d8e2cc04e8520a9208fa299f8a 100644 (file)
@@ -157,7 +157,7 @@ PIPE(8)                                                                PIPE(8)
 
        <b>size</b>=<i>size</i><b>_</b><i>limit</i> (optional)
               Messages greater in size than this limit (in bytes)
-              will be bounced back to the sender.
+              will be returned to the sender as undeliverable.
 
        <b>user</b>=<i>username</i> (required)
 
index 44f02efae85b911efc2dc97faf2f8fb358b99a73..9e4dbc660d46ec206827f82f8ede260c6fb745cf 100644 (file)
@@ -144,8 +144,8 @@ specify \fB$sender\fR as an argument by itself.
 .sp
 This feature is available with Postfix 2.3 and later.
 .IP "\fBsize\fR=\fIsize_limit\fR (optional)"
-Messages greater in size than this limit (in bytes) will be bounced
-back to the sender.
+Messages greater in size than this limit (in bytes) will
+be returned to the sender as undeliverable.
 .IP "\fBuser\fR=\fIusername\fR (required)"
 .IP "\fBuser\fR=\fIusername\fR:\fIgroupname\fR"
 The external command is executed with the rights of the
index 84e25c79c982841b3fa14120a5c8919c9e94b6f6..fb2bcb83ed883cf34bcfc48b926fb84d4723ea94 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 9db66ece7bfc3423688e34c622c70349d6c44cbb..0476ecb43a7c343f5cf36279eae40ba2b9356a0d 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      "20050630"
+#define MAIL_RELEASE_DATE      "20050707"
 #define MAIL_VERSION_NUMBER    "2.3"
 
 #define VAR_MAIL_VERSION       "mail_version"
index 9c1e482df7ef62d9d2c08e947a3e337045f14aed..4749d6931006b85fe2d5231ffc14dc0211d6e4fa 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,37 +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);
 }
 
 /* scache_clnt_save_dest - create destination/endpoint association */
@@ -202,6 +233,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 +246,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 +267,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 +296,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,38 +316,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);
 }
 
 /* scache_clnt_size - dummy */
@@ -322,7 +379,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 +400,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 f2bfd0b72a98edd38b182ab63b25dfd8b992af96..795030d48cd93322127214a0076243328aee13fe 100644 (file)
 /* .sp
 /*     This feature is available with Postfix 2.3 and later.
 /* .IP "\fBsize\fR=\fIsize_limit\fR (optional)"
-/*     Messages greater in size than this limit (in bytes) will be bounced
-/*     back to the sender.
+/*     Messages greater in size than this limit (in bytes) will
+/*     be returned to the sender as undeliverable.
 /* .IP "\fBuser\fR=\fIusername\fR (required)"
 /* .IP "\fBuser\fR=\fIusername\fR:\fIgroupname\fR"
 /*     The external command is executed with the rights of the
index 8687a8ab21c7e929edad4ea0628f1dbcfc34331d..deb6f0dad5da671e30a0b7d8aae846784344b3e5 100644 (file)
@@ -241,17 +241,17 @@ 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: %m", myname);
-       attr_print(client_stream, ATTR_FLAG_NONE,
-                  ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_FAIL,
-                  ATTR_TYPE_END);
+       (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 fd4c847240aeeabc11f85c14e310f0035bed75d1..dc6b08e8b4c1c6356be078f06da2596d0b668ab5 100644 (file)
@@ -20,7 +20,8 @@
 /*     smtpd_peer_init() updates the following fields:
 /* .IP name
 /*     The client hostname. An unknown name is represented by the
-/*     string "unknown".
+/*     string "unknown". This includes names that could not be
+/*     verified with forward DNS lookups.
 /* .IP addr
 /*     Printable representation of the client address.
 /* .IP namaddr
@@ -213,6 +214,9 @@ void    smtpd_peer_init(SMTPD_STATE *state)
 
            /*
             * Reject the hostname if it does not list the peer address.
+            * Without further validation or qualification, such information
+            * must not be allowed to enter the audit trail, as people would
+            * draw false conclusions.
             */
            aierr = hostname_to_sockaddr(state->name, (char *) 0, 0, &res0);
            if (aierr) {
index 44df401318fea6de50f23c41459ba514b6237d27..f2a1bb372fa997eaf7e7d8bf42c05a7508162b47 100644 (file)
@@ -1308,6 +1308,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
 
  /*