From: Wietse Venema Date: Sat, 10 Dec 2005 05:00:00 +0000 (-0500) Subject: postfix-2.3-20051210 X-Git-Tag: v2.3-RC1~35 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3c425ec8a5b5fd8eb98e1ef4e9b917b0c6adce63;p=thirdparty%2Fpostfix.git postfix-2.3-20051210 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index a80b68ad8..e0498678a 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -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, diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index fa0303a70..3fbce5fe7 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -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 diff --git a/postfix/src/smtp/smtp.h b/postfix/src/smtp/smtp.h index 0448b8a63..2c9b785e3 100644 --- a/postfix/src/smtp/smtp.h +++ b/postfix/src/smtp/smtp.h @@ -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); diff --git a/postfix/src/smtp/smtp_connect.c b/postfix/src/smtp/smtp_connect.c index b9a4a7164..a3b79866b 100644 --- a/postfix/src/smtp/smtp_connect.c +++ b/postfix/src/smtp/smtp_connect.c @@ -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 diff --git a/postfix/src/smtp/smtp_session.c b/postfix/src/smtp/smtp_session.c index b5b51471f..ccdb8fdef 100644 --- a/postfix/src/smtp/smtp_session.c +++ b/postfix/src/smtp/smtp_session.c @@ -66,11 +66,9 @@ /* .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; diff --git a/postfix/src/smtp/smtp_trouble.c b/postfix/src/smtp/smtp_trouble.c index 82429292d..4ddef7dcc 100644 --- a/postfix/src/smtp/smtp_trouble.c +++ b/postfix/src/smtp/smtp_trouble.c @@ -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); }