]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.5-20071213
authorWietse Venema <wietse@porcupine.org>
Thu, 13 Dec 2007 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:33:41 +0000 (06:33 +0000)
12 files changed:
postfix/HISTORY
postfix/src/global/deliver_request.h
postfix/src/global/mail_version.h
postfix/src/oqmgr/qmgr_entry.c
postfix/src/qmgr/qmgr_entry.c
postfix/src/smtp/smtp.h
postfix/src/smtp/smtp_addr.c
postfix/src/smtp/smtp_addr.h
postfix/src/smtp/smtp_connect.c
postfix/src/smtp/smtp_proto.c
postfix/src/smtp/smtp_session.c
postfix/src/smtp/smtp_trouble.c

index db0082a90c51f327e09bf248205874c6d4096983..552e5fcc9f0bbb5e8fc7116e7a840b91003b9974 100644 (file)
@@ -13950,13 +13950,13 @@ Apologies for any names omitted.
 
        All changes up to this point should be ready for Postfix 2.5.
 
-       Documentation: updated nqgmr preemptive scheduler documentation
+       Documentation: updated nqmgr preemptive scheduler documentation
        by Patrik Rak. File: proto/SCHEDULER_README.html.
 
 20071211
 
-       Bugfix: memory leak when the first write on a bi-directional
-       VSTREAM fails. File: util/vstream.c.
+       Bugfix (introduced 19980315): the "write" equivalent of
+       bugfix 20030104. File: util/vstream.c.
 
 20071212
 
@@ -13967,3 +13967,25 @@ Apologies for any names omitted.
        starting with '-' at SMTP session time. To make this possible
        the feature was moved from qmgr(8) to trivial-rewrite(8).
        Files: *qmgr/qmgr_message.c, trivial-rewrite/resolve.c.
+
+20071213:
+
+       Cleanup: the queue manager and SMTP client now distinguish
+       between connection cache store and retrieve hints. Once the
+       queue manager enables enables connection caching (store and
+       load) hints on a per-destination queue, it keeps sending
+       connection cache retrieve hints to the delivery agent even
+       after it stops sending connection cache store hints.  This
+       prevents the SMTP client from making a new connection without
+       checking the connection cache first. Victor Duchovni.  Files:
+       *qmgr/qmgr_entry.c, smtp/smtp_connect.c.
+
+       Bugfix (introduced Postfix 2.3): the SMTP client never
+       marked corrupt files as corrupt. Victor Duchovni. File:
+       smtp/smtp_proto.c.
+
+       Cleanup: the SMTP client won't mark a destination as
+       unavailable when at least one SMTP session was completed
+       without connect or handshake error. Victor Duchovni. Files:
+       smtp/smtp_connect.c, smtp/smtp_session.c, smtp/smtp_proto.c,
+       smtp/smtp_trouble.c.
index 8f4298d723d409c601d18645652b3cbddb5d0c22..8c07e0209498b65026af9432b12275383e79efdb 100644 (file)
@@ -69,7 +69,14 @@ typedef struct DELIVER_REQUEST {
 #define DEL_REQ_FLAG_MTA_VRFY  (1<<8)  /* MTA-requested address probe */
 #define DEL_REQ_FLAG_USR_VRFY  (1<<9)  /* user-requested address probe */
 #define DEL_REQ_FLAG_RECORD    (1<<10) /* record and deliver */
-#define DEL_REQ_FLAG_SCACHE    (1<<11) /* opportunistic caching */
+#define DEL_REQ_FLAG_SCACHE_LD (1<<11) /* Consult opportunistic cache */
+#define DEL_REQ_FLAG_SCACHE_ST (1<<12) /* Update opportunistic cache */
+
+ /*
+  * Cache Load and Store as value or mask. Use explicit names for multi-bit
+  * values.
+  */
+#define DEL_REQ_FLAG_SCACHE_MASK (DEL_REQ_FLAG_SCACHE_LD|DEL_REQ_FLAG_SCACHE_ST)
 
  /*
   * For compatibility, the old confusing names.
index dc2237de677ff461362a6f62595c9404d8cb3567..def7a4d996cb4fb3e9711987c4d17377b26eeb90 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      "20071212"
+#define MAIL_RELEASE_DATE      "20071213"
 #define MAIL_VERSION_NUMBER    "2.5"
 
 #ifdef SNAPSHOT
index 0f0ac1840028ddb6d069f8f562ace7ab1570fac6..225e092134c93bc68174a18065670ddae1e6a5b3 100644 (file)
@@ -123,9 +123,8 @@ QMGR_ENTRY *qmgr_entry_select(QMGR_QUEUE *queue)
         * (we need to recognize back-to-back deliveries for transports with
         * concurrency 1).
         * 
-        * XXX It would be nice if we could say "try to reuse a cached
-        * connection, but don't bother saving it when you're done". As long
-        * as we can't, we must not turn off session caching too early.
+        * If caching has previously been enabled, but is not now, fetch any
+        * existing entries from the cache, but don't add new ones.
         */
 #define CONCURRENT_OR_BACK_TO_BACK_DELIVERY() \
            (queue->busy_refcount > 1 || BACK_TO_BACK_DELIVERY())
@@ -139,12 +138,12 @@ QMGR_ENTRY *qmgr_entry_select(QMGR_QUEUE *queue)
         * prevents unnecessary session caching when we have a burst of mail
         * <= the initial concurrency limit.
         */
-       if ((queue->dflags & DEL_REQ_FLAG_SCACHE) == 0) {
+       if ((queue->dflags & DEL_REQ_FLAG_SCACHE_ST) == 0) {
            if (BACK_TO_BACK_DELIVERY()) {
                if (msg_verbose)
                    msg_info("%s: allowing on-demand session caching for %s",
                             myname, queue->name);
-               queue->dflags |= DEL_REQ_FLAG_SCACHE;
+               queue->dflags |= DEL_REQ_FLAG_SCACHE_MASK;
            }
        }
 
@@ -159,7 +158,7 @@ QMGR_ENTRY *qmgr_entry_select(QMGR_QUEUE *queue)
                if (msg_verbose)
                    msg_info("%s: disallowing on-demand session caching for %s",
                             myname, queue->name);
-               queue->dflags &= ~DEL_REQ_FLAG_SCACHE;
+               queue->dflags &= ~DEL_REQ_FLAG_SCACHE_ST;
            }
        }
     }
index 82228d59c6c689d5177ae5cc5c322064b19e1d26..9e10a21ff8475d6cda6d28fd652d57d9b9fb8906 100644 (file)
@@ -135,9 +135,8 @@ QMGR_ENTRY *qmgr_entry_select(QMGR_PEER *peer)
         * (we need to recognize back-to-back deliveries for transports with
         * concurrency 1).
         * 
-        * XXX It would be nice if we could say "try to reuse a cached
-        * connection, but don't bother saving it when you're done". As long
-        * as we can't, we must not turn off session caching too early.
+        * If caching has previously been enabled, but is not now, fetch any
+        * existing entries from the cache, but don't add new ones.
         */
 #define CONCURRENT_OR_BACK_TO_BACK_DELIVERY() \
            (queue->busy_refcount > 1 || BACK_TO_BACK_DELIVERY())
@@ -151,12 +150,12 @@ QMGR_ENTRY *qmgr_entry_select(QMGR_PEER *peer)
         * prevents unnecessary session caching when we have a burst of mail
         * <= the initial concurrency limit.
         */
-       if ((queue->dflags & DEL_REQ_FLAG_SCACHE) == 0) {
+       if ((queue->dflags & DEL_REQ_FLAG_SCACHE_ST) == 0) {
            if (BACK_TO_BACK_DELIVERY()) {
                if (msg_verbose)
                    msg_info("%s: allowing on-demand session caching for %s",
                             myname, queue->name);
-               queue->dflags |= DEL_REQ_FLAG_SCACHE;
+               queue->dflags |= DEL_REQ_FLAG_SCACHE_MASK;
            }
        }
 
@@ -171,7 +170,7 @@ QMGR_ENTRY *qmgr_entry_select(QMGR_PEER *peer)
                if (msg_verbose)
                    msg_info("%s: disallowing on-demand session caching for %s",
                             myname, queue->name);
-               queue->dflags &= ~DEL_REQ_FLAG_SCACHE;
+               queue->dflags &= ~DEL_REQ_FLAG_SCACHE_ST;
            }
        }
     }
index d1e027cf1c4acbac9ce0e3553225c698558f521d..259d32ea92ff84e24cd05f17ff21820a0f5470c4 100644 (file)
@@ -141,7 +141,12 @@ typedef struct SMTP_STATE {
 #define SMTP_MISC_FLAG_FIRST_NEXTHOP   (1<<3)
 #define SMTP_MISC_FLAG_FINAL_NEXTHOP   (1<<4)
 #define SMTP_MISC_FLAG_FINAL_SERVER    (1<<5)
-#define SMTP_MISC_FLAG_CONN_CACHE      (1<<6)
+#define SMTP_MISC_FLAG_CONN_LOAD       (1<<6)
+#define SMTP_MISC_FLAG_CONN_STORE      (1<<7)
+#define SMTP_MISC_FLAG_COMPLETE_SESSION        (1<<8)
+
+#define SMTP_MISC_FLAG_CONN_CACHE_MASK \
+       (SMTP_MISC_FLAG_CONN_LOAD | SMTP_MISC_FLAG_CONN_STORE)
 
  /*
   * smtp.c
index ea4244dc2a6fd6048b79e6b8954aaf62b1db3c50..b9c62fb81fb38cb9bb57e5c5e5c235905c3776ec 100644 (file)
 
 /* smtp_print_addr - print address list */
 
-static void smtp_print_addr(char *what, DNS_RR *addr_list)
+static void smtp_print_addr(const char *what, DNS_RR *addr_list)
 {
     DNS_RR *addr;
     MAI_HOSTADDR_STR hostaddr;
@@ -120,8 +120,8 @@ static void smtp_print_addr(char *what, DNS_RR *addr_list)
 
 /* smtp_addr_one - address lookup for one host name */
 
-static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref,
-                                    DSN_BUF *why)
+static DNS_RR *smtp_addr_one(DNS_RR *addr_list, const char *host,
+                                    unsigned pref, DSN_BUF *why)
 {
     const char *myname = "smtp_addr_one";
     DNS_RR *addr = 0;
@@ -469,7 +469,7 @@ DNS_RR *smtp_domain_addr(char *name, int misc_flags, DSN_BUF *why,
 
 /* smtp_host_addr - direct host lookup */
 
-DNS_RR *smtp_host_addr(char *host, int misc_flags, DSN_BUF *why)
+DNS_RR *smtp_host_addr(const char *host, int misc_flags, DSN_BUF *why)
 {
     DNS_RR *addr_list;
 
index 3afec9fae31ae9bef2153087c40fd4603c1d3754..67ff5322ada405b6db1b729e953628b75b2152ac 100644 (file)
@@ -16,7 +16,7 @@
  /*
   * Internal interfaces.
   */
-extern DNS_RR *smtp_host_addr(char *, int, DSN_BUF *);
+extern DNS_RR *smtp_host_addr(const char *, int, DSN_BUF *);
 extern DNS_RR *smtp_domain_addr(char *, int, DSN_BUF *, int *);
 
 /* LICENSE
index 870c168b55c85dd9ef6ce1ea5ab8ee0795495396..6b7582b0dbae9d22db8bb58ea5e7ccab8139c0f7 100644 (file)
@@ -394,7 +394,7 @@ static void smtp_cleanup_session(SMTP_STATE *state)
     if (THIS_SESSION_IS_EXPIRED)
        smtp_quit(state);                       /* also disables caching */
     if (THIS_SESSION_IS_CACHED
-       /* Redundant tests for safety... */
+    /* Redundant tests for safety... */
        && vstream_ferror(session->stream) == 0
        && vstream_feof(session->stream) == 0) {
        smtp_save_session(state);
@@ -439,12 +439,36 @@ static void smtp_cleanup_session(SMTP_STATE *state)
     request->msg_stats.reuse_count = 0;
 }
 
+static void smtp_cache_policy(SMTP_STATE *state, const char *dest)
+{
+    DELIVER_REQUEST *request = state->request;
+
+    state->misc_flags &= ~SMTP_MISC_FLAG_CONN_CACHE_MASK;
+
+    /*
+     * XXX Disable connection caching when sender-dependent authentication is
+     * enabled. We must not send someone elses mail over an authenticated
+     * connection, and we must not send mail that requires authentication
+     * over a connection that wasn't authenticated.
+     */
+    if (var_smtp_sender_auth)
+       return;
+
+    if (smtp_cache_dest && string_list_match(smtp_cache_dest, dest)) {
+       state->misc_flags |= SMTP_MISC_FLAG_CONN_CACHE_MASK;
+    } else if (var_smtp_cache_demand) {
+       if (request->flags & DEL_REQ_FLAG_SCACHE_LD)
+           state->misc_flags |= SMTP_MISC_FLAG_CONN_LOAD;
+       if (request->flags & DEL_REQ_FLAG_SCACHE_ST)
+           state->misc_flags |= SMTP_MISC_FLAG_CONN_STORE;
+    }
+}
+
 /* smtp_connect_local - connect to local server */
 
 static void smtp_connect_local(SMTP_STATE *state, const char *path)
 {
     const char *myname = "smtp_connect_local";
-    DELIVER_REQUEST *request = state->request;
     SMTP_SESSION *session;
     DSN_BUF *why = state->why;
 
@@ -454,19 +478,8 @@ static void smtp_connect_local(SMTP_STATE *state, const char *path)
      * 
      * Connection cache management is based on the UNIX-domain pathname, without
      * the "unix:" prefix.
-     * 
-     * XXX Disable connection caching when sender-dependent authentication is
-     * enabled. We must not send someone elses mail over an authenticated
-     * connection, and we must not send mail that requires authentication
-     * over a connection that wasn't authenticated.
      */
-#define CAN_ENABLE_CONN_CACHE(request, dest) \
-    (!var_smtp_sender_auth \
-     && ((var_smtp_cache_demand && (request->flags & DEL_REQ_FLAG_SCACHE)) \
-        || (smtp_cache_dest && string_list_match(smtp_cache_dest, dest))))
-
-    if (CAN_ENABLE_CONN_CACHE(request, path))
-       state->misc_flags |= SMTP_MISC_FLAG_CONN_CACHE;
+    smtp_cache_policy(state, path);
 
     /*
      * XXX We assume that the session->addr member refers to a copy of the
@@ -486,7 +499,7 @@ static void smtp_connect_local(SMTP_STATE *state, const char *path)
      * available, "encrypt" may be a sensible policy. Otherwise, we also
      * downgrade "encrypt" to "none", this time just to avoid waste.
      */
-    if ((state->misc_flags & SMTP_MISC_FLAG_CONN_CACHE) == 0
+    if ((state->misc_flags & SMTP_MISC_FLAG_CONN_LOAD) == 0
        || (session = smtp_reuse_addr(state, path, NO_PORT)) == 0)
        session = smtp_connect_unix(path, why, state->misc_flags);
     if ((state->session = session) != 0) {
@@ -796,10 +809,10 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
         * authenticated connection, and we must not send mail that requires
         * authentication over a connection that wasn't authenticated.
         */
-       if (addr_list && (state->misc_flags & SMTP_MISC_FLAG_FIRST_NEXTHOP)
-           && CAN_ENABLE_CONN_CACHE(request, domain)) {
-           state->misc_flags |= SMTP_MISC_FLAG_CONN_CACHE;
-           SET_NEXTHOP_STATE(state, lookup_mx, domain, port);
+       if (addr_list && (state->misc_flags & SMTP_MISC_FLAG_FIRST_NEXTHOP)) {
+           smtp_cache_policy(state, domain);
+           if (state->misc_flags & SMTP_MISC_FLAG_CONN_STORE)
+               SET_NEXTHOP_STATE(state, lookup_mx, domain, port);
        }
 
        /*
@@ -812,7 +825,7 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
         * fall-back destination. smtp_reuse_session() will truncate the
         * address list when either limit is reached.
         */
-       if (addr_list && state->misc_flags & SMTP_MISC_FLAG_CONN_CACHE) {
+       if (addr_list && (state->misc_flags & SMTP_MISC_FLAG_CONN_LOAD)) {
            if (state->cache_used->used > 0)
                smtp_scrub_addr_list(state->cache_used, &addr_list);
            sess_count = addr_count =
@@ -843,7 +856,7 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
            next = addr->next;
            if (++addr_count == var_smtp_mxaddr_limit)
                next = 0;
-           if ((state->misc_flags & SMTP_MISC_FLAG_CONN_CACHE) == 0
+           if ((state->misc_flags & SMTP_MISC_FLAG_CONN_LOAD) == 0
                || addr->pref == domain_best_pref
                || dns_rr_to_pa(addr, &hostaddr) == 0
                || !(session = smtp_reuse_addr(state, hostaddr.buf, port)))
index ddee19f7cc3a14448a21041793b27872bdde056a..24dd01d0cfe42f5c58c0cb4012754aa66f913124 100644 (file)
@@ -1847,8 +1847,13 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state,
                    fail_status = smtp_mesg_fail(state, DSN_BY_LOCAL_MTA,
                                             SMTP_RESP_FAKE(&fake, "5.3.0"),
                                             "unreadable mail queue entry");
-                   if (fail_status == 0)
+                   /* Bailing out, abort stream with prejudice */
+                   (void) vstream_fpurge(session->stream, VSTREAM_PURGE_BOTH);
+                   DONT_USE_DEAD_SESSION;
+                   /* If bounce_append() succeeded, status is still 0 */
+                   if (state->status == 0)
                        (void) mark_corrupt(state->src);
+                   /* Don't override smtp_mesg_fail() here. */
                    RETURN(fail_status);
                }
            } else {
@@ -1899,6 +1904,7 @@ int     smtp_xfer(SMTP_STATE *state)
     int     send_state;
     int     recv_state;
     int     send_name_addr;
+    int     result;
 
     /*
      * Sanity check. Recipients should be unmarked at this point.
@@ -1921,6 +1927,8 @@ int     smtp_xfer(SMTP_STATE *state)
                    "message size %lu exceeds size limit %.0f of server %s",
                       request->data_size, (double) session->size_limit,
                       session->namaddr);
+       /* Redundant. We abort this delivery attempt. */
+       state->misc_flags |= SMTP_MISC_FLAG_COMPLETE_SESSION;
        return (0);
     }
 
@@ -1947,7 +1955,20 @@ int     smtp_xfer(SMTP_STATE *state)
     else
        recv_state = send_state = SMTP_STATE_MAIL;
 
-    return (smtp_loop(state, send_state, recv_state));
+    /*
+     * Remember this session's "normal completion", even if the server 4xx-ed
+     * some or all recipients. Connection or handshake errors with a later MX
+     * host should not cause this destination be marked as unreachable.
+     */
+    result = smtp_loop(state, send_state, recv_state);
+
+    if (result == 0
+    /* Just in case */
+       && vstream_ferror(session->stream) == 0
+       && vstream_feof(session->stream) == 0)
+       state->misc_flags |= SMTP_MISC_FLAG_COMPLETE_SESSION;
+
+    return (result);
 }
 
 /* smtp_rset - send a lone RSET command */
index abb32789b713e782805837d4d1c66f3f51addbbe..97cc8ceb9a3ca36b9211caf0de2556e5fee32493 100644 (file)
 /* .IP flags
 /*     Zero or more of the following:
 /* .RS
-/* .IP SMTP_MISC_FLAG_CONN_CACHE
-/*     Enable SMTP or LMTP connection caching.
+/* .IP SMTP_MISC_FLAG_CONN_LOAD
+/*     Enable re-use of cached SMTP or LMTP connections.
+/* .IP SMTP_MISC_FLAG_CONN_STORE
+/*     Enable saving of cached SMTP or LMTP connections.
 /* .RE
+/*     SMTP_MISC_FLAG_CONN_MASK corresponds with both _LOAD and _STORE.
 /* .IP dest_prop
 /*     Destination specific session properties: the server is the
 /*     best MX host for the current logical destination.
@@ -545,7 +548,7 @@ SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, const char *dest,
     session->sndbufsize = 0;
     session->send_proto_helo = 0;
 
-    if (flags & SMTP_MISC_FLAG_CONN_CACHE)
+    if (flags & SMTP_MISC_FLAG_CONN_STORE)
        CACHE_THIS_SESSION_UNTIL(start + var_smtp_reuse_time);
     else
        DONT_CACHE_THIS_SESSION;
index 761aee970d16690536bdd319e565ff861474f1c3..c8036ffb34168f10d92f043902ef9d795692d6b0 100644 (file)
@@ -244,7 +244,8 @@ static int smtp_bulk_fail(SMTP_STATE *state, int throttle_queue)
            SMTP_RCPT_DROP(state, rcpt);
            state->status |= status;
        }
-       if (throttle_queue && soft_error && request->hop_status == 0)
+       if ((state->misc_flags & SMTP_MISC_FLAG_COMPLETE_SESSION) == 0
+           && throttle_queue && soft_error && request->hop_status == 0)
            request->hop_status = DSN_COPY(&why->dsn);
     }