no SMTP connection caching for those platforms. Albert
Chin. File: util/sys_defs.h.
+20050630
+
+ Portability: the connection caching code broke on LP64
+ systems (inherited from Stevens Network Programming). Files:
+ util/unix_send_fd.c, util/unix_recv_fd.c. This code is
+ back-ported from the Postfix 2.3 snapshot release.
+
+20050706
+
+ Robustness: the SMTP client now disables caching when it
+ is unable to communicate with the scache(8) connection
+ caching server, instead of looping forever and not delivering
+ mail. File: global/scache_clnt.c. This code is back-ported
+ from the Postfix 2.3 snapshot release.
+
+ Portability: after sending a socket, the scache(8) server
+ now waits for an ACK from the connection cache client before
+ closing the socket that it just sent. Files: scache/scache.c,
+ global/scache_clnt.c. This code is back-ported from the
+ Postfix 2.3 snapshot release.
+
+20050711-3
+
+ Portability: on LP64 systems, integer expressions are int,
+ but sizeof() and pointer difference expressions are larger.
+ Point fixes for a few discrepancies with variadic functions
+ that expect int (the permanent fix is to change the receiving
+ modules, but that results in too much change, and is not
+ allowed in the stable release). Files: tls/tls_scache.c,
+ util/clean_env.c, util/vstring.h, smtpstone/qmqp-source.c.
* Protocol names are ESMTP or SMTP.
- * Protocol states are CONNECT, EHLO, HELO, MAIL, RCPT, DATA, END-OF-DATA,
+ * Protocol states are CONNECT, EHLO, HELO, MAIL, RCPT, 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.
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: clients in $mynetworks
- may make an unlimited number of connections).
+ $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 unit over which
client connection rates are computed (default: 60s).
<li> <p> Protocol names are ESMTP or SMTP. </p>
<li> <p> 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.
</p>
simultaneous connections (default: 50). This is half the default
process limit. </p>
+<li> <p> An SMTP client may make up to $<a href="postconf.5.html#smtpd_client_message_rate_limit">smtpd_client_message_rate_limit</a>
+message delivery requests per unit time (default: no limit). </p>
+
+<li> <p> An SMTP client may send up to $<a href="postconf.5.html#smtpd_client_recipient_rate_limit">smtpd_client_recipient_rate_limit</a>
+recipient addresses per unit time (default: no limit). </p>
+
<li> <p> An SMTP client may make up to $<a href="postconf.5.html#smtpd_client_connection_rate_limit">smtpd_client_connection_rate_limit</a>
connections per unit time (default: no limit). </p>
<li> <p> These limits are not applied to SMTP clients in the networks
-specified with $smtpd_client_connection_limit_exceptions (default:
+specified with $<a href="postconf.5.html#smtpd_client_event_limit_exceptions">smtpd_client_event_limit_exceptions</a> (default:
clients in $<a href="postconf.5.html#mynetworks">mynetworks</a> may make an unlimited number of connections).
<li> <p> The <a href="postconf.5.html#anvil_rate_time_unit">anvil_rate_time_unit</a> parameter specifies the time
</p>
<p>
-Specify a pathname ending "/" for qmail-style delivery.
+Specify a pathname ending in "/" for qmail-style delivery.
</p>
<p>
with whitespace.
.PP
Note: IP version 6 address information must be specified inside
-<tt>[]</tt> 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.
In main.cf specify "relay_transport = relay",
.IP \(bu
In master.cf specify "-o fallback_relay =" (i.e., empty) at
-the end of the <tt>relay</tt> 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.
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,
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 <tt>user@[ip.address]</tt>.
+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 <tt>[]</tt>,
+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
block from the list.
.PP
Note: IP version 6 address information must be specified inside
-<tt>[]</tt> 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
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 <tt>[]</tt>,
+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
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 <tt>[]</tt>,
+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
with whitespace.
.PP
Note: IP version 6 address information must be specified inside
-<tt>[]</tt> 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.
with whitespace.
.PP
Note: IP version 6 address information must be specified inside
-<tt>[]</tt> 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.
with whitespace.
.PP
Note: IP version 6 address information must be specified inside
-<tt>[]</tt> 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.
dot causes the domain to match any name below it).
.PP
Note: IP version 6 address information must be specified inside
-<tt>[]</tt> 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.
long lines by starting the next line with whitespace.
.PP
Note: IP version 6 address information must be specified inside
-<tt>[]</tt> 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.
$block =~ s/<li>\s*/\n.IP \\(bu\n/g;
$block =~ s/<dt>\s*/\n.IP "/g;
$block =~ s/\s*<\/dt>/"/g;
+ $block =~ s/<tt>\s*//g;
+ $block =~ s/\s*<\/tt>//g;
$block =~ s/<blockquote>/\n.na\n.nf\n.in +4\n/g;
$block =~ s/<\/blockquote>/\n.in -4\n.fi\n.ad\n/g;
$block =~ s/\n<br>/\n.br\n/g;
<li> <p> Protocol names are ESMTP or SMTP. </p>
<li> <p> 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.
</p>
simultaneous connections (default: 50). This is half the default
process limit. </p>
+<li> <p> An SMTP client may make up to $smtpd_client_message_rate_limit
+message delivery requests per unit time (default: no limit). </p>
+
+<li> <p> An SMTP client may send up to $smtpd_client_recipient_rate_limit
+recipient addresses per unit time (default: no limit). </p>
+
<li> <p> An SMTP client may make up to $smtpd_client_connection_rate_limit
connections per unit time (default: no limit). </p>
<li> <p> 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).
<li> <p> The anvil_rate_time_unit parameter specifies the time
</p>
<p>
-Specify a pathname ending "/" for qmail-style delivery.
+Specify a pathname ending in "/" for qmail-style delivery.
</p>
<p>
* 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
/* 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
#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,
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",
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,
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 */
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,
|| 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);
}
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",
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,
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 */
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,
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);
}
{
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
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
||
#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;
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);
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);
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);
/*
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.
/*
* 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++)
*/
#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
/*
/*
* 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);
* unix_send_fd test program) and copy its content until EOF.
*/
#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
#include <split_at.h>
#include <listen.h>
/*
* 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));
* to the unix_recv_fd test program.
*/
#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
#include <fcntl.h>
#include <split_at.h>
#include <connect.h>
/* char *vstring_str(vp)
/* VSTRING *vp;
/*
-/* VSTRING *VSTRING_LEN(vp)
+/* int VSTRING_LEN(vp)
/* VSTRING *vp;
/*
/* char *vstring_end(vp)
*/
#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); \