From 8ccfb61a86616f7a94b53e1d012a3a266414c1a5 Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Fri, 17 Sep 2004 00:00:00 -0500 Subject: [PATCH] postfix-2.2-20040917 --- postfix/.indent.pro | 2 +- postfix/HISTORY | 35 +++++++++++++-- postfix/RELEASE_NOTES | 2 +- postfix/conf/canonical | 6 --- postfix/html/canonical.5.html | 10 +---- postfix/html/postconf.5.html | 25 +++++++---- postfix/html/scache.8.html | 2 +- postfix/makedefs | 34 ++++++++++----- postfix/man/man5/canonical.5 | 5 --- postfix/man/man5/postconf.5 | 25 ++++++++--- postfix/mantools/postlink | 1 + postfix/proto/canonical | 5 --- postfix/proto/postconf.proto | 25 +++++++---- postfix/src/bounce/bounce_notify_util.c | 4 +- postfix/src/global/mail_version.h | 2 +- postfix/src/global/scache.c | 15 +++++++ postfix/src/global/scache.h | 13 ++++++ postfix/src/global/scache_clnt.c | 11 +++++ postfix/src/global/scache_multi.c | 57 ++++++++++++++++--------- postfix/src/global/scache_multi.ref | 49 --------------------- postfix/src/global/scache_single.c | 12 ++++++ postfix/src/scache/scache.c | 27 +++++++++++- postfix/src/smtp/smtp_reuse.c | 2 +- postfix/src/util/sys_defs.h | 2 + 24 files changed, 230 insertions(+), 141 deletions(-) diff --git a/postfix/.indent.pro b/postfix/.indent.pro index 6c604ed34..442d5ed0b 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -1,4 +1,3 @@ --TSCACHE_HEAD_NODE -TABOUNCE -TALIAS_TOKEN -TANVIL_LOCAL @@ -152,6 +151,7 @@ -TSCACHE_SINGLE -TSCACHE_SINGLE_DEST -TSCACHE_SINGLE_ENDP +-TSCACHE_SIZE -TSCAN_DIR -TSCAN_INFO -TSCAN_OBJ diff --git a/postfix/HISTORY b/postfix/HISTORY index 6834bb57a..ae41bf429 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -9587,9 +9587,9 @@ Apologies for any names omitted. 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 @@ -9706,9 +9706,36 @@ Apologies for any names omitted. 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 diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index c5df8ee68..01ac15a22 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -13,7 +13,7 @@ Incompatible changes with snapshot Postfix-2.2-20040829 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 diff --git a/postfix/conf/canonical b/postfix/conf/canonical index f47535da6..0445a0d5c 100644 --- a/postfix/conf/canonical +++ b/postfix/conf/canonical @@ -40,12 +40,6 @@ # 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. diff --git a/postfix/html/canonical.5.html b/postfix/html/canonical.5.html index fbfc98324..54106f599 100644 --- a/postfix/html/canonical.5.html +++ b/postfix/html/canonical.5.html @@ -44,13 +44,7 @@ CANONICAL(5) CANONICAL(5) sages) and message envelope addresses (for example, the addresses that are used in SMTP protocol commands). Think 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. + with the canonical_classes parameter. Typically, one would use the canonical table to replace login names by Firstname.Lastname, or to clean up @@ -160,7 +154,7 @@ CANONICAL(5) CANONICAL(5) The text below provides only a parameter summary. See postconf(5) for more details including examples. - canonical_classes + canonical_classes What addresses are subject to canonical address mapping. diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index 8f186a332..ee5633105 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -4993,10 +4993,10 @@ optional address extension. address extension.
  • 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. -
  • 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.
  • Look up the "@domain.tld" part. @@ -6224,18 +6224,27 @@ a restriction list, to make the default policy explicit.
    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.
    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.
    +application.
    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. +
    +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.
    reject_unauth_pipelining
    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.
    +ESMTP command pipelining. This stops mail from bulk mail software +that improperly uses ESMTP command pipelining in order to speed up +deliveries.
    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.
    reject
    diff --git a/postfix/html/scache.8.html b/postfix/html/scache.8.html index 92d73f051..79cb1f0d9 100644 --- a/postfix/html/scache.8.html +++ b/postfix/html/scache.8.html @@ -97,7 +97,7 @@ SCACHE(8) SCACHE(8) The maximal time-to-live value that the session cache server allows. - session_cache_status_update_time (600s) + session_cache_status_update_time (600s) How frequently the scache(8) server logs usage statistics with session cache hit and miss rates for logical destinations and for physical end- diff --git a/postfix/makedefs b/postfix/makedefs index 8cedde2c1..2ef53d797 100644 --- a/postfix/makedefs +++ b/postfix/makedefs @@ -52,6 +52,19 @@ SYSLIBS= 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` @@ -81,8 +94,7 @@ case "$SYSTEM.$RELEASE" in 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 @@ -135,12 +147,12 @@ case "$SYSTEM.$RELEASE" in 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 ;; @@ -179,7 +191,7 @@ case "$SYSTEM.$RELEASE" in 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 @@ -297,10 +309,10 @@ Rhapsody.5*|Darwin.*) : ${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 # @@ -327,7 +339,7 @@ case "$CC" in */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 diff --git a/postfix/man/man5/canonical.5 b/postfix/man/man5/canonical.5 index 544a8e20c..98b503d1c 100644 --- a/postfix/man/man5/canonical.5 +++ b/postfix/man/man5/canonical.5 @@ -43,11 +43,6 @@ that are used in SMTP protocol commands). Think Sendmail 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. diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index 3ac34368f..be6518246 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -2619,10 +2619,10 @@ Look up the "user@domain.tld" address without the optional 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. @@ -3286,16 +3286,27 @@ 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. +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 diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink index ccf72e1f0..d780e8a14 100755 --- a/postfix/mantools/postlink +++ b/postfix/mantools/postlink @@ -298,6 +298,7 @@ while (<>) { s;\bsetgid_group\b;$&;g; s;\bsession_cache_service\b;$&;g; + s;\bsession_cache_status_update_time\b;$&;g; s;\bsession_cache_ttl_limit\b;$&;g; s;\bshow_user_unknown_table_name\b;$&;g; diff --git a/postfix/proto/canonical b/postfix/proto/canonical index bba86891a..9ba1d3015 100644 --- a/postfix/proto/canonical +++ b/postfix/proto/canonical @@ -37,11 +37,6 @@ # 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. diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index 88cdf5134..49994026b 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -3142,10 +3142,10 @@ optional address extension. address extension.
  • 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. -
  • 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.
  • Look up the "@domain.tld" part. @@ -4124,18 +4124,27 @@ a restriction list, to make the default policy explicit.
    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.
    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.
    +application.
    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. +
    +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.
    reject_unauth_pipelining
    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.
    +ESMTP command pipelining. This stops mail from bulk mail software +that improperly uses ESMTP command pipelining in order to speed up +deliveries.
    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.
    reject
    diff --git a/postfix/src/bounce/bounce_notify_util.c b/postfix/src/bounce/bounce_notify_util.c index f5afe618b..205d2e453 100644 --- a/postfix/src/bounce/bounce_notify_util.c +++ b/postfix/src/bounce/bounce_notify_util.c @@ -345,12 +345,10 @@ BOUNCE_INFO *bounce_mail_one_init(const char *queue_name, * 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); } diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 9ca267e39..03e8adda8 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * 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" diff --git a/postfix/src/global/scache.c b/postfix/src/global/scache.c index 3a913c732..61347047b 100644 --- a/postfix/src/global/scache.c +++ b/postfix/src/global/scache.c @@ -6,6 +6,18 @@ /* SYNOPSIS /* #include /* 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; /* @@ -51,6 +63,9 @@ /* 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 diff --git a/postfix/src/global/scache.h b/postfix/src/global/scache.h index c00dd6d6b..1670546c5 100644 --- a/postfix/src/global/scache.h +++ b/postfix/src/global/scache.h @@ -17,6 +17,7 @@ #include typedef struct SCACHE SCACHE; +typedef struct SCACHE_SIZE SCACHE_SIZE; /* * In order to cache a session, we specify: @@ -85,6 +86,16 @@ typedef int (*SCACHE_FIND_ENDP_FN) (SCACHE *, const char *, VSTRING *); 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. @@ -94,6 +105,7 @@ struct SCACHE { 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 *); }; @@ -109,6 +121,7 @@ extern SCACHE *scache_multi_create(void); (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) /* diff --git a/postfix/src/global/scache_clnt.c b/postfix/src/global/scache_clnt.c index 6bb233daa..3838294d7 100644 --- a/postfix/src/global/scache_clnt.c +++ b/postfix/src/global/scache_clnt.c @@ -306,6 +306,16 @@ static int scache_clnt_find_dest(SCACHE *scache, const char *dest_label, 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) @@ -329,6 +339,7 @@ SCACHE *scache_clnt_create(const char *server, int idle_limit, int ttl_limit) 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, diff --git a/postfix/src/global/scache_multi.c b/postfix/src/global/scache_multi.c index 1053fd992..4e82e8e2b 100644 --- a/postfix/src/global/scache_multi.c +++ b/postfix/src/global/scache_multi.c @@ -75,18 +75,18 @@ typedef struct { 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) @@ -97,6 +97,7 @@ typedef struct { */ 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; @@ -111,6 +112,7 @@ static void scache_multi_expire_dest(int, char *); */ 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; @@ -149,12 +151,11 @@ static void scache_multi_drop_endp(SCACHE_MULTI_ENDP *endp, int direction) * 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. @@ -215,9 +216,9 @@ static void scache_multi_save_endp(SCACHE *scache, int ttl, 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; } /* @@ -225,9 +226,11 @@ static void scache_multi_save_endp(SCACHE *scache, int ttl, * 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. @@ -303,12 +306,10 @@ static void scache_multi_drop_dest(SCACHE_MULTI_DEST *dest, int direction) * 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. @@ -371,9 +372,9 @@ static void scache_multi_save_dest(SCACHE *scache, int ttl, 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; } /* @@ -390,6 +391,7 @@ static void scache_multi_save_dest(SCACHE *scache, int ttl, } 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); @@ -446,7 +448,18 @@ static int scache_multi_find_dest(SCACHE *scache, const char *dest_label, 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) { @@ -468,10 +481,12 @@ SCACHE *scache_multi_create(void) 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); } diff --git a/postfix/src/global/scache_multi.ref b/postfix/src/global/scache_multi.ref index 8bf63cb54..972d45cfb 100644 --- a/postfix/src/global/scache_multi.ref +++ b/postfix/src/global/scache_multi.ref @@ -6,96 +6,47 @@ >>> # 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 diff --git a/postfix/src/global/scache_single.c b/postfix/src/global/scache_single.c index c6ad17e4a..28ed333db 100644 --- a/postfix/src/global/scache_single.c +++ b/postfix/src/global/scache_single.c @@ -257,6 +257,17 @@ static int scache_single_find_dest(SCACHE *scache, const char *dest_label, 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) @@ -285,6 +296,7 @@ SCACHE *scache_single_create(void) 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); diff --git a/postfix/src/scache/scache.c b/postfix/src/scache/scache.c index 8ca7858ea..85f7d8164 100644 --- a/postfix/src/scache/scache.c +++ b/postfix/src/scache/scache.c @@ -186,8 +186,11 @@ static SCACHE *scache; */ 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; /* @@ -203,6 +206,7 @@ static void scache_save_endp_service(VSTREAM *client_stream) const char *myname = "scache_save_endp_service"; int ttl; int fd; + SCACHE_SIZE size; if (attr_scan(client_stream, ATTR_FLAG_STRICT, @@ -239,6 +243,11 @@ static void scache_save_endp_service(VSTREAM *client_stream) 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; } } @@ -294,6 +303,7 @@ static void scache_save_dest_service(VSTREAM *client_stream) { const char *myname = "scache_save_dest_service"; int ttl; + SCACHE_SIZE size; if (attr_scan(client_stream, ATTR_FLAG_STRICT, @@ -316,6 +326,12 @@ static void scache_save_dest_service(VSTREAM *client_stream) 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; } } @@ -414,7 +430,9 @@ static void scache_service(VSTREAM *client_stream, char *unused_service, 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); @@ -432,6 +450,13 @@ static void scache_status_dump(char *unused_name, char **unused_argv) / (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(); } diff --git a/postfix/src/smtp/smtp_reuse.c b/postfix/src/smtp/smtp_reuse.c index 705e782ee..f644ded94 100644 --- a/postfix/src/smtp/smtp_reuse.c +++ b/postfix/src/smtp/smtp_reuse.c @@ -151,7 +151,7 @@ void smtp_save_session(SMTP_STATE *state) 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); diff --git a/postfix/src/util/sys_defs.h b/postfix/src/util/sys_defs.h index e56739801..37a3598bb 100644 --- a/postfix/src/util/sys_defs.h +++ b/postfix/src/util/sys_defs.h @@ -911,6 +911,8 @@ extern int h_errno; */ #include #define S_ISSOCK(mode) (((mode) & (S_IFMT)) == (C_ISSOCK)) +#define CANT_USE_SEND_RECV_MSG +#define DEF_SMTP_CACHE_DEMAND 0 #endif /*