From f0eb7761f8fb5ea0af89a633b981915c43e25a30 Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Mon, 5 Sep 2011 00:00:00 -0500 Subject: [PATCH] postfix-2.9-20110905 --- postfix/HISTORY | 27 +++++++++++++++++++++++++++ postfix/WISHLIST | 6 +++--- postfix/html/postconf.5.html | 4 +++- postfix/man/man5/postconf.5 | 2 ++ postfix/proto/postconf.proto | 4 +++- postfix/src/global/mail_version.h | 2 +- postfix/src/master/master_avail.c | 4 +++- postfix/src/milter/milter8.c | 4 +++- postfix/src/tls/tls_bio_ops.c | 16 ++++++---------- postfix/src/util/vstream.c | 15 +++++++++++++++ postfix/src/util/vstream_tweak.c | 7 +++++-- 11 files changed, 71 insertions(+), 20 deletions(-) diff --git a/postfix/HISTORY b/postfix/HISTORY index 41e3eeb05..f2ed020e8 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -16911,3 +16911,30 @@ Apologies for any names omitted. treated as ordinary errors, and one corner-case error in TLS timeout handling was fixed before it could cause trouble. File: tls/tls_bio_ops.c. + +20110821-24 + + Cleanup: simplified the TLS read/write deadline implementation, + and documented why this same simplification is not possible + higher-up, at the VSTREAM level. Files: tls/tls_bio_ops.c, + util/vstream.c. + +20110831 + + Bugfix: allow for Milters that send an SMTP server reply + without RFC 3463 enhanced status code. Reported by Vladimir + Vassiliev. File: milter/milter8.c. + +20110902 + + Cleanup: don't log vstream_tweak "connection reset by peer" + errors. File: util/vstream_tweak.c. + +20110903 + + Bugfix: master daemon panic with an "at process limit X" + error, when "postfix reload" reduced the process limit for + some Postfix service from (a value larger than the current + process count for that service) to (a value <= the current + process count), and then a new connection was made to that + service. File: master/master_avail.c. diff --git a/postfix/WISHLIST b/postfix/WISHLIST index 4c2ee9666..f0780e46c 100644 --- a/postfix/WISHLIST +++ b/postfix/WISHLIST @@ -6,6 +6,9 @@ Wish list: Things to do after the stable release: + Investigate viability of Sendmail socket maps (the moral + equivalent of tcp_table(5)), and dns maps. + Make the rules for how to use close-on-exec more explicit. Add SASL / TLS note to BASIC_CONFIGURATION_README.html#relay_from. @@ -292,9 +295,6 @@ Wish list: Find a place to document all the mail routing mechanisms in one place so people can figure out how Postfix works. - Investigate viability of Sendmail socket maps (the moral - equivalent of tcp_table(5)), and dns maps. - The access map BCC action is marked "not stable", perhaps because people would also expect BCC actions in header/body_checks. How much would it take to make the queue file editing code diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index 1914a2ce5..18f375a2f 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -9911,7 +9911,9 @@ uses a generic enhanced status code (X.0.0) instead.

Specify the name of a "type:table" lookup table. The search string is a single SMTP reply line as received from the remote SMTP -server, except that the trailing <CR><LF> are removed.

+server, except that the trailing <CR><LF> are removed. +When the lookup succeeds, the result replaces the single SMTP reply +line.

Examples:

diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index c8467e669..b1b33649f 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -5757,6 +5757,8 @@ uses a generic enhanced status code (X.0.0) instead. Specify the name of a "type:table" lookup table. The search string is a single SMTP reply line as received from the remote SMTP server, except that the trailing are removed. +When the lookup succeeds, the result replaces the single SMTP reply +line. .PP Examples: .PP diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index bf53a24f8..56b36223a 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -13046,7 +13046,9 @@ uses a generic enhanced status code (X.0.0) instead.

Specify the name of a "type:table" lookup table. The search string is a single SMTP reply line as received from the remote SMTP -server, except that the trailing <CR><LF> are removed.

+server, except that the trailing <CR><LF> are removed. +When the lookup succeeds, the result replaces the single SMTP reply +line.

Examples:

diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 013b14363..e861bf990 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 "20110820" +#define MAIL_RELEASE_DATE "20110905" #define MAIL_VERSION_NUMBER "2.9" #ifdef SNAPSHOT diff --git a/postfix/src/master/master_avail.c b/postfix/src/master/master_avail.c index 09baead1f..472b59a1a 100644 --- a/postfix/src/master/master_avail.c +++ b/postfix/src/master/master_avail.c @@ -85,7 +85,9 @@ static void master_avail_event(int event, char *context) if (event == 0) /* XXX Can this happen? */ return; - if (MASTER_THROTTLED(serv)) { /* XXX interface botch */ + /* XXX Should check these when the process or service status is changed. */ + if (!MASTER_LIMIT_OK(serv->max_proc, serv->total_proc) + || MASTER_THROTTLED(serv)) { /* XXX interface botch */ for (n = 0; n < serv->listen_fd_count; n++) event_disable_readwrite(serv->listen_fd[n]); } else { diff --git a/postfix/src/milter/milter8.c b/postfix/src/milter/milter8.c index 35accb022..22d4c419f 100644 --- a/postfix/src/milter/milter8.c +++ b/postfix/src/milter/milter8.c @@ -1255,11 +1255,13 @@ static const char *milter8_event(MILTER8 *milter, int event, MILTER8_DATA_BUFFER, milter->buf, MILTER8_DATA_END) != 0) MILTER8_EVENT_BREAK(milter->def_reply); + /* XXX Enforce this for each line of a multi-line reply. */ if ((STR(milter->buf)[0] != '4' && STR(milter->buf)[0] != '5') || !ISDIGIT(STR(milter->buf)[1]) || !ISDIGIT(STR(milter->buf)[2]) || (STR(milter->buf)[3] != ' ' && STR(milter->buf)[3] != '-') - || STR(milter->buf)[4] != STR(milter->buf)[0]) { + || (ISDIGIT(STR(milter->buf)[4]) + && (STR(milter->buf)[4] != STR(milter->buf)[0]))) { msg_warn("milter %s: malformed reply: %s", milter->m.name, STR(milter->buf)); milter8_conf_error(milter); diff --git a/postfix/src/tls/tls_bio_ops.c b/postfix/src/tls/tls_bio_ops.c index 4d1bf1a41..075b113aa 100644 --- a/postfix/src/tls/tls_bio_ops.c +++ b/postfix/src/tls/tls_bio_ops.c @@ -159,16 +159,14 @@ int tls_bio(int fd, int timeout, TLS_SESS_STATE *TLScontext, int status; int err; int enable_deadline; - struct timeval time_limit; /* initial time limit */ struct timeval time_left; /* amount of time left */ - struct timeval time_entry; /* time of tls_bio() entry */ + struct timeval time_deadline; /* time of deadline */ struct timeval time_now; /* time after SSL_mumble() call */ - struct timeval time_elapsed; /* total elapsed time */ /* * Compensation for interface mis-match: With VSTREAMs, timeout <= 0 - * means wait forever; with the read/write_wait() calls below, we need - * to specify timeout < 0 instead. + * means wait forever; with the read/write_wait() calls below, we need to + * specify timeout < 0 instead. * * Safety: no time limit means no deadline. */ @@ -186,9 +184,8 @@ int tls_bio(int fd, int timeout, TLS_SESS_STATE *TLScontext, enable_deadline = vstream_fstat(TLScontext->stream, VSTREAM_FLAG_DEADLINE); if (enable_deadline) { - time_limit.tv_sec = timeout; - time_limit.tv_usec = 0; - GETTIMEOFDAY(&time_entry); + GETTIMEOFDAY(&time_deadline); + time_deadline.tv_sec += timeout; } } @@ -276,8 +273,7 @@ int tls_bio(int fd, int timeout, TLS_SESS_STATE *TLScontext, case SSL_ERROR_WANT_READ: if (enable_deadline) { GETTIMEOFDAY(&time_now); - timersub(&time_now, &time_entry, &time_elapsed); - timersub(&time_limit, &time_elapsed, &time_left); + timersub(&time_deadline, &time_now, &time_left); timeout = time_left.tv_sec + (time_left.tv_usec > 0); if (timeout <= 0) { errno = ETIMEDOUT; diff --git a/postfix/src/util/vstream.c b/postfix/src/util/vstream.c index 5da2f1598..fb010eed6 100644 --- a/postfix/src/util/vstream.c +++ b/postfix/src/util/vstream.c @@ -699,6 +699,13 @@ static int vstream_fflush_some(VSTREAM *stream, ssize_t to_flush) * When flushing a buffer, allow for partial writes. These can happen * while talking to a network. Update the cached file seek position, if * any. + * + * When deadlines are enabled, we count the elapsed time for each write + * operation instead of simply comparing the time-of-day clock with a + * per-stream deadline. The latter could result in anomalies when an + * application does lengthy processing between write operations. Keep in + * mind that a receiver may not be able to keep up when a sender suddenly + * floods it with a lot of data as it tries to catch up with a deadline. */ for (data = (char *) bp->data, len = to_flush; len > 0; len -= n, data += n) { if (bp->flags & VSTREAM_FLAG_DEADLINE) { @@ -852,6 +859,14 @@ static int vstream_buf_get_ready(VBUF *bp) * Fill the buffer with as much data as we can handle, or with as much * data as is available right now, whichever is less. Update the cached * file seek position, if any. + * + * When deadlines are enabled, we count the elapsed time for each read + * operation instead of simply comparing the time-of-day clock with a + * per-stream deadline. The latter could result in anomalies when an + * application does lengthy processing between read operations. Keep in + * mind that a sender may get blocked, and may not be able to keep up + * when a receiver suddenly wants to read a lot of data as it tries to + * catch up with a deadline. */ if (bp->flags & VSTREAM_FLAG_DEADLINE) { timeout = stream->time_limit.tv_sec + (stream->time_limit.tv_usec > 0); diff --git a/postfix/src/util/vstream_tweak.c b/postfix/src/util/vstream_tweak.c index a9dc8bd1b..83340d237 100644 --- a/postfix/src/util/vstream_tweak.c +++ b/postfix/src/util/vstream_tweak.c @@ -40,6 +40,7 @@ #include #include #include +#include /* Utility library. */ @@ -100,7 +101,8 @@ int vstream_tweak_tcp(VSTREAM *fp) * whatever value was stored last with setsockopt()). */ if ((err = getsockopt(vstream_fileno(fp), IPPROTO_TCP, TCP_MAXSEG, - (char *) &mss, &mss_len)) < 0) { + (char *) &mss, &mss_len)) < 0 + && errno != ECONNRESET) { msg_warn("%s: getsockopt TCP_MAXSEG: %m", myname); return (err); } @@ -131,7 +133,8 @@ int vstream_tweak_tcp(VSTREAM *fp) int nodelay = 1; if ((err = setsockopt(vstream_fileno(fp), IPPROTO_TCP, TCP_NODELAY, - (char *) &nodelay, sizeof(nodelay))) < 0) + (char *) &nodelay, sizeof(nodelay))) < 0 + && errno != ECONNRESET) msg_warn("%s: setsockopt TCP_NODELAY: %m", myname); } #endif