From: Wietse Venema Protocol names are ESMTP or SMTP. Protocol states are CONNECT, EHLO, HELO, MAIL, RCPT,
- DATA, END-OF-DATA, VRFY or ETRN; these are the SMTP protocol
+ DATA, END-OF-MESSAGE, VRFY or ETRN; these are the SMTP protocol
states where
the Postfix SMTP server makes an OK/REJECT/HOLD/etc. decision.
An SMTP client may make up to $smtpd_client_message_rate_limit +message delivery requests per unit time (default: no limit).
+ +An SMTP client may send up to $smtpd_client_recipient_rate_limit +recipient addresses per unit time (default: no limit).
+An SMTP client may make up to $smtpd_client_connection_rate_limit connections per unit time (default: no limit).
These limits are not applied to SMTP clients in the networks -specified with $smtpd_client_connection_limit_exceptions (default: +specified with $smtpd_client_event_limit_exceptions (default: clients in $mynetworks may make an unlimited number of connections).
The anvil_rate_time_unit parameter specifies the time diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index 71800a22c..c9d1260c1 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -2546,7 +2546,7 @@ home directory.
-Specify a pathname ending "/" for qmail-style delivery. +Specify a pathname ending in "/" for qmail-style delivery.
diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index 4e3570cd5..3447ab77f 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -514,7 +514,7 @@ result is ignored). Continue long lines by starting the next line with whitespace. .PP Note: IP version 6 address information must be specified inside -[] in the authorized_verp_clients value, and in files +[] in the authorized_verp_clients value, and in files specified with "/file/name". IP version 6 addresses contain the ":" character, and would otherwise be confused with a "type:table" pattern. @@ -1180,7 +1180,7 @@ is unavailable. In main.cf specify "relay_transport = relay", .IP \(bu In master.cf specify "-o fallback_relay =" (i.e., empty) at -the end of the relay entry. +the end of the relay entry. .IP \(bu In transport maps, specify "relay:\fInexthop...\fR" as the right-hand side for backup or primary MX domain entries. @@ -1326,7 +1326,7 @@ This feature is available in Postfix 2.0 and later. Optional pathname of a mailbox file relative to a \fBlocal\fR(8) user's home directory. .PP -Specify a pathname ending "/" for qmail-style delivery. +Specify a pathname ending in "/" for qmail-style delivery. .PP The precedence of \fBlocal\fR(8) delivery features from high to low is: aliases, .forward files, mailbox_transport, mailbox_command_maps, @@ -1389,11 +1389,11 @@ The network interface addresses that this mail system receives mail on. Specify "all" to receive mail on all network interfaces (default), and "loopback-only" to receive mail on loopback network interfaces only (Postfix 2.2 and later). The -parameter also controls delivery of mail to user@[ip.address]. +parameter also controls delivery of mail to user@[ip.address]. .PP Note 1: you need to stop and start Postfix when this parameter changes. .PP -Note 2: address information may be enclosed inside [], +Note 2: address information may be enclosed inside [], but this form is not recommended here. .PP When inet_interfaces specifies just one IPv4 and/or IPv6 address @@ -2347,7 +2347,7 @@ first match. Specify "!pattern" to exclude an address or network block from the list. .PP Note: IP version 6 address information must be specified inside -[] in the mynetworks value, and in files specified with +[] in the mynetworks value, and in files specified with "/file/name". IP version 6 addresses contain the ":" character, and would otherwise be confused with a "type:table" pattern. .PP @@ -3166,7 +3166,7 @@ automatically used as the smtp_bind_address. This supports virtual IP hosting, but can be a problem on multi-homed firewalls. See the inet_interfaces documentation for more detail. .PP -Note 2: address information may be enclosed inside [], +Note 2: address information may be enclosed inside [], but this form is not recommended here. .SH smtp_bind_address6 (default: empty) An optional numerical network address that the SMTP client should @@ -3193,7 +3193,7 @@ automatically used as the smtp_bind_address6. This supports virtual IP hosting, but can be a problem on multi-homed firewalls. See the inet_interfaces documentation for more detail. .PP -Note 2: address information may be enclosed inside [], +Note 2: address information may be enclosed inside [], but this form is not recommended here. .SH smtp_connect_timeout (default: 30s) The SMTP client time limit for completing a TCP connection, or @@ -3839,7 +3839,7 @@ result is ignored). Continue long lines by starting the next line with whitespace. .PP Note: IP version 6 address information must be specified inside -[] in the smtpd_authorized_verp_clients value, and in +[] in the smtpd_authorized_verp_clients value, and in files specified with "/file/name". IP version 6 addresses contain the ":" character, and would otherwise be confused with a "type:table" pattern. @@ -3865,7 +3865,7 @@ result is ignored). Continue long lines by starting the next line with whitespace. .PP Note: IP version 6 address information must be specified inside -[] in the smtpd_authorized_xclient_hosts value, and in +[] in the smtpd_authorized_xclient_hosts value, and in files specified with "/file/name". IP version 6 addresses contain the ":" character, and would otherwise be confused with a "type:table" pattern. @@ -3890,7 +3890,7 @@ result is ignored). Continue long lines by starting the next line with whitespace. .PP Note: IP version 6 address information must be specified inside -[] in the smtpd_authorized_xforward_hosts value, and in +[] in the smtpd_authorized_xforward_hosts value, and in files specified with "/file/name". IP version 6 addresses contain the ":" character, and would otherwise be confused with a "type:table" pattern. @@ -3955,7 +3955,7 @@ list of network blocks, hostnames or .domain names (the initial dot causes the domain to match any name below it). .PP Note: IP version 6 address information must be specified inside -[] in the smtpd_client_event_limit_exceptions value, and +[] in the smtpd_client_event_limit_exceptions value, and in files specified with "/file/name". IP version 6 addresses contain the ":" character, and would otherwise be confused with a "type:table" pattern. @@ -4733,7 +4733,7 @@ matches a lookup string (the lookup result is ignored). Continue long lines by starting the next line with whitespace. .PP Note: IP version 6 address information must be specified inside -[] in the smtpd_sasl_exceptions_networks value, and in +[] in the smtpd_sasl_exceptions_networks value, and in files specified with "/file/name". IP version 6 addresses contain the ":" character, and would otherwise be confused with a "type:table" pattern. diff --git a/postfix/mantools/postconf2man b/postfix/mantools/postconf2man index acb182f35..4b83cb519 100755 --- a/postfix/mantools/postconf2man +++ b/postfix/mantools/postconf2man @@ -63,6 +63,8 @@ while(<>) { $block =~ s/
/\n.na\n.nf\n.in +4\n/g; $block =~ s/<\/blockquote>/\n.in -4\n.fi\n.ad\n/g; $block =~ s/\n
/\n.br\n/g; diff --git a/postfix/proto/SMTPD_POLICY_README.html b/postfix/proto/SMTPD_POLICY_README.html index dade4b8fc..d745a08fb 100644 --- a/postfix/proto/SMTPD_POLICY_README.html +++ b/postfix/proto/SMTPD_POLICY_README.html @@ -146,7 +146,7 @@ size=12345Protocol names are ESMTP or SMTP.
Protocol states are CONNECT, EHLO, HELO, MAIL, RCPT, - DATA, END-OF-DATA, VRFY or ETRN; these are the SMTP protocol + DATA, END-OF-MESSAGE, VRFY or ETRN; these are the SMTP protocol states where the Postfix SMTP server makes an OK/REJECT/HOLD/etc. decision.
diff --git a/postfix/proto/TUNING_README.html b/postfix/proto/TUNING_README.html index 43eb87784..9882044aa 100644 --- a/postfix/proto/TUNING_README.html +++ b/postfix/proto/TUNING_README.html @@ -242,11 +242,17 @@ traffic: mail will suffer grotesque delays if you do so. simultaneous connections (default: 50). This is half the default process limit. +An SMTP client may make up to $smtpd_client_message_rate_limit +message delivery requests per unit time (default: no limit).
+ +An SMTP client may send up to $smtpd_client_recipient_rate_limit +recipient addresses per unit time (default: no limit).
+An SMTP client may make up to $smtpd_client_connection_rate_limit connections per unit time (default: no limit).
These limits are not applied to SMTP clients in the networks -specified with $smtpd_client_connection_limit_exceptions (default: +specified with $smtpd_client_event_limit_exceptions (default: clients in $mynetworks may make an unlimited number of connections).
The anvil_rate_time_unit parameter specifies the time diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index 83eedcdda..3ab5bd2c3 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -1524,7 +1524,7 @@ home directory.
-Specify a pathname ending "/" for qmail-style delivery. +Specify a pathname ending in "/" for qmail-style delivery.
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index d11dbc9a6..5fcf512bc 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,8 +20,8 @@ * Patches change the patchlevel and the release date. Snapshots change the * release date only. */ -#define MAIL_RELEASE_DATE "20050621" -#define MAIL_VERSION_NUMBER "2.2.4" +#define MAIL_RELEASE_DATE "20050719" +#define MAIL_VERSION_NUMBER "2.2.5" #define VAR_MAIL_VERSION "mail_version" #ifdef SNAPSHOT diff --git a/postfix/src/global/scache_clnt.c b/postfix/src/global/scache_clnt.c index 9c1e482df..f8098eea3 100644 --- a/postfix/src/global/scache_clnt.c +++ b/postfix/src/global/scache_clnt.c @@ -25,6 +25,7 @@ /* Upper bound on the time that a connection is allowed to persist. /* DIAGNOSTICS /* Fatal error: memory allocation problem; +/* warning: communication error; /* panic: internal consistency failure. /* SEE ALSO /* scache(3), generic session cache API @@ -73,6 +74,8 @@ typedef struct { #define STR(x) vstring_str(x) +#define SCACHE_MAX_TRIES 2 + /* scache_clnt_save_endp - save endpoint */ static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl, @@ -83,6 +86,7 @@ static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl, const char *myname = "scache_clnt_save_endp"; VSTREAM *stream; int status; + int tries; if (msg_verbose) msg_info("%s: endp=%s prop=%s fd=%d", @@ -95,11 +99,11 @@ static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl, msg_panic("%s: bad endp_ttl: %d", myname, endp_ttl); /* - * Keep trying until we get a complete response. The session cache - * service is CPU bound and making the client asynchronous would just - * complicate the code. + * Try a few times before disabling the cache. We use synchronous calls; + * the session cache service is CPU bound and making the client + * asynchronous would just complicate the code. */ - for (;;) { + for (tries = 0; sp->clnt_stream != 0 ; tries++) { stream = clnt_stream_access(sp->clnt_stream); errno = 0; if (attr_print(stream, ATTR_FLAG_NONE, @@ -121,14 +125,26 @@ static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl, if (msg_verbose || (errno != EPIPE && errno != ENOENT)) msg_warn("problem talking to service %s: %m", VSTREAM_PATH(stream)); + /* Give up or recover. */ } else { - if (close(fd) < 0) - msg_warn("%s: close(%d): %m", myname, fd); + if (msg_verbose && status != 0) + msg_warn("%s: descriptor save failed with status %d", + myname, status); + break; + } + /* Give up or recover. */ + if (tries >= SCACHE_MAX_TRIES - 1) { + msg_warn("disabling connection caching"); + clnt_stream_free(sp->clnt_stream); + sp->clnt_stream = 0; break; } sleep(1); /* XXX make configurable */ clnt_stream_recover(sp->clnt_stream); } + /* Always close the descriptor before returning. */ + if (close(fd) < 0) + msg_warn("%s: close(%d): %m", myname, fd); } /* scache_clnt_find_endp - look up cached session */ @@ -140,14 +156,15 @@ static int scache_clnt_find_endp(SCACHE *scache, const char *endp_label, const char *myname = "scache_clnt_find_endp"; VSTREAM *stream; int status; + int tries; int fd; /* - * Keep trying until we get a complete response. The session cache - * service is CPU bound and making the client asynchronous would just - * complicate the code. + * Try a few times before disabling the cache. We use synchronous calls; + * the session cache service is CPU bound and making the client + * asynchronous would just complicate the code. */ - for (;;) { + for (tries = 0; sp->clnt_stream != 0 ; tries++) { stream = clnt_stream_access(sp->clnt_stream); errno = 0; if (attr_print(stream, ATTR_FLAG_NONE, @@ -158,36 +175,51 @@ static int scache_clnt_find_endp(SCACHE *scache, const char *endp_label, || attr_scan(stream, ATTR_FLAG_STRICT, ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, ATTR_TYPE_STR, MAIL_ATTR_PROP, endp_prop, - ATTR_TYPE_END) != 2 - || (status == 0 - && ( + ATTR_TYPE_END) != 2) { + if (msg_verbose || (errno != EPIPE && errno != ENOENT)) + msg_warn("problem talking to service %s: %m", + VSTREAM_PATH(stream)); + /* Give up or recover. */ + } else if (status != 0) { + if (msg_verbose) + msg_info("%s: not found: %s", myname, endp_label); + return (-1); + } else if ( #ifdef CANT_WRITE_BEFORE_SENDING_FD - attr_print(stream, ATTR_FLAG_NONE, - ATTR_TYPE_STR, MAIL_ATTR_DUMMY, "", - ATTR_TYPE_END) != 0 - || vstream_fflush(stream) != 0 - || read_wait(vstream_fileno(stream), - stream->timeout) < 0 || /* XXX */ + attr_print(stream, ATTR_FLAG_NONE, + ATTR_TYPE_STR, MAIL_ATTR_DUMMY, "", + ATTR_TYPE_END) != 0 + || vstream_fflush(stream) != 0 + || read_wait(vstream_fileno(stream), + stream->timeout) < 0 || /* XXX */ #endif - (fd = LOCAL_RECV_FD(vstream_fileno(stream))) < 0))) { + (fd = LOCAL_RECV_FD(vstream_fileno(stream))) < 0) { if (msg_verbose || (errno != EPIPE && errno != ENOENT)) msg_warn("problem talking to service %s: %m", VSTREAM_PATH(stream)); + /* Give up or recover. */ } else { - break; +#ifdef MUST_READ_AFTER_SENDING_FD + (void) attr_print(stream, ATTR_FLAG_NONE, + ATTR_TYPE_STR, MAIL_ATTR_DUMMY, "", + ATTR_TYPE_END); + (void) vstream_fflush(stream); +#endif + if (msg_verbose) + msg_info("%s: endp=%s prop=%s fd=%d", + myname, endp_label, STR(endp_prop), fd); + return (fd); + } + /* Give up or recover. */ + if (tries >= SCACHE_MAX_TRIES - 1) { + msg_warn("disabling connection caching"); + clnt_stream_free(sp->clnt_stream); + sp->clnt_stream = 0; + return (-1); } sleep(1); /* XXX make configurable */ clnt_stream_recover(sp->clnt_stream); } - - if (status == 0) { - if (msg_verbose) - msg_info("%s: endp=%s prop=%s fd=%d", - myname, endp_label, STR(endp_prop), fd); - return (fd); - } - if (msg_verbose) - msg_info("%s: not found: %s", myname, endp_label); return (-1); } @@ -202,6 +234,7 @@ static void scache_clnt_save_dest(SCACHE *scache, int dest_ttl, const char *myname = "scache_clnt_save_dest"; VSTREAM *stream; int status; + int tries; if (msg_verbose) msg_info("%s: dest_label=%s dest_prop=%s endp_label=%s", @@ -214,11 +247,11 @@ static void scache_clnt_save_dest(SCACHE *scache, int dest_ttl, msg_panic("%s: bad dest_ttl: %d", myname, dest_ttl); /* - * Keep trying until we get a complete response. The session cache - * service is CPU bound and making the client asynchronous would just - * complicate the code. + * Try a few times before disabling the cache. We use synchronous calls; + * the session cache service is CPU bound and making the client + * asynchronous would just complicate the code. */ - for (;;) { + for (tries = 0; sp->clnt_stream != 0 ; tries++) { stream = clnt_stream_access(sp->clnt_stream); errno = 0; if (attr_print(stream, ATTR_FLAG_NONE, @@ -235,7 +268,18 @@ static void scache_clnt_save_dest(SCACHE *scache, int dest_ttl, if (msg_verbose || (errno != EPIPE && errno != ENOENT)) msg_warn("problem talking to service %s: %m", VSTREAM_PATH(stream)); + /* Give up or recover. */ } else { + if (msg_verbose && status != 0) + msg_warn("%s: destination save failed with status %d", + myname, status); + break; + } + /* Give up or recover. */ + if (tries >= SCACHE_MAX_TRIES - 1) { + msg_warn("disabling connection caching"); + clnt_stream_free(sp->clnt_stream); + sp->clnt_stream = 0; break; } sleep(1); /* XXX make configurable */ @@ -253,14 +297,15 @@ static int scache_clnt_find_dest(SCACHE *scache, const char *dest_label, const char *myname = "scache_clnt_find_dest"; VSTREAM *stream; int status; + int tries; int fd; /* - * Keep trying until we get a complete response. The session cache - * service is CPU bound and making the client asynchronous would just - * complicate the code. + * Try a few times before disabling the cache. We use synchronous calls; + * the session cache service is CPU bound and making the client + * asynchronous would just complicate the code. */ - for (;;) { + for (tries = 0; sp->clnt_stream != 0 ; tries++) { stream = clnt_stream_access(sp->clnt_stream); errno = 0; if (attr_print(stream, ATTR_FLAG_NONE, @@ -272,37 +317,51 @@ static int scache_clnt_find_dest(SCACHE *scache, const char *dest_label, ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, ATTR_TYPE_STR, MAIL_ATTR_PROP, dest_prop, ATTR_TYPE_STR, MAIL_ATTR_PROP, endp_prop, - ATTR_TYPE_END) != 3 - || (status == 0 - && ( + ATTR_TYPE_END) != 3) { + if (msg_verbose || (errno != EPIPE && errno != ENOENT)) + msg_warn("problem talking to service %s: %m", + VSTREAM_PATH(stream)); + /* Give up or recover. */ + } else if (status != 0) { + if (msg_verbose) + msg_info("%s: not found: %s", myname, dest_label); + return (-1); + } else if ( #ifdef CANT_WRITE_BEFORE_SENDING_FD - attr_print(stream, ATTR_FLAG_NONE, - ATTR_TYPE_STR, MAIL_ATTR_DUMMY, "", - ATTR_TYPE_END) != 0 - || vstream_fflush(stream) != 0 - || read_wait(vstream_fileno(stream), - stream->timeout) < 0 || /* XXX */ + attr_print(stream, ATTR_FLAG_NONE, + ATTR_TYPE_STR, MAIL_ATTR_DUMMY, "", + ATTR_TYPE_END) != 0 + || vstream_fflush(stream) != 0 + || read_wait(vstream_fileno(stream), + stream->timeout) < 0 || /* XXX */ #endif - (fd = LOCAL_RECV_FD(vstream_fileno(stream))) < 0))) { + (fd = LOCAL_RECV_FD(vstream_fileno(stream))) < 0) { if (msg_verbose || (errno != EPIPE && errno != ENOENT)) msg_warn("problem talking to service %s: %m", VSTREAM_PATH(stream)); + /* Give up or recover. */ } else { - break; +#ifdef MUST_READ_AFTER_SENDING_FD + (void) attr_print(stream, ATTR_FLAG_NONE, + ATTR_TYPE_STR, MAIL_ATTR_DUMMY, "", + ATTR_TYPE_END); + (void) vstream_fflush(stream); +#endif + if (msg_verbose) + msg_info("%s: dest=%s dest_prop=%s endp_prop=%s fd=%d", + myname, dest_label, STR(dest_prop), STR(endp_prop), fd); + return (fd); + } + /* Give up or recover. */ + if (tries >= SCACHE_MAX_TRIES - 1) { + msg_warn("disabling connection caching"); + clnt_stream_free(sp->clnt_stream); + sp->clnt_stream = 0; + return (-1); } sleep(1); /* XXX make configurable */ clnt_stream_recover(sp->clnt_stream); } - - if (status == 0) { - if (msg_verbose) - msg_info("%s: dest=%s dest_prop=%s endp_prop=%s fd=%d", - myname, dest_label, STR(dest_prop), STR(endp_prop), fd); - return (fd); - } - if (msg_verbose) - msg_info("%s: not found: %s", myname, dest_label); - return (-1); } @@ -322,7 +381,8 @@ static void scache_clnt_free(SCACHE *scache) { SCACHE_CLNT *sp = (SCACHE_CLNT *) scache; - clnt_stream_free(sp->clnt_stream); + if (sp->clnt_stream) + clnt_stream_free(sp->clnt_stream); #ifdef CANT_WRITE_BEFORE_SENDING_FD vstring_free(sp->dummy); #endif @@ -342,6 +402,7 @@ SCACHE *scache_clnt_create(const char *server, int idle_limit, int ttl_limit) sp->scache->size = scache_clnt_size; sp->scache->free = scache_clnt_free; + /* XXX Need flags to stop looping on ECONNREFUSED errors. */ sp->clnt_stream = clnt_stream_create(MAIL_CLASS_PRIVATE, server, idle_limit, ttl_limit); #ifdef CANT_WRITE_BEFORE_SENDING_FD diff --git a/postfix/src/scache/scache.c b/postfix/src/scache/scache.c index f3d27fa62..deb6f0dad 100644 --- a/postfix/src/scache/scache.c +++ b/postfix/src/scache/scache.c @@ -240,18 +240,18 @@ static void scache_save_endp_service(VSTREAM *client_stream) || #endif (fd = LOCAL_RECV_FD(vstream_fileno(client_stream))) < 0) { - msg_warn("%s: unable to receive file descriptor", myname); - attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_FAIL, - ATTR_TYPE_END); + msg_warn("%s: unable to receive file descriptor: %m", myname); + (void) attr_print(client_stream, ATTR_FLAG_NONE, + ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_FAIL, + ATTR_TYPE_END); return; } else { scache_save_endp(scache, ttl > var_scache_ttl_lim ? var_scache_ttl_lim : ttl, STR(scache_endp_label), STR(scache_endp_prop), fd); - attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_OK, - ATTR_TYPE_END); + (void) attr_print(client_stream, ATTR_FLAG_NONE, + ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_OK, + ATTR_TYPE_END); scache_size(scache, &size); if (size.endp_count > scache_endp_count) scache_endp_count = size.endp_count; @@ -297,7 +297,13 @@ static void scache_find_endp_service(VSTREAM *client_stream) ATTR_TYPE_STR, MAIL_ATTR_DUMMY, scache_dummy, ATTR_TYPE_END) != 1 #endif - || LOCAL_SEND_FD(vstream_fileno(client_stream), fd) < 0) + || LOCAL_SEND_FD(vstream_fileno(client_stream), fd) < 0 +#ifdef MUST_READ_AFTER_SENDING_FD + || attr_scan(client_stream, ATTR_FLAG_STRICT, + ATTR_TYPE_STR, MAIL_ATTR_DUMMY, scache_dummy, + ATTR_TYPE_END) != 1 +#endif + ) msg_warn("%s: cannot send file descriptor: %m", myname); if (close(fd) < 0) msg_warn("close(%d): %m", fd); @@ -384,7 +390,13 @@ static void scache_find_dest_service(VSTREAM *client_stream) ATTR_TYPE_STR, MAIL_ATTR_DUMMY, scache_dummy, ATTR_TYPE_END) != 1 #endif - || LOCAL_SEND_FD(vstream_fileno(client_stream), fd) < 0) + || LOCAL_SEND_FD(vstream_fileno(client_stream), fd) < 0 +#ifdef MUST_READ_AFTER_SENDING_FD + || attr_scan(client_stream, ATTR_FLAG_STRICT, + ATTR_TYPE_STR, MAIL_ATTR_DUMMY, scache_dummy, + ATTR_TYPE_END) != 1 +#endif + ) msg_warn("%s: cannot send file descriptor: %m", myname); if (close(fd) < 0) msg_warn("close(%d): %m", fd); diff --git a/postfix/src/smtpstone/qmqp-source.c b/postfix/src/smtpstone/qmqp-source.c index 367de51bd..360b312b7 100644 --- a/postfix/src/smtpstone/qmqp-source.c +++ b/postfix/src/smtpstone/qmqp-source.c @@ -372,7 +372,7 @@ static void send_data(SESSION *session) STR(message_buffer), LEN(message_buffer), STR(sender_buffer), LEN(sender_buffer), STR(recipient_buffer), LEN(recipient_buffer), - 0); + (char *) 0); netstring_fflush(session->stream); /* diff --git a/postfix/src/tls/tls_scache.c b/postfix/src/tls/tls_scache.c index c00789cc3..3cc2abb4b 100644 --- a/postfix/src/tls/tls_scache.c +++ b/postfix/src/tls/tls_scache.c @@ -316,7 +316,7 @@ static int tls_scache_decode(TLS_SCACHE *cp, const char *cache_id, cp->cache_label, cache_id, (long) entry->scache_db_version, (long) entry->openssl_version, (long) entry->timestamp, entry->flags, - LEN(bin_data) - offsetof(TLS_SCACHE_ENTRY, session)); + (int) (LEN(bin_data) - offsetof(TLS_SCACHE_ENTRY, session))); /* * Other mandatory restrictions. diff --git a/postfix/src/util/clean_env.c b/postfix/src/util/clean_env.c index 14023dfe2..888f7bab2 100644 --- a/postfix/src/util/clean_env.c +++ b/postfix/src/util/clean_env.c @@ -56,7 +56,7 @@ void clean_env(char **preserve_list) /* * Preserve or specify selected environment variables. */ -#define STRING_AND_LENGTH(x, y) (x), (y) +#define STRING_AND_LENGTH(x, y) (x), (int) (y) save_list = argv_alloc(10); for (cpp = preserve_list; *cpp; cpp++) diff --git a/postfix/src/util/sys_defs.h b/postfix/src/util/sys_defs.h index 463dbf4e7..c358db320 100644 --- a/postfix/src/util/sys_defs.h +++ b/postfix/src/util/sys_defs.h @@ -1303,6 +1303,15 @@ typedef int pid_t; */ #ifndef CAN_WRITE_BEFORE_SENDING_FD #define CANT_WRITE_BEFORE_SENDING_FD +#endif + + /* + * FreeBSD sendmsg(2) says that after sending a file descriptor, the sender + * must not immediately close the descriptor, otherwise it may close the + * descriptor before it is actually sent. + */ +#ifndef DONT_WAIT_AFTER_SENDING_FD +#define MUST_READ_AFTER_SENDING_FD #endif /* diff --git a/postfix/src/util/unix_recv_fd.c b/postfix/src/util/unix_recv_fd.c index 3fdc5bfcc..d7fbb7eba 100644 --- a/postfix/src/util/unix_recv_fd.c +++ b/postfix/src/util/unix_recv_fd.c @@ -61,17 +61,18 @@ int unix_recv_fd(int fd) /* * Adapted from: W. Richard Stevens, UNIX Network Programming, Volume 1, - * Second edition. + * Second edition. Except that we use CMSG_LEN instead of CMSG_SPACE, for + * portability to LP64 environments. */ #if defined(CMSG_SPACE) && !defined(NO_MSGHDR_MSG_CONTROL) union { - struct msghdr just_for_alignment; + struct cmsghdr just_for_alignment; char control[CMSG_SPACE(sizeof(newfd))]; } control_un; struct cmsghdr *cmptr; msg.msg_control = control_un.control; - msg.msg_controllen = sizeof(control_un.control); + msg.msg_controllen = CMSG_LEN(sizeof(newfd)); /* Fix 200506 */ #else msg.msg_accrights = (char *) &newfd; msg.msg_accrightslen = sizeof(newfd); @@ -123,6 +124,8 @@ int unix_recv_fd(int fd) * unix_send_fd test program) and copy its content until EOF. */ #include
+#include +#include #include #include diff --git a/postfix/src/util/unix_send_fd.c b/postfix/src/util/unix_send_fd.c index 7c555b77a..f913de53e 100644 --- a/postfix/src/util/unix_send_fd.c +++ b/postfix/src/util/unix_send_fd.c @@ -63,17 +63,18 @@ int unix_send_fd(int fd, int sendfd) /* * Adapted from: W. Richard Stevens, UNIX Network Programming, Volume 1, - * Second edition. + * Second edition. Except that we use CMSG_LEN instead of CMSG_SPACE; the + * latter breaks on LP64 systems. */ #if defined(CMSG_SPACE) && !defined(NO_MSGHDR_MSG_CONTROL) union { - struct msghdr just_for_alignment; + struct cmsghdr just_for_alignment; char control[CMSG_SPACE(sizeof(sendfd))]; } control_un; struct cmsghdr *cmptr; msg.msg_control = control_un.control; - msg.msg_controllen = sizeof(control_un.control); + msg.msg_controllen = CMSG_LEN(sizeof(sendfd)); /* Fix 200506 */ cmptr = CMSG_FIRSTHDR(&msg); cmptr->cmsg_len = CMSG_LEN(sizeof(sendfd)); @@ -109,6 +110,8 @@ int unix_send_fd(int fd, int sendfd) * to the unix_recv_fd test program. */ #include +#include +#include #include #include #include diff --git a/postfix/src/util/vstring.c b/postfix/src/util/vstring.c index 53d366017..ddc66302a 100644 --- a/postfix/src/util/vstring.c +++ b/postfix/src/util/vstring.c @@ -19,7 +19,7 @@ /* char *vstring_str(vp) /* VSTRING *vp; /* -/* VSTRING *VSTRING_LEN(vp) +/* int VSTRING_LEN(vp) /* VSTRING *vp; /* /* char *vstring_end(vp) diff --git a/postfix/src/util/vstring.h b/postfix/src/util/vstring.h index b1b81bb8a..0c1b23944 100644 --- a/postfix/src/util/vstring.h +++ b/postfix/src/util/vstring.h @@ -53,7 +53,7 @@ extern VSTRING *vstring_import(char *); */ #define VSTRING_SPACE(vp, len) ((vp)->vbuf.space(&(vp)->vbuf, len)) #define vstring_str(vp) ((char *) (vp)->vbuf.data) -#define VSTRING_LEN(vp) ((vp)->vbuf.ptr - (vp)->vbuf.data) +#define VSTRING_LEN(vp) ((int) ((vp)->vbuf.ptr - (vp)->vbuf.data)) #define vstring_end(vp) ((char *) (vp)->vbuf.ptr) #define VSTRING_TERMINATE(vp) { if ((vp)->vbuf.cnt <= 0) \ VSTRING_SPACE((vp),1); \