diff --git a/postfix/HISTORY b/postfix/HISTORY index 741ec1c24..eefd210ca 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -22419,3 +22419,13 @@ Apologies for any names omitted. after-220 tests. Files: postscreen_misc.c, postscreen_state.c, postscreen.h, postscreen_tests.c, postscreen.c, postscreen_smtpd.c, postscreen_early.c. + +20160730 + + Cleanup: don't try to optimize away postscreen cache updates. + File: postscreen_misc.c. + + Cleanup: removed compatibility crutches that emulated a + historical data organization from four years ago. Files: + postscreen/postscreen.[hc], postscreen/postscreen_early.c, + postscreen/postscreen_smtpd.c, postscreen/postscreen_tests.c. diff --git a/postfix/html/cidr_table.5.html b/postfix/html/cidr_table.5.html index c8f63f9da..879a792ea 100644 --- a/postfix/html/cidr_table.5.html +++ b/postfix/html/cidr_table.5.html @@ -85,16 +85,17 @@ CIDR_TABLE(5) CIDR_TABLE(5) An IPv4 network address is a sequence of four decimal octets separated by ".", and an IPv6 network address is a sequence of three to eight - hexadecimal octets or octet pairs separated by ":". The pattern - 0.0.0.0/0 matches every IPv4 address, and ::/0 matches every IPv6 + hexadecimal octet pairs separated by ":" or "::", where the latter is + short-hand for a sequence of one or more all-zero octet pairs. The pat- + tern 0.0.0.0/0 matches every IPv4 address, and ::/0 matches every IPv6 address. IPv6 support is available in Postfix 2.2 and later. - Before comparisons are made, lookup keys and table entries are con- - verted from string to binary. Therefore, IPv6 patterns will be matched - regardless of leading zeros (a leading zero in an IPv4 address octet + Before comparisons are made, lookup keys and table entries are con- + verted from string to binary. Therefore, IPv6 patterns will be matched + regardless of leading zeros (a leading zero in an IPv4 address octet indicates octal notation). - Note: address information may be enclosed inside "[]" but this form is + Note: address information may be enclosed inside "[]" but this form is not required. EXAMPLE SMTPD ACCESS MAP @@ -106,6 +107,8 @@ CIDR_TABLE(5) CIDR_TABLE(5) # before more general blacklist entries. 192.168.1.1 OK 192.168.0.0/16 REJECT + 2001:db8::1 OK + 2001:db8::/32 REJECT SEE ALSO postmap(1), Postfix lookup table manager diff --git a/postfix/html/postscreen.8.html b/postfix/html/postscreen.8.html index f5884e2cb..71802ff84 100644 --- a/postfix/html/postscreen.8.html +++ b/postfix/html/postscreen.8.html @@ -4,7 +4,7 @@ Postfix manual - postscreen(8)
-POSTSCREEN(8)               System Manager's Manual              POSTSCREEN(8)
+POSTSCREEN(8)                                                    POSTSCREEN(8)
 
 NAME
        postscreen - Postfix zombie blocker
@@ -106,14 +106,14 @@ POSTSCREEN(8)               System Manager's Manual              POSTSCREEN(8)
 
        postscreen_discard_ehlo_keyword_address_maps  ($smtpd_discard_ehlo_key-
        word_address_maps)
-              Lookup tables, indexed by the remote SMTP client  address,  with
-              case  insensitive  lists of EHLO keywords (pipelining, starttls,
-              auth, etc.) that the postscreen(8) server will not send  in  the
+              Lookup  tables,  indexed by the remote SMTP client address, with
+              case insensitive lists of EHLO keywords  (pipelining,  starttls,
+              auth,  etc.)  that the postscreen(8) server will not send in the
               EHLO response to a remote SMTP client.
 
        postscreen_discard_ehlo_keywords ($smtpd_discard_ehlo_keywords)
-              A  case insensitive list of EHLO keywords (pipelining, starttls,
-              auth, etc.) that the postscreen(8) server will not send  in  the
+              A case insensitive list of EHLO keywords (pipelining,  starttls,
+              auth,  etc.)  that the postscreen(8) server will not send in the
               EHLO response to a remote SMTP client.
 
        Available in Postfix version 3.1 and later:
@@ -127,27 +127,27 @@ POSTSCREEN(8)               System Manager's Manual              POSTSCREEN(8)
               postscreen_reject_footer attribute expansions.
 
        postscreen_reject_footer ($smtpd_reject_footer)
-              Optional information  that  is  appended  after  a  4XX  or  5XX
+              Optional  information  that  is  appended  after  a  4XX  or 5XX
               postscreen(8) server response.
 
        soft_bounce (no)
-              Safety  net to keep mail queued that would otherwise be returned
+              Safety net to keep mail queued that would otherwise be  returned
               to the sender.
 
 BEFORE-POSTSCREEN PROXY AGENT
        Available in Postfix version 2.10 and later:
 
        postscreen_upstream_proxy_protocol (empty)
-              The  name  of  the  proxy   protocol   used   by   an   optional
+              The   name   of   the   proxy   protocol  used  by  an  optional
               before-postscreen proxy agent.
 
        postscreen_upstream_proxy_timeout (5s)
-              The  time  limit  for  the  proxy  protocol  specified  with the
+              The time  limit  for  the  proxy  protocol  specified  with  the
               postscreen_upstream_proxy_protocol parameter.
 
 PERMANENT WHITE/BLACKLIST TEST
-       This test is executed immediately after a remote SMTP client  connects.
-       If  a  client is permanently whitelisted, the client will be handed off
+       This  test is executed immediately after a remote SMTP client connects.
+       If a client is permanently whitelisted, the client will be  handed  off
        immediately to a Postfix SMTP server process.
 
        postscreen_access_list (permit_mynetworks)
@@ -155,40 +155,40 @@ POSTSCREEN(8)               System Manager's Manual              POSTSCREEN(8)
 
        postscreen_blacklist_action (ignore)
               The action that postscreen(8) takes when a remote SMTP client is
-              permanently  blacklisted with the postscreen_access_list parame-
+              permanently blacklisted with the postscreen_access_list  parame-
               ter.
 
 MAIL EXCHANGER POLICY TESTS
-       When postscreen(8) is configured to monitor all primary and  backup  MX
-       addresses,  it can refuse to whitelist clients that connect to a backup
+       When  postscreen(8)  is configured to monitor all primary and backup MX
+       addresses, it can refuse to whitelist clients that connect to a  backup
        MX address only. For small sites, this requires configuring primary and
-       backup  MX  addresses on the same MTA. Larger sites would have to share
-       the postscreen(8) cache between primary and backup  MTAs,  which  would
+       backup MX addresses on the same MTA. Larger sites would have  to  share
+       the  postscreen(8)  cache  between primary and backup MTAs, which would
        introduce a common point of failure.
 
        postscreen_whitelist_interfaces (static:all)
-              A  list  of  local  postscreen(8)  server  IP  addresses where a
-              non-whitelisted remote SMTP client  can  obtain  postscreen(8)'s
+              A list of  local  postscreen(8)  server  IP  addresses  where  a
+              non-whitelisted  remote  SMTP  client can obtain postscreen(8)'s
               temporary whitelist status.
 
 BEFORE 220 GREETING TESTS
-       These  tests  are  executed  before the remote SMTP client receives the
+       These tests are executed before the remote  SMTP  client  receives  the
        "220 servername" greeting. If no tests remain after the successful com-
-       pletion  of  this phase, the client will be handed off immediately to a
+       pletion of this phase, the client will be handed off immediately  to  a
        Postfix SMTP server process.
 
        dnsblog_service_name (dnsblog)
               The name of the dnsblog(8) service entry in master.cf.
 
        postscreen_dnsbl_action (ignore)
-              The action that postscreen(8) takes when a remote SMTP  client's
+              The  action that postscreen(8) takes when a remote SMTP client's
               combined DNSBL score is equal to or greater than a threshold (as
-              defined      with      the      postscreen_dnsbl_sites       and
+              defined       with      the      postscreen_dnsbl_sites      and
               postscreen_dnsbl_threshold parameters).
 
        postscreen_dnsbl_reply_map (empty)
-              A  mapping from actual DNSBL domain name which includes a secret
-              password, to the DNSBL domain name that  postscreen  will  reply
+              A mapping from actual DNSBL domain name which includes a  secret
+              password,  to  the  DNSBL domain name that postscreen will reply
               with when it rejects mail.
 
        postscreen_dnsbl_sites (empty)
@@ -196,36 +196,36 @@ POSTSCREEN(8)               System Manager's Manual              POSTSCREEN(8)
               factors.
 
        postscreen_dnsbl_threshold (1)
-              The inclusive lower bound for blocking  a  remote  SMTP  client,
-              based   on   its  combined  DNSBL  score  as  defined  with  the
+              The  inclusive  lower  bound  for blocking a remote SMTP client,
+              based  on  its  combined  DNSBL  score  as  defined   with   the
               postscreen_dnsbl_sites parameter.
 
        postscreen_greet_action (ignore)
-              The action that postscreen(8) takes when a  remote  SMTP  client
-              speaks  before  its  turn  within  the  time  specified with the
+              The  action  that  postscreen(8) takes when a remote SMTP client
+              speaks before its  turn  within  the  time  specified  with  the
               postscreen_greet_wait parameter.
 
        postscreen_greet_banner ($smtpd_banner)
-              The text in the  optional  "220-text..."  server  response  that
+              The  text  in  the  optional  "220-text..." server response that
               postscreen(8) sends ahead of the real Postfix SMTP server's "220
-              text..." response, in an attempt to confuse bad SMTP clients  so
+              text..."  response, in an attempt to confuse bad SMTP clients so
               that they speak before their turn (pre-greet).
 
        postscreen_greet_wait (normal: 6s, overload: 2s)
-              The  amount  of  time  that  postscreen(8) will wait for an SMTP
-              client to send a command before its turn, and for DNS  blocklist
+              The amount of time that postscreen(8)  will  wait  for  an  SMTP
+              client  to send a command before its turn, and for DNS blocklist
               lookup results to arrive (default: up to 2 seconds under stress,
               up to 6 seconds otherwise).
 
        smtpd_service_name (smtpd)
-              The internal service that postscreen(8) hands off  allowed  con-
+              The  internal  service that postscreen(8) hands off allowed con-
               nections to.
 
        Available in Postfix version 2.11 and later:
 
        postscreen_dnsbl_whitelist_threshold (0)
-              Allow  a  remote  SMTP  client  to  skip "before" and "after 220
-              greeting" protocol tests, based on its combined DNSBL  score  as
+              Allow a remote SMTP client  to  skip  "before"  and  "after  220
+              greeting"  protocol  tests, based on its combined DNSBL score as
               defined with the postscreen_dnsbl_sites parameter.
 
        Available in Postfix version 3.0 and later:
@@ -235,18 +235,18 @@ POSTSCREEN(8)               System Manager's Manual              POSTSCREEN(8)
 
 AFTER 220 GREETING TESTS
        These tests are executed after the remote SMTP client receives the "220
-       servername" greeting. If a client passes all tests during  this  phase,
-       it  will  receive  a  4XX  response  to all RCPT TO commands. After the
-       client reconnects, it will be allowed to talk  directly  to  a  Postfix
+       servername"  greeting.  If a client passes all tests during this phase,
+       it will receive a 4XX response to  all  RCPT  TO  commands.  After  the
+       client  reconnects,  it  will  be allowed to talk directly to a Postfix
        SMTP server process.
 
        postscreen_bare_newline_action (ignore)
-              The  action  that  postscreen(8) takes when a remote SMTP client
-              sends a bare newline character, that is, a newline not  preceded
+              The action that postscreen(8) takes when a  remote  SMTP  client
+              sends  a bare newline character, that is, a newline not preceded
               by carriage return.
 
        postscreen_bare_newline_enable (no)
-              Enable  "bare  newline" SMTP protocol tests in the postscreen(8)
+              Enable "bare newline" SMTP protocol tests in  the  postscreen(8)
               server.
 
        postscreen_disable_vrfy_command ($disable_vrfy_command)
@@ -261,7 +261,7 @@ POSTSCREEN(8)               System Manager's Manual              POSTSCREEN(8)
               mencing a MAIL transaction.
 
        postscreen_non_smtp_command_action (drop)
-              The action that postscreen(8) takes when a  remote  SMTP  client
+              The  action  that  postscreen(8) takes when a remote SMTP client
               sends non-SMTP commands as specified with the postscreen_forbid-
               den_commands parameter.
 
@@ -269,12 +269,12 @@ POSTSCREEN(8)               System Manager's Manual              POSTSCREEN(8)
               Enable "non-SMTP command" tests in the postscreen(8) server.
 
        postscreen_pipelining_action (enforce)
-              The action that postscreen(8) takes when a  remote  SMTP  client
+              The  action  that  postscreen(8) takes when a remote SMTP client
               sends multiple commands instead of sending one command and wait-
               ing for the server to respond.
 
        postscreen_pipelining_enable (no)
-              Enable "pipelining" SMTP protocol  tests  in  the  postscreen(8)
+              Enable  "pipelining"  SMTP  protocol  tests in the postscreen(8)
               server.
 
 CACHE CONTROLS
@@ -322,29 +322,29 @@ POSTSCREEN(8)               System Manager's Manual              POSTSCREEN(8)
 
        postscreen_client_connection_count_limit         ($smtpd_client_connec-
        tion_count_limit)
-              How  many  simultaneous  connections  any  remote SMTP client is
+              How many simultaneous connections  any  remote  SMTP  client  is
               allowed to have with the postscreen(8) daemon.
 
        postscreen_command_count_limit (20)
-              The limit on the total number of commands per SMTP  session  for
+              The  limit  on the total number of commands per SMTP session for
               postscreen(8)'s built-in SMTP protocol engine.
 
        postscreen_command_time_limit (normal: 300s, overload: 10s)
-              The   time   limit   to   read   an  entire  command  line  with
+              The  time  limit  to  read   an   entire   command   line   with
               postscreen(8)'s built-in SMTP protocol engine.
 
        postscreen_post_queue_limit ($default_process_limit)
-              The number of clients that can be waiting  for  service  from  a
+              The  number  of  clients  that can be waiting for service from a
               real Postfix SMTP server process.
 
        postscreen_pre_queue_limit ($default_process_limit)
-              The  number of non-whitelisted clients that can be waiting for a
-              decision whether they will receive service from a  real  Postfix
+              The number of non-whitelisted clients that can be waiting for  a
+              decision  whether  they will receive service from a real Postfix
               SMTP server process.
 
        postscreen_watchdog_timeout (10s)
-              How  much  time a postscreen(8) process may take to respond to a
-              remote SMTP client command  or  to  perform  a  cache  operation
+              How much time a postscreen(8) process may take to respond  to  a
+              remote  SMTP  client  command  or  to  perform a cache operation
               before it is terminated by a built-in watchdog timer.
 
 STARTTLS CONTROLS
@@ -357,11 +357,11 @@ POSTSCREEN(8)               System Manager's Manual              POSTSCREEN(8)
               The name of the tlsproxy(8) service entry in master.cf.
 
 OBSOLETE STARTTLS SUPPORT CONTROLS
-       These  parameters  are supported for compatibility with smtpd(8) legacy
+       These parameters are supported for compatibility with  smtpd(8)  legacy
        parameters.
 
        postscreen_use_tls ($smtpd_use_tls)
-              Opportunistic TLS: announce  STARTTLS  support  to  remote  SMTP
+              Opportunistic  TLS:  announce  STARTTLS  support  to remote SMTP
               clients, but do not require that clients use TLS encryption.
 
        postscreen_enforce_tls ($smtpd_enforce_tls)
@@ -370,18 +370,18 @@ POSTSCREEN(8)               System Manager's Manual              POSTSCREEN(8)
 
 MISCELLANEOUS CONTROLS
        config_directory (see 'postconf -d' output)
-              The default location of the Postfix main.cf and  master.cf  con-
+              The  default  location of the Postfix main.cf and master.cf con-
               figuration files.
 
        delay_logging_resolution_limit (2)
-              The  maximal  number of digits after the decimal point when log-
+              The maximal number of digits after the decimal point  when  log-
               ging sub-second delay values.
 
        command_directory (see 'postconf -d' output)
               The location of all postfix administrative commands.
 
        max_idle (100s)
-              The maximum amount of time that an idle Postfix  daemon  process
+              The  maximum  amount of time that an idle Postfix daemon process
               waits for an incoming connection before terminating voluntarily.
 
        process_id (read-only)
@@ -394,9 +394,8 @@ POSTSCREEN(8)               System Manager's Manual              POSTSCREEN(8)
               The syslog facility of Postfix logging.
 
        syslog_name (see 'postconf -d' output)
-              The  mail  system  name that is prepended to the process name in
-              syslog records, so that "smtpd"  becomes,  for  example,  "post-
-              fix/smtpd".
+              A  prefix  that  is  prepended  to  the  process  name in syslog
+              records, so that, for example, "smtpd" becomes "prefix/smtpd".
 
 SEE ALSO
        smtpd(8), Postfix SMTP server
@@ -413,7 +412,7 @@ POSTSCREEN(8)               System Manager's Manual              POSTSCREEN(8)
 HISTORY
        This service was introduced with Postfix version 2.8.
 
-       Many ideas in postscreen(8) were explored in earlier  work  by  Michael
+       Many  ideas  in  postscreen(8) were explored in earlier work by Michael
        Tokarev, in OpenBSD spamd, and in MailChannels Traffic Control.
 
 AUTHOR(S)
diff --git a/postfix/man/man5/cidr_table.5 b/postfix/man/man5/cidr_table.5
index 51a58a9d4..fae30fb96 100644
--- a/postfix/man/man5/cidr_table.5
+++ b/postfix/man/man5/cidr_table.5
@@ -96,10 +96,12 @@ part must be zero).
 
 An IPv4 network address is a sequence of four decimal octets
 separated by ".", and an IPv6 network address is a sequence
-of three to eight hexadecimal octets or octet pairs separated by
-":".  The pattern 0.0.0.0/0 matches every IPv4 address, and ::/0
-matches every IPv6 address.  IPv6 support is available in
-Postfix 2.2 and later.
+of three to eight hexadecimal octet pairs separated by ":"
+or "::", where the latter is short\-hand for a sequence of
+one or more all\-zero octet pairs. The pattern 0.0.0.0/0
+matches every IPv4 address, and ::/0 matches every IPv6
+address.  IPv6 support is available in Postfix 2.2 and
+later.
 
 Before comparisons are made, lookup keys and table entries
 are converted from string to binary. Therefore, IPv6 patterns
@@ -120,6 +122,8 @@ this form is not required.
     # before more general blacklist entries.
     192.168.1.1             OK
     192.168.0.0/16          REJECT
+    2001:db8::1             OK
+    2001:db8::/32           REJECT
 .fi
 .SH "SEE ALSO"
 .na
diff --git a/postfix/man/man8/postscreen.8 b/postfix/man/man8/postscreen.8
index 8d43d953e..0b28e87c9 100644
--- a/postfix/man/man8/postscreen.8
+++ b/postfix/man/man8/postscreen.8
@@ -397,8 +397,8 @@ The process name of a Postfix command or daemon process.
 .IP "\fBsyslog_facility (mail)\fR"
 The syslog facility of Postfix logging.
 .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
-The mail system name that is prepended to the process name in syslog
-records, so that "smtpd" becomes, for example, "postfix/smtpd".
+A prefix that is prepended to the process name in syslog
+records, so that, for example, "smtpd" becomes "prefix/smtpd".
 .SH "SEE ALSO"
 .na
 .nf
diff --git a/postfix/proto/cidr_table b/postfix/proto/cidr_table
index 51d39aa13..91ac7e716 100644
--- a/postfix/proto/cidr_table
+++ b/postfix/proto/cidr_table
@@ -84,10 +84,12 @@
 #
 #	An IPv4 network address is a sequence of four decimal octets
 #	separated by ".", and an IPv6 network address is a sequence
-#	of three to eight hexadecimal octets or octet pairs separated by
-#	":".  The pattern 0.0.0.0/0 matches every IPv4 address, and ::/0
-#	matches every IPv6 address.  IPv6 support is available in
-#	Postfix 2.2 and later.
+#	of three to eight hexadecimal octet pairs separated by ":"
+#	or "::", where the latter is short-hand for a sequence of
+#	one or more all-zero octet pairs. The pattern 0.0.0.0/0
+#	matches every IPv4 address, and ::/0 matches every IPv6
+#	address.  IPv6 support is available in Postfix 2.2 and
+#	later.
 #
 #	Before comparisons are made, lookup keys and table entries
 #	are converted from string to binary. Therefore, IPv6 patterns
@@ -106,6 +108,8 @@
 #	    # before more general blacklist entries.
 #	    192.168.1.1             OK
 #	    192.168.0.0/16          REJECT
+#	    2001:db8::1             OK
+#	    2001:db8::/32           REJECT
 # .fi
 # SEE ALSO
 #	postmap(1), Postfix lookup table manager
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index f723684bf..a7cce8137 100644
--- a/postfix/src/global/mail_version.h
+++ b/postfix/src/global/mail_version.h
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE	"20160728"
+#define MAIL_RELEASE_DATE	"20160730"
 #define MAIL_VERSION_NUMBER	"3.2"
 
 #ifdef SNAPSHOT
diff --git a/postfix/src/postscreen/postscreen.c b/postfix/src/postscreen/postscreen.c
index 4b766d4f0..e2621fba2 100644
--- a/postfix/src/postscreen/postscreen.c
+++ b/postfix/src/postscreen/postscreen.c
@@ -357,8 +357,8 @@
 /* .IP "\fBsyslog_facility (mail)\fR"
 /*	The syslog facility of Postfix logging.
 /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
-/*	The mail system name that is prepended to the process name in syslog
-/*	records, so that "smtpd" becomes, for example, "postfix/smtpd".
+/*	A prefix that is prepended to the process name in syslog
+/*	records, so that, for example, "smtpd" becomes "prefix/smtpd".
 /* SEE ALSO
 /*	smtpd(8), Postfix SMTP server
 /*	tlsproxy(8), Postfix TLS proxy server
@@ -691,7 +691,7 @@ static void psc_endpt_lookup_done(int endpt_status,
      * Reply with 421 when the client has too many open connections.
      */
     if (var_psc_cconn_limit > 0
-	&& state->client_concurrency > var_psc_cconn_limit) {
+	&& state->client_info->concurrency > var_psc_cconn_limit) {
 	msg_info("NOQUEUE: reject: CONNECT from [%s]:%s: too many connections",
 		 state->smtp_client_addr, state->smtp_client_port);
 	PSC_DROP_SESSION_STATE(state,
@@ -840,7 +840,7 @@ static int psc_cache_validator(const char *client_addr,
 			               const char *stamp_str,
 			               void *unused_context)
 {
-    PSC_STATE dummy;
+    PSC_STATE dummy_state;
     PSC_CLIENT_INFO dummy_client_info;
 
     /*
@@ -851,9 +851,9 @@ static int psc_cache_validator(const char *client_addr,
      * silly logging we remove the cache entry only after all tests have
      * expired longer ago than the cache retention time.
      */
-    dummy.client_info = &dummy_client_info;
-    psc_parse_tests(&dummy, stamp_str, event_time() - var_psc_cache_ret);
-    return ((dummy.flags & PSC_STATE_MASK_ANY_TODO) == 0);
+    dummy_state.client_info = &dummy_client_info;
+    psc_parse_tests(&dummy_state, stamp_str, event_time() - var_psc_cache_ret);
+    return ((dummy_state.flags & PSC_STATE_MASK_ANY_TODO) == 0);
 }
 
 /* pre_jail_init - pre-jail initialization */
diff --git a/postfix/src/postscreen/postscreen.h b/postfix/src/postscreen/postscreen.h
index a02fa7fac..119692e6f 100644
--- a/postfix/src/postscreen/postscreen.h
+++ b/postfix/src/postscreen/postscreen.h
@@ -99,19 +99,6 @@ typedef struct {
     const char *where;			/* SMTP protocol state */
 } PSC_STATE;
 
- /*
-  * Emulate legacy ad-hoc variables on top of indexable time stamps. This
-  * avoids massive scar tissue during initial feature development.
-  */
-#define pregr_stamp	client_info->expire_time[PSC_TINDX_PREGR]
-#define dnsbl_stamp	client_info->expire_time[PSC_TINDX_DNSBL]
-#define pipel_stamp	client_info->expire_time[PSC_TINDX_PIPEL]
-#define nsmtp_stamp	client_info->expire_time[PSC_TINDX_NSMTP]
-#define barlf_stamp	client_info->expire_time[PSC_TINDX_BARLF]
-
- /* Minize the patch size for stable releases. */
-#define client_concurrency client_info->concurrency
-
  /*
   * Special expiration time values.
   */
diff --git a/postfix/src/postscreen/postscreen_early.c b/postfix/src/postscreen/postscreen_early.c
index b5bb50e14..50b46eed7 100644
--- a/postfix/src/postscreen/postscreen_early.c
+++ b/postfix/src/postscreen/postscreen_early.c
@@ -104,6 +104,7 @@ static void psc_early_event(int event, void *context)
 {
     const char *myname = "psc_early_event";
     PSC_STATE *state = (PSC_STATE *) context;
+    time_t *expire_time = state->client_info->expire_time;
     char    read_buf[PSC_READ_BUF_SIZE];
     int     read_count;
     DELTA_TIME elapsed;
@@ -142,7 +143,7 @@ static void psc_early_event(int event, void *context)
 	 */
 	if ((state->flags & PSC_STATE_FLAG_PREGR_TODO) != 0
 	    && (state->flags & PSC_STATE_MASK_PREGR_FAIL_DONE) == 0) {
-	    state->pregr_stamp = event_time() + var_psc_pregr_ttl;
+	    expire_time[PSC_TINDX_PREGR] = event_time() + var_psc_pregr_ttl;
 	    PSC_PASS_SESSION_STATE(state, "pregreet test",
 				   PSC_STATE_FLAG_PREGR_PASS);
 	}
@@ -175,7 +176,7 @@ static void psc_early_event(int event, void *context)
 		    psc_whitelist_non_dnsbl(state);
 	    }
 	    if (state->dnsbl_score < var_psc_dnsbl_thresh) {
-		state->dnsbl_stamp = event_time() + state->dnsbl_ttl;
+		expire_time[PSC_TINDX_DNSBL] = event_time() + state->dnsbl_ttl;
 		PSC_PASS_SESSION_STATE(state, "dnsbl test",
 				       PSC_STATE_FLAG_DNSBL_PASS);
 	    } else {
diff --git a/postfix/src/postscreen/postscreen_misc.c b/postfix/src/postscreen/postscreen_misc.c
index 95cd6e9a8..d54b24f9d 100644
--- a/postfix/src/postscreen/postscreen_misc.c
+++ b/postfix/src/postscreen/postscreen_misc.c
@@ -112,10 +112,13 @@ void    psc_conclude(PSC_STATE *state)
     /*
      * Update the postscreen cache. This still supports a scenario where a
      * client gets whitelisted in the course of multiple sessions, as long as
-     * that client does not "fail" any test.
+     * that client does not "fail" any test. Don't try to optimize away cache
+     * updates; we want cached information to be up-to-date even if a test
+     * result is renewed during overlapping SMTP sessions, and even if
+     * 'postfix reload' happens in the middle of that.
      */
     if ((state->flags & PSC_STATE_MASK_ANY_UPDATE) != 0
-	&& psc_cache_map != 0 && state->client_info->pass_new_count <= 1) {
+	&& psc_cache_map != 0) {
 	psc_print_tests(psc_temp, state);
 	psc_cache_update(psc_cache_map, state->smtp_client_addr, STR(psc_temp));
     }
diff --git a/postfix/src/postscreen/postscreen_smtpd.c b/postfix/src/postscreen/postscreen_smtpd.c
index 1717ce277..eac1841b4 100644
--- a/postfix/src/postscreen/postscreen_smtpd.c
+++ b/postfix/src/postscreen/postscreen_smtpd.c
@@ -722,6 +722,7 @@ static void psc_smtpd_read_event(int event, void *context)
 {
     const char *myname = "psc_smtpd_read_event";
     PSC_STATE *state = (PSC_STATE *) context;
+    time_t *expire_time = state->client_info->expire_time;
     int     ch;
     struct cmd_trans {
 	int     state;
@@ -835,7 +836,7 @@ static void psc_smtpd_read_event(int event, void *context)
 			     PSC_CLIENT_ADDR_PORT(state), STR(psc_temp));
 		    PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_BARLF_FAIL);
 		    PSC_UNPASS_SESSION_STATE(state, PSC_STATE_FLAG_BARLF_PASS);
-		    state->barlf_stamp = PSC_TIME_STAMP_DISABLED;	/* XXX */
+		    expire_time[PSC_TINDX_BARLF] = PSC_TIME_STAMP_DISABLED;	/* XXX */
 		    /* Skip this test for the remainder of this session. */
 		    PSC_SKIP_SESSION_STATE(state, "bare newline test",
 					   PSC_STATE_FLAG_BARLF_SKIP);
@@ -855,7 +856,7 @@ static void psc_smtpd_read_event(int event, void *context)
 			/* Temporarily whitelist until something expires. */
 			PSC_PASS_SESSION_STATE(state, "bare newline test",
 					       PSC_STATE_FLAG_BARLF_PASS);
-			state->barlf_stamp = event_time() + psc_min_ttl;
+			expire_time[PSC_TINDX_BARLF] = event_time() + psc_min_ttl;
 			break;
 		    default:
 			msg_panic("%s: unknown bare_newline action value %d",
@@ -960,7 +961,7 @@ static void psc_smtpd_read_event(int event, void *context)
 		     command, STR(psc_temp));
 	    PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_NSMTP_FAIL);
 	    PSC_UNPASS_SESSION_STATE(state, PSC_STATE_FLAG_NSMTP_PASS);
-	    state->nsmtp_stamp = PSC_TIME_STAMP_DISABLED;	/* XXX */
+	    expire_time[PSC_TINDX_NSMTP] = PSC_TIME_STAMP_DISABLED;	/* XXX */
 	    /* Skip this test for the remainder of this SMTP session. */
 	    PSC_SKIP_SESSION_STATE(state, "non-smtp test",
 				   PSC_STATE_FLAG_NSMTP_SKIP);
@@ -980,7 +981,7 @@ static void psc_smtpd_read_event(int event, void *context)
 		/* Temporarily whitelist until something else expires. */
 		PSC_PASS_SESSION_STATE(state, "non-smtp test",
 				       PSC_STATE_FLAG_NSMTP_PASS);
-		state->nsmtp_stamp = event_time() + psc_min_ttl;
+		expire_time[PSC_TINDX_NSMTP] = event_time() + psc_min_ttl;
 		break;
 	    default:
 		msg_panic("%s: unknown non_smtp_command action value %d",
@@ -997,7 +998,7 @@ static void psc_smtpd_read_event(int event, void *context)
 		     PSC_CLIENT_ADDR_PORT(state), command, STR(psc_temp));
 	    PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_PIPEL_FAIL);
 	    PSC_UNPASS_SESSION_STATE(state, PSC_STATE_FLAG_PIPEL_PASS);
-	    state->pipel_stamp = PSC_TIME_STAMP_DISABLED;	/* XXX */
+	    expire_time[PSC_TINDX_PIPEL] = PSC_TIME_STAMP_DISABLED;	/* XXX */
 	    /* Skip this test for the remainder of this SMTP session. */
 	    PSC_SKIP_SESSION_STATE(state, "pipelining test",
 				   PSC_STATE_FLAG_PIPEL_SKIP);
@@ -1017,7 +1018,7 @@ static void psc_smtpd_read_event(int event, void *context)
 		/* Temporarily whitelist until something else expires. */
 		PSC_PASS_SESSION_STATE(state, "pipelining test",
 				       PSC_STATE_FLAG_PIPEL_PASS);
-		state->pipel_stamp = event_time() + psc_min_ttl;
+		expire_time[PSC_TINDX_PIPEL] = event_time() + psc_min_ttl;
 		break;
 	    default:
 		msg_panic("%s: unknown pipelining action value %d",
@@ -1036,21 +1037,21 @@ static void psc_smtpd_read_event(int event, void *context)
 		PSC_PASS_SESSION_STATE(state, "bare newline test",
 				       PSC_STATE_FLAG_BARLF_PASS);
 		/* XXX Reset to PSC_TIME_STAMP_DISABLED on failure. */
-		state->barlf_stamp = event_time() + var_psc_barlf_ttl;
+		expire_time[PSC_TINDX_BARLF] = event_time() + var_psc_barlf_ttl;
 	    }
 	    if ((state->flags & PSC_STATE_MASK_NSMTP_TODO_PASS_FAIL)
 		== PSC_STATE_FLAG_NSMTP_TODO) {
 		PSC_PASS_SESSION_STATE(state, "non-smtp test",
 				       PSC_STATE_FLAG_NSMTP_PASS);
 		/* XXX Reset to PSC_TIME_STAMP_DISABLED on failure. */
-		state->nsmtp_stamp = event_time() + var_psc_nsmtp_ttl;
+		expire_time[PSC_TINDX_NSMTP] = event_time() + var_psc_nsmtp_ttl;
 	    }
 	    if ((state->flags & PSC_STATE_MASK_PIPEL_TODO_PASS_FAIL)
 		== PSC_STATE_FLAG_PIPEL_TODO) {
 		PSC_PASS_SESSION_STATE(state, "pipelining test",
 				       PSC_STATE_FLAG_PIPEL_PASS);
 		/* XXX Reset to PSC_TIME_STAMP_DISABLED on failure. */
-		state->pipel_stamp = event_time() + var_psc_pipel_ttl;
+		expire_time[PSC_TINDX_PIPEL] = event_time() + var_psc_pipel_ttl;
 	    }
 	}
 	/* Command COUNT limit test. */
diff --git a/postfix/src/postscreen/postscreen_tests.c b/postfix/src/postscreen/postscreen_tests.c
index f8b92a988..ef5f98add 100644
--- a/postfix/src/postscreen/postscreen_tests.c
+++ b/postfix/src/postscreen/postscreen_tests.c
@@ -133,6 +133,7 @@
 
 void    psc_new_tests(PSC_STATE *state)
 {
+    time_t *expire_time = state->client_info->expire_time;
 
     /*
      * Give all tests a PSC_TIME_STAMP_NEW time stamp, so that we can later
@@ -140,11 +141,11 @@ void    psc_new_tests(PSC_STATE *state)
      * write a cache entry to the database, any new-but-disabled tests will
      * get a PSC_TIME_STAMP_DISABLED time stamp.
      */
-    state->pregr_stamp = PSC_TIME_STAMP_NEW;
-    state->dnsbl_stamp = PSC_TIME_STAMP_NEW;
-    state->pipel_stamp = PSC_TIME_STAMP_NEW;
-    state->nsmtp_stamp = PSC_TIME_STAMP_NEW;
-    state->barlf_stamp = PSC_TIME_STAMP_NEW;
+    expire_time[PSC_TINDX_PREGR] = PSC_TIME_STAMP_NEW;
+    expire_time[PSC_TINDX_DNSBL] = PSC_TIME_STAMP_NEW;
+    expire_time[PSC_TINDX_PIPEL] = PSC_TIME_STAMP_NEW;
+    expire_time[PSC_TINDX_NSMTP] = PSC_TIME_STAMP_NEW;
+    expire_time[PSC_TINDX_BARLF] = PSC_TIME_STAMP_NEW;
 
     /*
      * Determine what tests need to be completed.
@@ -190,7 +191,7 @@ void    psc_parse_tests(PSC_STATE *state,
 
 void    psc_todo_tests(PSC_STATE *state, time_t time_value)
 {
-    time_t *time_stamps = state->client_info->expire_time;
+    time_t *expire_time = state->client_info->expire_time;
     time_t *sp;
 
     /*
@@ -203,7 +204,7 @@ void    psc_todo_tests(PSC_STATE *state, time_t time_value)
      * enabled tests, but the remote SMTP client has not yet passed all those
      * tests.
      */
-    for (sp = time_stamps; sp < time_stamps + PSC_TINDX_COUNT; sp++) {
+    for (sp = expire_time; sp < expire_time + PSC_TINDX_COUNT; sp++) {
 	if (*sp == PSC_TIME_STAMP_NEW)
 	    state->flags |= PSC_STATE_FLAG_NEW;
     }
@@ -212,15 +213,15 @@ void    psc_todo_tests(PSC_STATE *state, time_t time_value)
      * Don't flag disabled tests as "todo", because there would be no way to
      * make those bits go away.
      */
-    if (PSC_PREGR_TEST_ENABLE() && time_value > state->pregr_stamp)
+    if (PSC_PREGR_TEST_ENABLE() && time_value > expire_time[PSC_TINDX_PREGR])
 	state->flags |= PSC_STATE_FLAG_PREGR_TODO;
-    if (PSC_DNSBL_TEST_ENABLE() && time_value > state->dnsbl_stamp)
+    if (PSC_DNSBL_TEST_ENABLE() && time_value > expire_time[PSC_TINDX_DNSBL])
 	state->flags |= PSC_STATE_FLAG_DNSBL_TODO;
-    if (var_psc_pipel_enable && time_value > state->pipel_stamp)
+    if (var_psc_pipel_enable && time_value > expire_time[PSC_TINDX_PIPEL])
 	state->flags |= PSC_STATE_FLAG_PIPEL_TODO;
-    if (var_psc_nsmtp_enable && time_value > state->nsmtp_stamp)
+    if (var_psc_nsmtp_enable && time_value > expire_time[PSC_TINDX_NSMTP])
 	state->flags |= PSC_STATE_FLAG_NSMTP_TODO;
-    if (var_psc_barlf_enable && time_value > state->barlf_stamp)
+    if (var_psc_barlf_enable && time_value > expire_time[PSC_TINDX_BARLF])
 	state->flags |= PSC_STATE_FLAG_BARLF_TODO;
 
     /*
@@ -235,15 +236,15 @@ void    psc_todo_tests(PSC_STATE *state, time_t time_value)
 	&& var_psc_refresh_time > 0) {
 	time_t  refresh_time = time_value + var_psc_refresh_time;
 
-	if (PSC_PREGR_TEST_ENABLE() && refresh_time > state->pregr_stamp)
+	if (PSC_PREGR_TEST_ENABLE() && refresh_time > expire_time[PSC_TINDX_PREGR])
 	    state->flags |= PSC_STATE_FLAG_PREGR_TODO;
-	if (PSC_DNSBL_TEST_ENABLE() && refresh_time > state->dnsbl_stamp)
+	if (PSC_DNSBL_TEST_ENABLE() && refresh_time > expire_time[PSC_TINDX_DNSBL])
 	    state->flags |= PSC_STATE_FLAG_DNSBL_TODO;
-	if (var_psc_pipel_enable && refresh_time > state->pipel_stamp)
+	if (var_psc_pipel_enable && refresh_time > expire_time[PSC_TINDX_PIPEL])
 	    state->flags |= PSC_STATE_FLAG_PIPEL_TODO;
-	if (var_psc_nsmtp_enable && refresh_time > state->nsmtp_stamp)
+	if (var_psc_nsmtp_enable && refresh_time > expire_time[PSC_TINDX_NSMTP])
 	    state->flags |= PSC_STATE_FLAG_NSMTP_TODO;
-	if (var_psc_barlf_enable && refresh_time > state->barlf_stamp)
+	if (var_psc_barlf_enable && refresh_time > expire_time[PSC_TINDX_BARLF])
 	    state->flags |= PSC_STATE_FLAG_BARLF_TODO;
     }
 #endif
@@ -271,6 +272,7 @@ void    psc_todo_tests(PSC_STATE *state, time_t time_value)
 char   *psc_print_tests(VSTRING *buf, PSC_STATE *state)
 {
     const char *myname = "psc_print_tests";
+    time_t *expire_time = state->client_info->expire_time;
 
     /*
      * Sanity check.
@@ -283,23 +285,23 @@ char   *psc_print_tests(VSTRING *buf, PSC_STATE *state)
      * with "pass new" when some disabled test becomes enabled at some later
      * time.
      */
-    if (PSC_PREGR_TEST_ENABLE() == 0 && state->pregr_stamp == PSC_TIME_STAMP_NEW)
-	state->pregr_stamp = PSC_TIME_STAMP_DISABLED;
-    if (PSC_DNSBL_TEST_ENABLE() == 0 && state->dnsbl_stamp == PSC_TIME_STAMP_NEW)
-	state->dnsbl_stamp = PSC_TIME_STAMP_DISABLED;
-    if (var_psc_pipel_enable == 0 && state->pipel_stamp == PSC_TIME_STAMP_NEW)
-	state->pipel_stamp = PSC_TIME_STAMP_DISABLED;
-    if (var_psc_nsmtp_enable == 0 && state->nsmtp_stamp == PSC_TIME_STAMP_NEW)
-	state->nsmtp_stamp = PSC_TIME_STAMP_DISABLED;
-    if (var_psc_barlf_enable == 0 && state->barlf_stamp == PSC_TIME_STAMP_NEW)
-	state->barlf_stamp = PSC_TIME_STAMP_DISABLED;
+    if (PSC_PREGR_TEST_ENABLE() == 0 && expire_time[PSC_TINDX_PREGR] == PSC_TIME_STAMP_NEW)
+	expire_time[PSC_TINDX_PREGR] = PSC_TIME_STAMP_DISABLED;
+    if (PSC_DNSBL_TEST_ENABLE() == 0 && expire_time[PSC_TINDX_DNSBL] == PSC_TIME_STAMP_NEW)
+	expire_time[PSC_TINDX_DNSBL] = PSC_TIME_STAMP_DISABLED;
+    if (var_psc_pipel_enable == 0 && expire_time[PSC_TINDX_PIPEL] == PSC_TIME_STAMP_NEW)
+	expire_time[PSC_TINDX_PIPEL] = PSC_TIME_STAMP_DISABLED;
+    if (var_psc_nsmtp_enable == 0 && expire_time[PSC_TINDX_NSMTP] == PSC_TIME_STAMP_NEW)
+	expire_time[PSC_TINDX_NSMTP] = PSC_TIME_STAMP_DISABLED;
+    if (var_psc_barlf_enable == 0 && expire_time[PSC_TINDX_BARLF] == PSC_TIME_STAMP_NEW)
+	expire_time[PSC_TINDX_BARLF] = PSC_TIME_STAMP_DISABLED;
 
     vstring_sprintf(buf, "%lu;%lu;%lu;%lu;%lu",
-		    (unsigned long) state->pregr_stamp,
-		    (unsigned long) state->dnsbl_stamp,
-		    (unsigned long) state->pipel_stamp,
-		    (unsigned long) state->nsmtp_stamp,
-		    (unsigned long) state->barlf_stamp);
+		    (unsigned long) expire_time[PSC_TINDX_PREGR],
+		    (unsigned long) expire_time[PSC_TINDX_DNSBL],
+		    (unsigned long) expire_time[PSC_TINDX_PIPEL],
+		    (unsigned long) expire_time[PSC_TINDX_NSMTP],
+		    (unsigned long) expire_time[PSC_TINDX_BARLF]);
     return (STR(buf));
 }