Postfix 2.0.11 introduced a workaround for a Solaris bug that randomly locked up an SMTP server process until it was killed by the watchdog timer. Unfortunately the 2.0.11 workaround triggers a Solaris bug that randomly breaks SMTP sessions with "lost connection after DATA". Postfix 2.0.15 works around both Solaris bugs. Prereq: ""2.0.14" diff -cr /tmp/postfix-2.0.14/src/global/mail_version.h ./src/global/mail_version.h *** /tmp/postfix-2.0.14/src/global/mail_version.h Tue Aug 12 11:18:27 2003 --- ./src/global/mail_version.h Fri Sep 5 19:42:38 2003 *************** *** 20,29 **** * Patches change the patchlevel and the release date. Snapshots change the * release date only, unless they include the same bugfix as a patch release. */ ! #define MAIL_RELEASE_DATE "20030812" #define VAR_MAIL_VERSION "mail_version" ! #define DEF_MAIL_VERSION "2.0.14" extern char *var_mail_version; /* --- 20,29 ---- * Patches change the patchlevel and the release date. Snapshots change the * release date only, unless they include the same bugfix as a patch release. */ ! #define MAIL_RELEASE_DATE "20030905" #define VAR_MAIL_VERSION "mail_version" ! #define DEF_MAIL_VERSION "2.0.15" extern char *var_mail_version; /* diff -cr /tmp/postfix-2.0.14/HISTORY ./HISTORY *** /tmp/postfix-2.0.14/HISTORY Tue Aug 12 11:09:51 2003 --- ./HISTORY Fri Sep 5 19:41:49 2003 *************** *** 7865,7870 **** --- 7865,7877 ---- formatted numerical port. Files: util/find_inet.c, smtp/smtp_connect.c, lmtp/lmtp_connect.c. + 20030905 + + Workaround: Solaris 8 select() claims that a non-blocking + socket is readable and then read() fails with EAGAIN. Files: + util/timed_read.c and as precautionary measure, + util/timed_write.c. + Open problems: Doc: mention the proxy_interfaces parameter everywhere the diff -cr /tmp/postfix-2.0.14/conf/main.cf ./conf/main.cf *** /tmp/postfix-2.0.14/conf/main.cf Wed Jul 30 23:08:28 2003 --- ./conf/main.cf Fri Sep 5 20:30:35 2003 *************** *** 147,152 **** --- 147,155 ---- # a name matches a lookup key (the right-hand side is ignored). # Continue long lines by starting the next line with whitespace. # + # DO NOT LIST RELAY DESTINATIONS IN MYDESTINATION. + # SPECIFY RELAY DESTINATIONS IN RELAY_DOMAINS. + # # See also below, section "REJECTING MAIL FOR UNKNOWN LOCAL USERS". # #mydestination = $myhostname, localhost.$mydomain diff -cr /tmp/postfix-2.0.14/conf/sample-pcre-access.cf ./conf/sample-pcre-access.cf *** /tmp/postfix-2.0.14/conf/sample-pcre-access.cf Tue Aug 12 12:40:11 2003 --- ./conf/sample-pcre-access.cf Wed Aug 13 12:15:53 2003 *************** *** 9,17 **** # the forward slash is used). The regular expression can contain # whitespace. # - # When the regular expression is prefixed by `!', the pattern - # succeeds when it does not match. - # # By default, matching is case-INsensitive, although following # the second slash with an 'i' will reverse this. Other flags are # supported, but the only other useful one is 'U', which makes --- 9,14 ---- diff -cr /tmp/postfix-2.0.14/conf/sample-pcre-body.cf ./conf/sample-pcre-body.cf *** /tmp/postfix-2.0.14/conf/sample-pcre-body.cf Tue Aug 12 12:41:49 2003 --- ./conf/sample-pcre-body.cf Wed Aug 13 12:16:11 2003 *************** *** 11,19 **** # the forward slash is used). The regular expression can contain # whitespace. # - # When the regular expression is prefixed by `!', the pattern - # succeeds when it does not match. - # # By default, matching is case-INsensitive, although following # the second slash with an 'i' will reverse this. Other flags are # supported, but the only other useful one is 'U', which makes --- 11,16 ---- diff -cr /tmp/postfix-2.0.14/conf/sample-pcre-header.cf ./conf/sample-pcre-header.cf *** /tmp/postfix-2.0.14/conf/sample-pcre-header.cf Tue Aug 12 12:46:28 2003 --- ./conf/sample-pcre-header.cf Wed Aug 13 12:16:21 2003 *************** *** 12,20 **** # the forward slash is used). The regular expression can contain # whitespace. # - # When the regular expression is prefixed by `!', the pattern - # succeeds when it does not match. - # # By default, matching is case-INsensitive, although following # the second slash with an 'i' will reverse this. Other flags are # supported, but the only other useful one is 'U', which makes --- 12,17 ---- diff -cr /tmp/postfix-2.0.14/html/faq.html ./html/faq.html *** /tmp/postfix-2.0.14/html/faq.html Thu Aug 7 17:25:57 2003 --- ./html/faq.html Mon Aug 25 16:50:37 2003 *************** *** 1441,1447 ****

You run the Postfix SMTP server inside a chroot jail for ! extra security, but some configuration files are missing. In order to run inside a chroot jail, the Postfix SMTP client and server need copies of system configuration files inside the Postfix queue directory. The exact list of files is very system dependent, but --- 1441,1460 ----

You run the Postfix SMTP server inside a chroot jail for ! extra security, but some configuration files are missing or have ! incorrect information. The command "postfix check" will report ! what files may have incorrect information. For example: ! !

!
! warning: /var/spool/postfix/etc/resolv.conf and /etc/resolv.conf differ
! warning: /var/spool/postfix/etc/localtime and /etc/localtime differ
! 
!
! !

! ! In order to run inside a chroot jail, the Postfix SMTP client and server need copies of system configuration files inside the Postfix queue directory. The exact list of files is very system dependent, but *************** *** 1776,1782 **** Check out your Postfix master.cf file. If the SMTP client runs chrooted, then it needs a bunch of files inside the Postfix queue directory. Examples are in the source distribution in the ! examples subdirectory. --- 1789,1796 ---- Check out your Postfix master.cf file. If the SMTP client runs chrooted, then it needs a bunch of files inside the Postfix queue directory. Examples are in the source distribution in the ! examples subdirectory. See also the other FAQ entry on ! name service trouble. diff -cr /tmp/postfix-2.0.14/html/uce.html ./html/uce.html *** /tmp/postfix-2.0.14/html/uce.html Tue Aug 12 13:02:04 2003 --- ./html/uce.html Mon Aug 25 09:54:11 2003 *************** *** 348,355 ****

smtpd_client_restrictions = hash:/etc/postfix/access, reject_rbl_client relays.ordb.org (free service) !
smtpd_client_restrictions = hash:/etc/postfix/access, ! reject_rhsbl_client dsn.rfc-ignorant.org (free service)
smtpd_client_restrictions = permit_mynetworks, reject_unknown_client --- 348,355 ----
smtpd_client_restrictions = hash:/etc/postfix/access, reject_rbl_client relays.ordb.org (free service) !
smtpd_sender_restrictions = hash:/etc/postfix/access, ! reject_rhsbl_sender dsn.rfc-ignorant.org (free service)
smtpd_client_restrictions = permit_mynetworks, reject_unknown_client *************** *** 934,952 **** !
Recipient domain matches Recipient lookup table !
$mydestination or ! $inet_interfaces ! $local_recipient_maps !
$virtual_alias_domains $virtual_alias_maps !
$virtual_mailbox_domains $virtual_mailbox_maps !
$relay_domains $relay_recipient_maps !
--- 934,952 ---- ! ! ! ! ! ! !
Recipient domain matches Recipient lookup table
$mydestination or ! $inet_interfaces$local_recipient_maps
$virtual_alias_domains $virtual_alias_maps
$virtual_mailbox_domains $virtual_mailbox_maps
$relay_domains $relay_recipient_maps
diff -cr /tmp/postfix-2.0.14/src/util/timed_read.c ./src/util/timed_read.c *** /tmp/postfix-2.0.14/src/util/timed_read.c Thu May 4 13:56:57 2000 --- ./src/util/timed_read.c Fri Sep 5 19:02:57 2003 *************** *** 48,70 **** #include #include /* Utility library. */ ! #include "iostuff.h" /* timed_read - read with deadline */ int timed_read(int fd, void *buf, unsigned len, int timeout, void *unused_context) { /* * Wait for a limited amount of time for something to happen. If nothing * happens, report an ETIMEDOUT error. */ ! if (timeout > 0 && read_wait(fd, timeout) < 0) ! return (-1); ! else ! return (read(fd, buf, len)); } --- 48,83 ---- #include #include + #include /* Utility library. */ ! #include ! #include /* timed_read - read with deadline */ int timed_read(int fd, void *buf, unsigned len, int timeout, void *unused_context) { + int ret; /* * Wait for a limited amount of time for something to happen. If nothing * happens, report an ETIMEDOUT error. + * + * XXX Solaris 8 read() fails with EAGAIN after read-select() returns + * success. */ ! for (;;) { ! if (timeout > 0 && read_wait(fd, timeout) < 0) ! return (-1); ! if ((ret = read(fd, buf, len)) < 0 && timeout > 0 && errno == EAGAIN) { ! msg_warn("read() returns EAGAIN on a readable file descriptor!"); ! msg_warn("pausing to avoid going into a tight select/read loop!"); ! sleep(1); ! } else { ! return (ret); ! } ! } } diff -cr /tmp/postfix-2.0.14/src/util/timed_write.c ./src/util/timed_write.c *** /tmp/postfix-2.0.14/src/util/timed_write.c Thu May 4 13:57:08 2000 --- ./src/util/timed_write.c Fri Sep 5 19:02:16 2003 *************** *** 48,70 **** #include #include /* Utility library. */ ! #include "iostuff.h" /* timed_write - write with deadline */ int timed_write(int fd, void *buf, unsigned len, int timeout, void *unused_context) { /* * Wait for a limited amount of time for something to happen. If nothing * happens, report an ETIMEDOUT error. */ ! if (timeout > 0 && write_wait(fd, timeout) < 0) ! return (-1); ! else ! return (write(fd, buf, len)); } --- 48,89 ---- #include #include + #include /* Utility library. */ ! #include ! #include /* timed_write - write with deadline */ int timed_write(int fd, void *buf, unsigned len, int timeout, void *unused_context) { + int ret; /* * Wait for a limited amount of time for something to happen. If nothing * happens, report an ETIMEDOUT error. + * + * XXX Solaris 8 read() fails with EAGAIN after read-select() returns + * success. The code below exists just in case their write implementation + * is equally broken. + * + * This condition may also be found on systems where select() returns + * success on pipes with less than PIPE_BUF bytes of space, and with + * badly designed software where multiple writers are fighting for access + * to the same resource. */ ! for (;;) { ! if (timeout > 0 && write_wait(fd, timeout) < 0) ! return (-1); ! if ((ret = write(fd, buf, len)) < 0 && timeout > 0 && errno == EAGAIN) { ! msg_warn("write() returns EAGAIN on a writable file descriptor!"); ! msg_warn("pausing to avoid going into a tight select/write loop!"); ! sleep(1); ! } else { ! return (ret); ! } ! } }