]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.3-20051210
authorWietse Venema <wietse@porcupine.org>
Sat, 10 Dec 2005 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:31:53 +0000 (06:31 +0000)
postfix/HISTORY
postfix/src/global/mail_version.h
postfix/src/smtp/smtp.h
postfix/src/smtp/smtp_connect.c
postfix/src/smtp/smtp_session.c
postfix/src/smtp/smtp_trouble.c

index a80b68ad87aae732ed4eec14325a6d560738358b..e0498678a07cea0b4f14d031f9565d3f1e99348a 100644 (file)
@@ -11543,6 +11543,12 @@ Apologies for any names omitted.
        broken.  This the analog of queue manager bugfix 20051119.
        Files: global/deliver_pass.c.
        
+20051210
+
+       Cleanup: simplified the SMTP/LMTP connection management
+       logic for address list and fallback relay processing.
+       Still need to simplify deferred recipient handling.
+
 Open problems:
 
        "postsuper -r" no longer resets the message arrival time,
index fa0303a7028f0b4dc43ded92a0a1213de53ac2ba..3fbce5fe7b02184801b01a9f49d3b478ac10b7d5 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      "20051209"
+#define MAIL_RELEASE_DATE      "20051210"
 #define MAIL_VERSION_NUMBER    "2.3"
 
 #ifdef SNAPSHOT
index 0448b8a63dbe4d0f70347ecf72651e1a879640b5..2c9b785e3540a7367ed5e6ec03c10ac4a8618cc6 100644 (file)
@@ -78,7 +78,6 @@ typedef struct SMTP_STATE {
      * There is some redundancy for sanity checking. At the end of an SMTP
      * session all recipients should be marked one way or the other.
      */
-    int     final_server;              /* final mail server */
     int     rcpt_left;                 /* recipients left over */
     int     rcpt_drop;                 /* recipients marked as drop */
     int     rcpt_keep;                 /* recipients marked as keep */
@@ -141,6 +140,10 @@ typedef struct SMTP_STATE {
 #define SMTP_MISC_FLAG_LOOP_DETECT     (1<<0)
 #define        SMTP_MISC_FLAG_IN_STARTTLS      (1<<1)
 #define SMTP_MISC_FLAG_USE_LMTP                (1<<2)
+#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)
 
  /*
   * smtp.c
@@ -230,9 +233,6 @@ extern void smtp_session_free(SMTP_SESSION *);
 extern int smtp_session_passivate(SMTP_SESSION *, VSTRING *, VSTRING *);
 extern SMTP_SESSION *smtp_session_activate(int, VSTRING *, VSTRING *);
 
-#define SMTP_SESS_FLAG_NONE    0       /* no options */
-#define SMTP_SESS_FLAG_CACHE   (1<<0)  /* enable session caching */
-
 #ifdef USE_TLS
 extern void smtp_tls_list_init(void);
 
index b9a4a7164fe90eee0b92dd3642c6349f831bfcf7..a3b79866b98715c54ea581ed83a854bd41316bb8 100644 (file)
@@ -476,7 +476,6 @@ static void smtp_connect_local(SMTP_STATE *state, const char *path,
                                       DSN_BUF *why)
 {
     DELIVER_REQUEST *request = state->request;
-    int     sess_flags = SMTP_SESS_FLAG_NONE;
     SMTP_SESSION *session;
 
     /*
@@ -497,23 +496,22 @@ static void smtp_connect_local(SMTP_STATE *state, const char *path,
         || (smtp_cache_dest && string_list_match(smtp_cache_dest, dest))))
 
     if (CAN_ENABLE_CONN_CACHE(request, path))
-       sess_flags |= SMTP_SESS_FLAG_CACHE;
+       state->misc_flags |= SMTP_MISC_FLAG_CONN_CACHE;
 
     /*
      * XXX We assume that the session->addr member refers to a copy of the
      * UNIX-domain pathname, so that smtp_save_session() will cache the
      * connection using the pathname as the physical endpoint name.
      */
-#define NO_MX  0
 #define NO_PORT        0
 
-    if ((sess_flags & SMTP_SESS_FLAG_CACHE) == 0
+    if ((state->misc_flags & SMTP_MISC_FLAG_CONN_CACHE) == 0
        || (session = smtp_reuse_addr(state, path, NO_PORT)) == 0)
-       session = smtp_connect_unix(path, why, sess_flags);
+       session = smtp_connect_unix(path, why, state->misc_flags);
     if ((state->session = session) != 0) {
        session->state = state;
        /* All delivery errors bounce or defer. */
-       state->final_server = 1;
+       state->misc_flags |= SMTP_MISC_FLAG_FINAL_SERVER;
        if ((session->features & SMTP_FEATURE_FROM_CACHE) == 0
            && smtp_helo(state) != 0) {
            if (vstream_ferror(session->stream) == 0
@@ -609,7 +607,6 @@ static int smtp_reuse_session(SMTP_STATE *state, int lookup_mx,
     int     session_count = 0;
     DNS_RR *addr;
     DNS_RR *next;
-    int     saved_final_server = state->final_server;
     MAI_HOSTADDR_STR hostaddr;
     SMTP_SESSION *session;
 
@@ -624,7 +621,9 @@ static int smtp_reuse_session(SMTP_STATE *state, int lookup_mx,
     && (session = smtp_reuse_domain(state, lookup_mx, domain, port)) != 0) {
        session_count = 1;
        smtp_update_addr_list(addr_list, session->addr, session_count);
-       state->final_server = (saved_final_server && *addr_list == 0);
+       if ((state->misc_flags & SMTP_MISC_FLAG_FINAL_NEXTHOP)
+           && *addr_list == 0)
+           state->misc_flags |= SMTP_MISC_FLAG_FINAL_SERVER;
        smtp_xfer(state);
        smtp_cleanup_session(state);
     }
@@ -647,7 +646,9 @@ static int smtp_reuse_session(SMTP_STATE *state, int lookup_mx,
            smtp_update_addr_list(addr_list, session->addr, session_count);
            if (*addr_list == 0)
                next = 0;
-           state->final_server = (saved_final_server && next == 0);
+           if ((state->misc_flags & SMTP_MISC_FLAG_FINAL_NEXTHOP)
+               && next == 0)
+               state->misc_flags |= SMTP_MISC_FLAG_FINAL_SERVER;
            smtp_xfer(state);
            smtp_cleanup_session(state);
        }
@@ -658,16 +659,13 @@ static int smtp_reuse_session(SMTP_STATE *state, int lookup_mx,
 /* smtp_connect_remote - establish remote connection */
 
 static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
-                                       DSN_BUF *why)
+                                       char *def_service, DSN_BUF *why)
 {
     DELIVER_REQUEST *request = state->request;
-    char   *def_service;
     ARGV   *sites;
     char   *dest;
     char  **cpp;
-    int     sess_flags = SMTP_SESS_FLAG_NONE;
     int     non_fallback_sites;
-    int     saved_misc_flags = state->misc_flags;
 
     /*
      * First try to deliver to the indicated destination, then try to deliver
@@ -681,12 +679,8 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
     if (sites->argc == 0)
        msg_panic("null destination: \"%s\"", request->nexthop);
     non_fallback_sites = sites->argc;
-    if ((state->misc_flags & SMTP_MISC_FLAG_USE_LMTP) == 0) {
+    if ((state->misc_flags & SMTP_MISC_FLAG_USE_LMTP) == 0)
        argv_split_append(sites, var_fallback_relay, ", \t\r\n");
-       def_service = "smtp";                   /* XXX ##IPPORT_SMTP? */
-    } else {
-       def_service = var_lmtp_tcp_port;
-    }
 
     /*
      * Don't give up after a hard host lookup error until we have tried the
@@ -707,7 +701,9 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
 #define IS_FALLBACK_RELAY(cpp, sites, non_fallback_sites) \
            (*(cpp) && (cpp) >= (sites)->argv + (non_fallback_sites))
 
-    for (cpp = sites->argv; SMTP_RCPT_LEFT(state) > 0 && (dest = *cpp) != 0; cpp++) {
+    for (cpp = sites->argv, (state->misc_flags |= SMTP_MISC_FLAG_FIRST_NEXTHOP);
+        SMTP_RCPT_LEFT(state) > 0 && (dest = *cpp) != 0;
+        cpp++, (state->misc_flags &= ~SMTP_MISC_FLAG_FIRST_NEXTHOP)) {
        char   *dest_buf;
        char   *domain;
        unsigned port;
@@ -721,7 +717,8 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
        unsigned domain_best_pref;
        MAI_HOSTADDR_STR hostaddr;
 
-       state->misc_flags = saved_misc_flags;
+       if (cpp[1] == 0)
+           state->misc_flags |= SMTP_MISC_FLAG_FINAL_NEXTHOP;
 
        /*
         * Parse the destination. Default is to use the SMTP port. Look up
@@ -739,6 +736,8 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
        if ((state->misc_flags & SMTP_MISC_FLAG_USE_LMTP) == 0) {
            if (ntohs(port) == IPPORT_SMTP)
                state->misc_flags |= SMTP_MISC_FLAG_LOOP_DETECT;
+           else
+               state->misc_flags &= ~SMTP_MISC_FLAG_LOOP_DETECT;
            lookup_mx = (var_disable_dns == 0 && *dest != '[');
        } else
            lookup_mx = 0;
@@ -752,17 +751,15 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
                                         why, &i_am_mx);
            /* If we're MX host, don't connect to non-MX backups. */
            if (i_am_mx)
-               argv_truncate(sites, cpp - sites->argv + 1);
+               state->misc_flags |= SMTP_MISC_FLAG_FINAL_NEXTHOP;
        }
 
        /*
-        * Don't try any backup host if mail loops to myself. That would just
+        * Don't try fall-back hosts if mail loops to myself. That would just
         * make the problem worse.
         */
-       if (addr_list == 0 && smtp_errno == SMTP_ERR_LOOP) {
-           myfree(dest_buf);
-           break;
-       }
+       if (addr_list == 0 && smtp_errno == SMTP_ERR_LOOP)
+           state->misc_flags |= SMTP_MISC_FLAG_FINAL_NEXTHOP;
 
        /*
         * No early loop exit or we have a memory leak with dest_buf.
@@ -794,8 +791,9 @@ 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 (cpp == sites->argv && CAN_ENABLE_CONN_CACHE(request, domain)) {
-           sess_flags |= SMTP_SESS_FLAG_CACHE;
+       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);
        }
 
@@ -809,11 +807,9 @@ 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 && (sess_flags & SMTP_SESS_FLAG_CACHE) != 0) {
+       if (addr_list && state->misc_flags & SMTP_MISC_FLAG_CONN_CACHE) {
            if (state->cache_used->used > 0)
                smtp_scrub_addr_list(state->cache_used, &addr_list);
-           /* Count delivery errors towards the session limit. */
-           state->final_server = (cpp[1] == 0);
            sess_count = addr_count =
                smtp_reuse_session(state, lookup_mx, domain, port,
                                   &addr_list, domain_best_pref);
@@ -842,17 +838,20 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
            next = addr->next;
            if (++addr_count == var_smtp_mxaddr_limit)
                next = 0;
-           if ((sess_flags & SMTP_SESS_FLAG_CACHE) == 0
+           if ((state->misc_flags & SMTP_MISC_FLAG_CONN_CACHE) == 0
                || addr->pref == domain_best_pref
                || dns_rr_to_pa(addr, &hostaddr) == 0
                || !(session = smtp_reuse_addr(state, hostaddr.buf, port)))
-               session = smtp_connect_addr(dest, addr, port, why, sess_flags);
+               session = smtp_connect_addr(dest, addr, port, why,
+                                           state->misc_flags);
            if ((state->session = session) != 0) {
                session->state = state;
                if (addr->pref == domain_best_pref)
                    session->features |= SMTP_FEATURE_BEST_MX;
                /* Don't count handshake errors towards the session limit. */
-               state->final_server = (cpp[1] == 0 && next == 0);
+               if ((state->misc_flags & SMTP_MISC_FLAG_FINAL_NEXTHOP)
+                   && next == 0)
+                   state->misc_flags |= SMTP_MISC_FLAG_FINAL_SERVER;
                if ((session->features & SMTP_FEATURE_FROM_CACHE) == 0
                    && smtp_helo(state) != 0) {
                    if (vstream_ferror(session->stream) == 0
@@ -862,7 +861,9 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
                    /* Do count delivery errors towards the session limit. */
                    if (++sess_count == var_smtp_mxsess_limit)
                        next = 0;
-                   state->final_server = (cpp[1] == 0 && next == 0);
+                   if ((state->misc_flags & SMTP_MISC_FLAG_FINAL_NEXTHOP)
+                       && next == 0)
+                       state->misc_flags |= SMTP_MISC_FLAG_FINAL_SERVER;
                    smtp_xfer(state);
                }
                smtp_cleanup_session(state);
@@ -872,6 +873,8 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
        }
        dns_rr_free(addr_list);
        myfree(dest_buf);
+       if (state->misc_flags & SMTP_MISC_FLAG_FINAL_NEXTHOP)
+           break;
     }
 
     /*
@@ -962,6 +965,8 @@ int     smtp_connect(SMTP_STATE *state)
      * destination to address list, and whether to stop before we reach the
      * end of that list.
      */
+#define DEF_LMTP_SERVICE       var_lmtp_tcp_port
+#define DEF_SMTP_SERVICE       "smtp"
 
     /*
      * With LMTP we have direct-to-host delivery only. The destination may
@@ -973,7 +978,7 @@ int     smtp_connect(SMTP_STATE *state)
        } else {
            if (strncmp(destination, "inet:", 5) == 0)
                destination += 5;
-           smtp_connect_remote(state, destination, why);
+           smtp_connect_remote(state, destination, DEF_LMTP_SERVICE, why);
        }
     }
 
@@ -986,20 +991,27 @@ int     smtp_connect(SMTP_STATE *state)
      * Postfix configurations that have a host with such a name.
      */
     else {
-       smtp_connect_remote(state, destination, why);
+       smtp_connect_remote(state, destination, DEF_SMTP_SERVICE, why);
     }
 
     /*
      * We still need to bounce or defer some left-over recipients: either
      * (SMTP) mail loops or some server was unavailable.
      * 
+     * We could avoid this (and the "final server" complexity) by keeping one
+     * DSN structure per recipient in memory, by updating those in-memory
+     * structures with each delivery attempt, and by always flushing all
+     * deferred recipients at the end. We'd probably still want to bounce
+     * recipients immediately, so we'd end up with another chunk of code for
+     * defer logging only.
+     * 
      * XXX Unlike enhanced status codes, changing a 4xx into 5xx SMTP code is
      * not simply a matter of changing the initial digit. What we're doing
      * here is correct only under specific conditions, such as changing 450
      * into 550 or vice versa.
      */
     if (SMTP_RCPT_LEFT(state) > 0) {
-       state->final_server = 1;                /* XXX */
+       state->misc_flags |= SMTP_MISC_FLAG_FINAL_SERVER;       /* XXX */
        if (smtp_errno == SMTP_ERR_RETRY)
            STR(why->status)[0] = STR(why->dtext)[0] = '4';     /* XXX */
        else
index b5b51471fd844c897637908cc1fcd145e4e7b1a7..ccdb8fdef738f96156df0a168f7dd57f70933536 100644 (file)
 /* .IP flags
 /*     Zero or more of the following:
 /* .RS
-/* .IP SMTP_SESS_FLAG_CACHE
+/* .IP SMTP_MISC_FLAG_CONN_CACHE
 /*     Enable session caching.
 /* .RE
-/* .IP
-/*     The manifest constant SMTP_SESS_FLAG_NONE requests no options.
 /* .IP dest_prop
 /*     Destination specific session properties: the server is the
 /*     best MX host for the current logical destination.
@@ -221,14 +219,17 @@ SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, const char *dest,
     smtp_chat_init(session);
     session->mime_state = 0;
 
-    vstring_sprintf(session->buffer, "%s:%d",
-                   session->namaddr, ntohs(session->port));
-    session->namaddrport = mystrdup(STR(session->buffer));
+    if (session->port) {
+       vstring_sprintf(session->buffer, "%s:%d",
+                       session->namaddr, ntohs(session->port));
+       session->namaddrport = mystrdup(STR(session->buffer));
+    } else
+       session->namaddrport = mystrdup(session->namaddr);
 
     session->sndbufsize = 0;
     session->send_proto_helo = 0;
 
-    if (flags & SMTP_SESS_FLAG_CACHE)
+    if (flags & SMTP_MISC_FLAG_CONN_CACHE)
        CACHE_THIS_SESSION_UNTIL(start + var_smtp_reuse_time);
     else
        DONT_CACHE_THIS_SESSION;
@@ -470,8 +471,10 @@ SMTP_SESSION *smtp_session_activate(int fd, VSTRING *dest_prop,
     /*
      * Allright, bundle up what we have sofar.
      */
+#define NO_FLAGS       0
+
     session = smtp_session_alloc(vstream_fdopen(fd, O_RDWR), dest, host,
-                              addr, port, (time_t) 0, SMTP_SESS_FLAG_NONE);
+                                addr, port, (time_t) 0, NO_FLAGS);
     session->features = (features | SMTP_FEATURE_FROM_CACHE);
     CACHE_THIS_SESSION_UNTIL(expire_time);
     session->reuse_count = ++reuse_count;
index 82429292dddd94fb7eba793422dab66eef67b0bd..4ddef7dcc33b081a9c4a00b4ccc9052a5b7f0d48 100644 (file)
@@ -197,7 +197,7 @@ static int smtp_bulk_fail(SMTP_STATE *state, DSN *dsn, int throttle_queue)
      * delivery to a backup server. Just log something informative to show
      * why we're skipping this host.
      */
-    if (soft_error && state->final_server == 0) {
+    if (soft_error && (state->misc_flags & SMTP_MISC_FLAG_FINAL_SERVER) == 0) {
        msg_info("%s: %s", request->queue_id, dsn->reason);
        for (nrcpt = 0; nrcpt < SMTP_RCPT_LEFT(state); nrcpt++) {
            rcpt = request->rcpt_list.info + nrcpt;
@@ -393,7 +393,7 @@ void    smtp_rcpt_fail(SMTP_STATE *state, RECIPIENT *rcpt, const char *mta_name,
      * for trying other mail servers. Just log something informative to show
      * why we're skipping this recipient now.
      */
-    if (soft_error && state->final_server == 0) {
+    if (soft_error && (state->misc_flags & SMTP_MISC_FLAG_FINAL_SERVER) == 0) {
        msg_info("%s: %s", request->queue_id, dsn.reason);
        SMTP_RCPT_KEEP(state, rcpt);
     }