--TSCACHE_HEAD_NODE
-TABOUNCE
-TALIAS_TOKEN
-TANVIL_LOCAL
-TSCACHE_SINGLE
-TSCACHE_SINGLE_DEST
-TSCACHE_SINGLE_ENDP
+-TSCACHE_SIZE
-TSCAN_DIR
-TSCAN_INFO
-TSCAN_OBJ
20040723
- Bug? Safety? spawn(8) did not reject a user with the -1
- UID value, so the command could run as root. Files:
- util/spawn_command.c, src/util/spawn.c.
+ Safety: spawn(8) now rejects a user with the -1 UID or GID
+ value, so that commands will not end up running as root.
+ Files: util/spawn_command.c, spawn/spawn.c.
User interface: parameter smtp_connection_cache_domains
renamed to smtp_connection_cache_destinations. Destinations
Portability: Solaris closefrom() support didn't work for
non-SUN compilers. Victor Duchovni, Morgan Stanley.
+20040830
+
+ Feature: the scache(8) session cache manager now logs the
+ peak counts of destinations, endpoints and sessions. Files:
+ scache/scache.c, global/scache*c.
+
+20040831
+
+ Portability: disable session caching support on SCO 5
+ because of incompatible sockets API. File: util/sys_defs.h.
+
+20040913
+
+ Bugfix (introduced 20020803): sent the wrong bounce message
+ type when a Delivered-To: loop was detected for a mailing
+ list alias. Nicolas Riendeau. File: bounce_notify_util.c.
+
Open problems:
- Low: scache & anvil should log cache peak sizes.
+ Low: should the Delivered-To: test in local(8) be configurable?
+
+ Low: append a different domain (like, address.invalid) for
+ mail from clients not in mynetworks.
+
+ Low: document propagate_unmatched_extensions in aliases(5)
+ etc.
+
+ Low: make mail_addr_find() lookup configurable.
+
+ Low: anvil(8) should log cache peak size, like scache(8).
Low: update events.c so that 1-second timer requests do
not suffer from rounding errors. This is needed for 1-second
When no recipients are specified on the command line or via the -t
option, the Postfix sendmail command terminates with status EX_USAGE
and produces an error message instead of accepting the mail first
-and bouncing it later. This gives direct more feedback in case of
+and bouncing it later. This gives more direct feedback in case of
a common client configuration error.
Major changes with snapshot Postfix-2.2-20040827
# Sendmail rule set S3, if you like. This is controlled
# with the canonical_classes parameter.
#
-# The canonical mapping affects both message header
-# addresses (i.e. addresses that appear inside messages) and
-# message envelope addresses (for example, the addresses
-# that are used in SMTP protocol commands). Think Sendmail
-# rule set S3, if you like.
-#
# Typically, one would use the canonical table to replace
# login names by Firstname.Lastname, or to clean up
# addresses produced by legacy mail systems.
sages) and message envelope addresses (for example, the
addresses that are used in SMTP protocol commands). Think
Sendmail rule set <b>S3</b>, if you like. This is controlled
- with the <b>canonical_classes</b> parameter.
-
- The <b>canonical</b> mapping affects both message header
- addresses (i.e. addresses that appear inside messages) and
- message envelope addresses (for example, the addresses
- that are used in SMTP protocol commands). Think Sendmail
- rule set <b>S3</b>, if you like.
+ with the <b><a href="postconf.5.html#canonical_classes">canonical_classes</a></b> parameter.
Typically, one would use the <b>canonical</b> table to replace
login names by <i>Firstname.Lastname</i>, or to clean up
The text below provides only a parameter summary. See
<a href="postconf.5.html">postconf(5)</a> for more details including examples.
- <b>canonical_classes</b>
+ <b><a href="postconf.5.html#canonical_classes">canonical_classes</a></b>
What addresses are subject to canonical address
mapping.
address extension.
<li> Look up the "user+extension" address local part when the
-recipient domain equals $<a href="postconf.5.html#myorigin">myorigin</a>, $<a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a>
+sender domain equals $<a href="postconf.5.html#myorigin">myorigin</a>, $<a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a>
or $<a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a>.
-<li> Look up the "user" address local part when the recipient domain
+<li> Look up the "user" address local part when the sender domain
equals $<a href="postconf.5.html#myorigin">myorigin</a>, $<a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> or $<a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a>.
<li> Look up the "@domain.tld" part.
<dd>Reject the request when the envelope sender is the null address,
and the message has multiple envelope recipients. Although this
usage is technically allowed, it seems to have no legitimate
-application. <br> The <a href="postconf.5.html#multi_recipient_bounce_reject_code">multi_recipient_bounce_reject_code</a> parameter
-specifies the response code for rejected requests (default: 550).
-This feature is available in Postfix 2.1 and later. </dd>
+application. <br> NOTE: this restriction can only work reliably
+when used in <a href="postconf.5.html#smtpd_data_restrictions">smtpd_data_restrictions</a>, because the total number of
+recipients is not known at an earlier stage of the SMTP conversation.
+Use at the RCPT stage will only reject the second etc. recipient.
+<br>
+The <a href="postconf.5.html#multi_recipient_bounce_reject_code">multi_recipient_bounce_reject_code</a> parameter specifies the
+response code for rejected requests (default: 550). This feature
+is available in Postfix 2.1 and later. </dd>
<dt><b><a name="reject_unauth_pipelining">reject_unauth_pipelining</a></b></dt>
<dd>Reject the request when the client sends SMTP commands ahead
of time where it is not allowed, or when the client sends SMTP
commands ahead of time without knowing that Postfix actually supports
-SMTP command pipelining. This stops mail from bulk mail software
-that improperly uses SMTP command pipelining in order to speed up
-deliveries.</dd>
+ESMTP command pipelining. This stops mail from bulk mail software
+that improperly uses ESMTP command pipelining in order to speed up
+deliveries. <br> NOTE: <a href="postconf.5.html#reject_unauth_pipelining">reject_unauth_pipelining</a> is not useful
+outside <a href="postconf.5.html#smtpd_data_restrictions">smtpd_data_restrictions</a> when 1) the client uses ESMTP (EHLO
+instead of HELO) and 2) with "<a href="postconf.5.html#smtpd_delay_reject">smtpd_delay_reject</a> = yes" (the
+default). The use of <a href="postconf.5.html#reject_unauth_pipelining">reject_unauth_pipelining</a> in the other
+restriction contexts is therefore not recommended. </dd>
<dt><b><a name="reject">reject</a></b></dt>
The maximal time-to-live value that the session
cache server allows.
- <b>session_cache_status_update_time (600s)</b>
+ <b><a href="postconf.5.html#session_cache_status_update_time">session_cache_status_update_time</a> (600s)</b>
How frequently the <a href="scache.8.html">scache(8)</a> server logs usage
statistics with session cache hit and miss rates
for logical destinations and for physical end-
AR=ar
ARFL=rv
+# Ugly function to make our error message more visible among the
+# garbage that is output by some versions of make(1).
+
+# By now all shells must have functions.
+
+error() {
+ # Alas, tput(1) is not portable so we can't use visual effects.
+ echo "ATTENTION:" 1>&2;
+ echo "ATTENTION:" $* 1>&2;
+ echo "ATTENTION:" 1>&2;
+ exit 1
+}
+
SYSTEM=`(uname -s) 2>/dev/null`
RELEASE=`(uname -r) 2>/dev/null`
VERSION=`(uname -v) 2>/dev/null`
RANLIB=echo
SYSLIBS="-lresolv -lsocket -lnsl -lc -L/usr/ucblib -lucb"
;;
- *) echo "Seems to be UnixWare`uname -v`. Untested." 1>&2;
- exit 1;;
+ *) error "Seems to be UnixWare`uname -v`. Untested.";;
esac
;;
FreeBSD.2*) SYSTYPE=FREEBSD2
STRCASE="strcasecmp.o"
# Avoid common types of braindamage
case "$LD_LIBRARY_PATH" in
- ?*) echo "Don't set LD_LIBRARY_PATH" 1>&2; exit 1;;
+ ?*) error "Don't set LD_LIBRARY_PATH";;
esac
- case "$CC" in
- *ucb*) echo "Don't use /usr/ucb/cc or ucblib" 1>&2; exit 1;;
- cc*) case `which cc` in
- *ucb*) echo "Don't use /usr/ucb/cc or ucblib" 1>&2; exit 1;;
+ case "${CC}" in
+ *ucb*) error "Don't use /usr/ucb/cc or ucblib";;
+ cc*) case `which ${CC}` in
+ *ucb*) error "Don't use /usr/ucb/cc or ucblib";;
esac;;
esac
;;
esac
CCARGS="$CCARGS -D_ALL_SOURCE"
;;
- *) echo "Unknown AIX version: `uname -v`." 1>&2; exit 1;;
+ *) error "Unknown AIX version: `uname -v`.";;
esac;;
# Tested with RedHat 3.03 on 20020729.
Linux.1*) SYSTYPE=LINUX1
: ${CC=cc}
RANLIB="sleep 5; ranlib"
else
- echo "Unable to determine your system type." 1>&2; exit 1
+ error "Unable to determine your system type."
fi
;;
- *) echo "Unknown system type: $SYSTEM $RELEASE" 1>&2; exit 1;;
+ *) error "Unknown system type: $SYSTEM $RELEASE";;
esac
#
*/gcc|gcc) case `$CC -v` in
"gcc version 2.8"*) : ${OPT=};;
esac;;
- *CC) echo "Don't use CC. That's the C++ compiler" 1>&2; exit 1;;
+ *CC) error "Don't use CC. That's the C++ compiler";;
*) : ${OPT='-O'};;
esac
rule set \fBS3\fR, if you like. This is controlled with
the \fBcanonical_classes\fR parameter.
-The \fBcanonical\fR mapping affects both message header addresses
-(i.e. addresses that appear inside messages) and message envelope
-addresses (for example, the addresses that are used in SMTP protocol
-commands). Think Sendmail rule set \fBS3\fR, if you like.
-
Typically, one would use the \fBcanonical\fR table to replace login
names by \fIFirstname.Lastname\fR, or to clean up addresses produced
by legacy mail systems.
address extension.
.IP \(bu
Look up the "user+extension" address local part when the
-recipient domain equals $myorigin, $mydestination, $inet_interfaces
+sender domain equals $myorigin, $mydestination, $inet_interfaces
or $proxy_interfaces.
.IP \(bu
-Look up the "user" address local part when the recipient domain
+Look up the "user" address local part when the sender domain
equals $myorigin, $mydestination, $inet_interfaces or $proxy_interfaces.
.IP \(bu
Look up the "@domain.tld" part.
usage is technically allowed, it seems to have no legitimate
application.
.br
-The multi_recipient_bounce_reject_code parameter
-specifies the response code for rejected requests (default: 550).
-This feature is available in Postfix 2.1 and later.
+NOTE: this restriction can only work reliably
+when used in smtpd_data_restrictions, because the total number of
+recipients is not known at an earlier stage of the SMTP conversation.
+Use at the RCPT stage will only reject the second etc. recipient.
+.br
+The multi_recipient_bounce_reject_code parameter specifies the
+response code for rejected requests (default: 550). This feature
+is available in Postfix 2.1 and later.
.IP "\fBreject_unauth_pipelining\fR"
Reject the request when the client sends SMTP commands ahead
of time where it is not allowed, or when the client sends SMTP
commands ahead of time without knowing that Postfix actually supports
-SMTP command pipelining. This stops mail from bulk mail software
-that improperly uses SMTP command pipelining in order to speed up
+ESMTP command pipelining. This stops mail from bulk mail software
+that improperly uses ESMTP command pipelining in order to speed up
deliveries.
+.br
+NOTE: reject_unauth_pipelining is not useful
+outside smtpd_data_restrictions when 1) the client uses ESMTP (EHLO
+instead of HELO) and 2) with "smtpd_delay_reject = yes" (the
+default). The use of reject_unauth_pipelining in the other
+restriction contexts is therefore not recommended.
.IP "\fBreject\fR"
Reject the request. This restriction is useful at the end of
a restriction list, to make the default policy explicit. The
s;\bsetgid_group\b;<a href="postconf.5.html#setgid_group">$&</a>;g;
s;\bsession_cache_service\b;<a href="postconf.5.html#session_cache_service">$&</a>;g;
+ s;\bsession_cache_status_update_time\b;<a href="postconf.5.html#session_cache_status_update_time">$&</a>;g;
s;\bsession_cache_ttl_limit\b;<a href="postconf.5.html#session_cache_ttl_limit">$&</a>;g;
s;\bshow_user_unknown_table_name\b;<a href="postconf.5.html#show_user_unknown_table_name">$&</a>;g;
# rule set \fBS3\fR, if you like. This is controlled with
# the \fBcanonical_classes\fR parameter.
#
-# The \fBcanonical\fR mapping affects both message header addresses
-# (i.e. addresses that appear inside messages) and message envelope
-# addresses (for example, the addresses that are used in SMTP protocol
-# commands). Think Sendmail rule set \fBS3\fR, if you like.
-#
# Typically, one would use the \fBcanonical\fR table to replace login
# names by \fIFirstname.Lastname\fR, or to clean up addresses produced
# by legacy mail systems.
address extension.
<li> Look up the "user+extension" address local part when the
-recipient domain equals $myorigin, $mydestination, $inet_interfaces
+sender domain equals $myorigin, $mydestination, $inet_interfaces
or $proxy_interfaces.
-<li> Look up the "user" address local part when the recipient domain
+<li> Look up the "user" address local part when the sender domain
equals $myorigin, $mydestination, $inet_interfaces or $proxy_interfaces.
<li> Look up the "@domain.tld" part.
<dd>Reject the request when the envelope sender is the null address,
and the message has multiple envelope recipients. Although this
usage is technically allowed, it seems to have no legitimate
-application. <br> The multi_recipient_bounce_reject_code parameter
-specifies the response code for rejected requests (default: 550).
-This feature is available in Postfix 2.1 and later. </dd>
+application. <br> NOTE: this restriction can only work reliably
+when used in smtpd_data_restrictions, because the total number of
+recipients is not known at an earlier stage of the SMTP conversation.
+Use at the RCPT stage will only reject the second etc. recipient.
+<br>
+The multi_recipient_bounce_reject_code parameter specifies the
+response code for rejected requests (default: 550). This feature
+is available in Postfix 2.1 and later. </dd>
<dt><b><a name="reject_unauth_pipelining">reject_unauth_pipelining</a></b></dt>
<dd>Reject the request when the client sends SMTP commands ahead
of time where it is not allowed, or when the client sends SMTP
commands ahead of time without knowing that Postfix actually supports
-SMTP command pipelining. This stops mail from bulk mail software
-that improperly uses SMTP command pipelining in order to speed up
-deliveries.</dd>
+ESMTP command pipelining. This stops mail from bulk mail software
+that improperly uses ESMTP command pipelining in order to speed up
+deliveries. <br> NOTE: reject_unauth_pipelining is not useful
+outside smtpd_data_restrictions when 1) the client uses ESMTP (EHLO
+instead of HELO) and 2) with "smtpd_delay_reject = yes" (the
+default). The use of reject_unauth_pipelining in the other
+restriction contexts is therefore not recommended. </dd>
<dt><b><a name="reject">reject</a></b></dt>
* Initialize the bounce_info structure. Forge a logfile record for just
* one recipient.
*/
-#define REALLY_BOUNCE 1
-
log_handle = bounce_log_forge(orig_recipient, recipient, offset, dsn_status,
dsn_action, why);
bounce_info = bounce_mail_alloc("none", queue_name, queue_id,
- encoding, REALLY_BOUNCE, log_handle);
+ encoding, BOUNCE_MSG_FAIL, log_handle);
return (bounce_info);
}
* Patches change the patchlevel and the release date. Snapshots change the
* release date only.
*/
-#define MAIL_RELEASE_DATE "20040829"
+#define MAIL_RELEASE_DATE "20040917"
#define MAIL_VERSION_NUMBER "2.2"
#define VAR_MAIL_VERSION "mail_version"
/* SYNOPSIS
/* #include <scache.h>
/* DESCRIPTION
+/* typedef struct {
+/* .in +4
+/* int dest_count;
+/* int endp_count;
+/* int sess_count;
+/* .in -4
+/* } SCACHE_SIZE;
+/*
+/* unsigned scache_size(scache, size)
+/* SCACHE *scache;
+/* SCACHE_SIZE *size;
+/*
/* void scache_free(scache)
/* SCACHE *scache;
/*
/* endpoints, and one physical endpoint may have multiple
/* sessions.
/*
+/* scache_size() returns the number of logical destination
+/* names, physical endpoint addresses, and cached sessions.
+/*
/* scache_free() destroys the specified session cache.
/*
/* scache_save_endp() stores an open session under the specified
#include <vstring.h>
typedef struct SCACHE SCACHE;
+typedef struct SCACHE_SIZE SCACHE_SIZE;
/*
* In order to cache a session, we specify:
typedef void (*SCACHE_SAVE_DEST_FN) (SCACHE *, int, const char *, const char *, const char *);
typedef int (*SCACHE_FIND_DEST_FN) (SCACHE *, const char *, VSTRING *, VSTRING *);
+ /*
+ * Session cache statistics. These are the actual numbers at a specific
+ * point in time.
+ */
+struct SCACHE_SIZE {
+ int dest_count; /* Nr of destination names */
+ int endp_count; /* Nr of endpoint adresses */
+ int sess_count; /* Nr of cached sessions */
+};
+
/*
* Generic session cache object. Actual session cache objects are derived
* types with some additional, cache dependent, private information.
SCACHE_FIND_ENDP_FN find_endp;
SCACHE_SAVE_DEST_FN save_dest;
SCACHE_FIND_DEST_FN find_dest;
+ void (*size) (struct SCACHE *, SCACHE_SIZE *);
void (*free) (struct SCACHE *);
};
(scache)->save_dest((scache), (ttl), (dest_label), (dest_prop), (endp_label))
#define scache_find_dest(scache, dest_label, dest_prop, endp_prop) \
(scache)->find_dest((scache), (dest_label), (dest_prop), (endp_prop))
+#define scache_size(scache, stats) (scache)->size((scache), (stats))
#define scache_free(scache) (scache)->free(scache)
/*
return (-1);
}
+/* scache_clnt_size - dummy */
+
+static void scache_clnt_size(SCACHE *scache, SCACHE_SIZE *size)
+{
+ /* XXX Crap in a hurry. */
+ size->dest_count = 0;
+ size->endp_count = 0;
+ size->sess_count = 0;
+}
+
/* scache_clnt_free - destroy cache */
static void scache_clnt_free(SCACHE *scache)
sp->scache->find_endp = scache_clnt_find_endp;
sp->scache->save_dest = scache_clnt_save_dest;
sp->scache->find_dest = scache_clnt_find_dest;
+ sp->scache->size = scache_clnt_size;
sp->scache->free = scache_clnt_free;
sp->clnt_stream = clnt_stream_create(MAIL_CLASS_PRIVATE, server,
SCACHE scache[1]; /* super-class */
HTABLE *dest_cache; /* destination->endpoint bindings */
HTABLE *endp_cache; /* endpoint->session bindings */
+ int sess_count; /* number of cached sessions */
} SCACHE_MULTI;
/*
- * Storage for a destination or endpoint list head. The list head has
- * references to its own hash table entry, so that we can remove a list when
- * it becomes empty. List items are stored in a circular list under the list
- * head.
+ * Storage for a destination or endpoint list head. Each list head knows its
+ * own hash table entry name, so that we can remove the list when it becomes
+ * empty. List items are stored in a circular list under the list head.
*/
typedef struct {
RING ring[1]; /* circular list linkage */
- HTABLE *parent_table; /* parent info */
- char *parent_key; /* parent info */
+ char *parent_key; /* parent linkage: hash table */
+ SCACHE_MULTI *cache; /* parent linkage: cache */
} SCACHE_MULTI_HEAD;
#define RING_TO_MULTI_HEAD(p) RING_TO_APPL((p), SCACHE_MULTI_HEAD, ring)
*/
typedef struct {
RING ring[1]; /* circular list linkage */
+ SCACHE_MULTI_HEAD *head; /* parent linkage: list head */
char *endp_label; /* endpoint name */
char *dest_prop; /* binding properties */
} SCACHE_MULTI_DEST;
*/
typedef struct {
RING ring[1]; /* circular list linkage */
+ SCACHE_MULTI_HEAD *head; /* parent linkage: list head */
int fd; /* cached session */
char *endp_prop; /* binding properties */
} SCACHE_MULTI_ENDP;
* the list becomes empty. Otherwise, remove the endpoint->session
* binding from the list.
*/
- if (direction == BOTTOM_UP
- && ring_pred(endp->ring) == ring_succ(endp->ring)) {
- head = RING_TO_MULTI_HEAD(ring_pred(endp->ring));
- htable_delete(head->parent_table, head->parent_key, myfree);
- } else
- ring_detach(endp->ring);
+ ring_detach(endp->ring);
+ head = endp->head;
+ head->cache->sess_count--;
+ if (direction == BOTTOM_UP && ring_pred(head->ring) == head->ring)
+ htable_delete(head->cache->endp_cache, head->parent_key, myfree);
/*
* Destroy the endpoint->session binding.
htable_find(sp->endp_cache, endp_label)) == 0) {
head = (SCACHE_MULTI_HEAD *) mymalloc(sizeof(*head));
ring_init(head->ring);
- head->parent_table = sp->endp_cache;
head->parent_key =
htable_enter(sp->endp_cache, endp_label, (char *) head)->key;
+ head->cache = sp;
}
/*
* duplicate, because each session must have a different file descriptor.
*/
endp = (SCACHE_MULTI_ENDP *) mymalloc(sizeof(*endp));
+ endp->head = head;
endp->fd = fd;
endp->endp_prop = mystrdup(endp_prop);
ring_prepend(head->ring, endp->ring);
+ sp->sess_count++;
/*
* Make sure this binding will go away eventually.
* the list becomes empty. Otherwise, remove the destination->endpoint
* binding from the list.
*/
- if (direction == BOTTOM_UP
- && ring_pred(dest->ring) == ring_succ(dest->ring)) {
- head = RING_TO_MULTI_HEAD(ring_pred(dest->ring));
- htable_delete(head->parent_table, head->parent_key, myfree);
- } else
- ring_detach(dest->ring);
+ ring_detach(dest->ring);
+ head = dest->head;
+ if (direction == BOTTOM_UP && ring_pred(head->ring) == head->ring)
+ htable_delete(head->cache->dest_cache, head->parent_key, myfree);
/*
* Destroy the destination->endpoint binding.
htable_find(sp->dest_cache, dest_label)) == 0) {
head = (SCACHE_MULTI_HEAD *) mymalloc(sizeof(*head));
ring_init(head->ring);
- head->parent_table = sp->dest_cache;
head->parent_key =
htable_enter(sp->dest_cache, dest_label, (char *) head)->key;
+ head->cache = sp;
}
/*
}
if (refresh == 0) {
dest = (SCACHE_MULTI_DEST *) mymalloc(sizeof(*dest));
+ dest->head = head;
dest->endp_label = mystrdup(endp_label);
dest->dest_prop = mystrdup(dest_prop);
ring_prepend(head->ring, dest->ring);
return (-1);
}
-/* scache_multi_free - destroy single-element cache object */
+/* scache_multi_size - size of multi-element cache object */
+
+static void scache_multi_size(SCACHE *scache, SCACHE_SIZE *size)
+{
+ SCACHE_MULTI *sp = (SCACHE_MULTI *) scache;
+
+ size->dest_count = sp->dest_cache->used;
+ size->endp_count = sp->endp_cache->used;
+ size->sess_count = sp->sess_count;
+}
+
+/* scache_multi_free - destroy multi-element cache object */
static void scache_multi_free(SCACHE *scache)
{
sp->scache->find_endp = scache_multi_find_endp;
sp->scache->save_dest = scache_multi_save_dest;
sp->scache->find_dest = scache_multi_find_dest;
+ sp->scache->size = scache_multi_size;
sp->scache->free = scache_multi_free;
sp->dest_cache = htable_create(1);
sp->endp_cache = htable_create(1);
+ sp->sess_count = 0;
return (sp->scache);
}
>>> # Destination name space collision test
>>>
>>> save_dest 2 a_dest a_prop b_endp
-unknown: scache_multi_save_dest: dest_label=a_dest -> dest_prop=a_prop endp_label=b_endp
>>> sleep 1
>>> save_dest 2 a_dest a_prop b_endp
-unknown: scache_multi_save_dest: dest_label=a_dest -> dest_prop=a_prop endp_label=b_endp (refreshed)
>>> sleep 1
>>> save_dest 2 a_dest a_prop b_endp
-unknown: scache_multi_save_dest: dest_label=a_dest -> dest_prop=a_prop endp_label=b_endp (refreshed)
>>> sleep 2
-unknown: scache_multi_drop_dest: dest_prop=a_prop endp_label=b_endp
>>>
>>> # Another destination name space collision test
>>>
>>> save_dest 2 a_dest a_prop b_endp
-unknown: scache_multi_save_dest: dest_label=a_dest -> dest_prop=a_prop endp_label=b_endp
>>> sleep 1
>>> save_dest 2 a_dest a_prop2 b_endp
-unknown: scache_multi_save_dest: dest_label=a_dest -> dest_prop=a_prop2 endp_label=b_endp
>>> sleep 1
-unknown: scache_multi_drop_dest: dest_prop=a_prop endp_label=b_endp
>>> save_dest 2 a_dest a_prop2 b_endp2
-unknown: scache_multi_save_dest: dest_label=a_dest -> dest_prop=a_prop2 endp_label=b_endp2
>>> sleep 2
-unknown: scache_multi_drop_dest: dest_prop=a_prop2 endp_label=b_endp
-unknown: scache_multi_drop_dest: dest_prop=a_prop2 endp_label=b_endp2
>>>
>>> # Endpoint name space collision test
>>>
>>> save_endp 2 b_endp b_prop 12
-unknown: scache_multi_save_endp: endp_label=b_endp -> endp_prop=b_prop fd=12
>>> save_endp 2 b_endp b_prop 13
-unknown: scache_multi_save_endp: endp_label=b_endp -> endp_prop=b_prop fd=13
>>> sleep 3
-unknown: scache_multi_drop_endp: endp_prop=b_prop fd=12
-unknown: scache_multi_drop_endp: endp_prop=b_prop fd=13
>>>
>>> # Combined destiation and endpoint collision test with lookup
>>>
>>> save_dest 2 a_dest a_prop b_endp
-unknown: scache_multi_save_dest: dest_label=a_dest -> dest_prop=a_prop endp_label=b_endp
>>> save_dest 2 a_dest a_prop2 b_endp
-unknown: scache_multi_save_dest: dest_label=a_dest -> dest_prop=a_prop2 endp_label=b_endp
>>> save_dest 2 a_dest a_prop2 b_endp2
-unknown: scache_multi_save_dest: dest_label=a_dest -> dest_prop=a_prop2 endp_label=b_endp2
>>> save_endp 2 b_endp b_prop 12
-unknown: scache_multi_save_endp: endp_label=b_endp -> endp_prop=b_prop fd=12
>>> save_endp 2 b_endp b_prop 13
-unknown: scache_multi_save_endp: endp_label=b_endp -> endp_prop=b_prop fd=13
>>> find_dest a_dest
-unknown: scache_multi_find_endp: found: endp_label=b_endp -> endp_prop=b_prop fd=12
-unknown: scache_multi_drop_endp: endp_prop=b_prop fd=-1
>>> find_dest a_dest
-unknown: scache_multi_find_endp: found: endp_label=b_endp -> endp_prop=b_prop fd=13
-unknown: scache_multi_drop_endp: endp_prop=b_prop fd=-1
>>> find_dest a_dest
-unknown: scache_multi_find_endp: no endpoint cache: endp_label=b_endp
-unknown: scache_multi_find_endp: no endpoint cache: endp_label=b_endp
-unknown: scache_multi_find_endp: no endpoint cache: endp_label=b_endp2
-unknown: scache_multi_find_dest: not found: dest_label=a_dest
>>>
>>> # Another combined destiation and endpoint collision test with lookup
>>>
>>> save_endp 2 b_endp2 b_prop 12
-unknown: scache_multi_save_endp: endp_label=b_endp2 -> endp_prop=b_prop fd=12
>>> save_endp 2 b_endp2 b_prop 13
-unknown: scache_multi_save_endp: endp_label=b_endp2 -> endp_prop=b_prop fd=13
>>> save_endp 2 b_endp2 b_prop 14
-unknown: scache_multi_save_endp: endp_label=b_endp2 -> endp_prop=b_prop fd=14
>>> find_dest a_dest
-unknown: scache_multi_find_endp: no endpoint cache: endp_label=b_endp
-unknown: scache_multi_find_endp: no endpoint cache: endp_label=b_endp
-unknown: scache_multi_find_endp: found: endp_label=b_endp2 -> endp_prop=b_prop fd=12
-unknown: scache_multi_drop_endp: endp_prop=b_prop fd=-1
>>> find_dest a_dest
-unknown: scache_multi_find_endp: no endpoint cache: endp_label=b_endp
-unknown: scache_multi_find_endp: no endpoint cache: endp_label=b_endp
-unknown: scache_multi_find_endp: found: endp_label=b_endp2 -> endp_prop=b_prop fd=13
-unknown: scache_multi_drop_endp: endp_prop=b_prop fd=-1
>>> find_dest a_dest
-unknown: scache_multi_find_endp: no endpoint cache: endp_label=b_endp
-unknown: scache_multi_find_endp: no endpoint cache: endp_label=b_endp
-unknown: scache_multi_find_endp: found: endp_label=b_endp2 -> endp_prop=b_prop fd=14
-unknown: scache_multi_drop_endp: endp_prop=b_prop fd=-1
>>> find_dest a_dest
-unknown: scache_multi_find_endp: no endpoint cache: endp_label=b_endp
-unknown: scache_multi_find_endp: no endpoint cache: endp_label=b_endp
-unknown: scache_multi_find_endp: no endpoint cache: endp_label=b_endp2
-unknown: scache_multi_find_dest: not found: dest_label=a_dest
>>>
>>> # Let the exit handler clean up the destiation->endpoint bindings.
>>>
-unknown: scache_multi_drop_dest: dest_prop=a_prop endp_label=b_endp
-unknown: scache_multi_drop_dest: dest_prop=a_prop2 endp_label=b_endp
-unknown: scache_multi_drop_dest: dest_prop=a_prop2 endp_label=b_endp2
return (-1);
}
+/* scache_single_size - size of single-element cache :-) */
+
+static void scache_single_size(SCACHE *scache, SCACHE_SIZE *size)
+{
+ SCACHE_SINGLE *sp = (SCACHE_SINGLE *) scache;
+
+ size->dest_count = (!SCACHE_SINGLE_DEST_BUSY(sp) ? 0 : 1);
+ size->endp_count = (!SCACHE_SINGLE_ENDP_BUSY(sp) ? 0 : 1);
+ size->sess_count = (sp->endp.fd < 0 ? 0 : 1);
+}
+
/* scache_single_free - destroy single-element cache object */
static void scache_single_free(SCACHE *scache)
sp->scache->find_endp = scache_single_find_endp;
sp->scache->save_dest = scache_single_save_dest;
sp->scache->find_dest = scache_single_find_dest;
+ sp->scache->size = scache_single_size;
sp->scache->free = scache_single_free;
sp->endp.endp_label = vstring_alloc(10);
*/
static int scache_dest_hits;
static int scache_dest_miss;
+static int scache_dest_count;
static int scache_endp_hits;
static int scache_endp_miss;
+static int scache_endp_count;
+static int scache_sess_count;
time_t scache_start_time;
/*
const char *myname = "scache_save_endp_service";
int ttl;
int fd;
+ SCACHE_SIZE size;
if (attr_scan(client_stream,
ATTR_FLAG_STRICT,
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;
+ if (size.sess_count > scache_sess_count)
+ scache_sess_count = size.sess_count;
return;
}
}
{
const char *myname = "scache_save_dest_service";
int ttl;
+ SCACHE_SIZE size;
if (attr_scan(client_stream,
ATTR_FLAG_STRICT,
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.dest_count > scache_dest_count)
+ scache_dest_count = size.dest_count;
+ if (size.endp_count > scache_endp_count)
+ scache_endp_count = size.endp_count;
+ return;
return;
}
}
static void scache_status_dump(char *unused_name, char **unused_argv)
{
if (scache_dest_hits || scache_dest_miss
- || scache_endp_hits || scache_endp_miss)
+ || scache_endp_hits || scache_endp_miss
+ || scache_dest_count || scache_endp_count
+ || scache_sess_count)
msg_info("statistics: start interval %.15s",
ctime(&scache_start_time) + 4);
/ (scache_endp_hits + scache_endp_miss));
scache_endp_hits = scache_endp_miss = 0;
}
+ if (scache_dest_count || scache_endp_count || scache_sess_count) {
+ msg_info("statistics: max simultaneous domains=%d addresses=%d sessions=%d",
+ scache_dest_count, scache_endp_count, scache_sess_count);
+ scache_dest_count = 0;
+ scache_endp_count = 0;
+ scache_sess_count = 0;
+ }
scache_start_time = event_time();
}
STR(state->dest_prop), STR(state->endp_label));
/*
- * Save every good sessions under its physical endpoint address.
+ * Save every good session under its physical endpoint address.
*/
scache_save_endp(smtp_scache, var_smtp_cache_conn, STR(state->endp_label),
STR(state->endp_prop), fd);
*/
#include <cpio.h>
#define S_ISSOCK(mode) (((mode) & (S_IFMT)) == (C_ISSOCK))
+#define CANT_USE_SEND_RECV_MSG
+#define DEF_SMTP_CACHE_DEMAND 0
#endif
/*