diff -u -r -N squid-3.5.22/cfgaux/config.guess squid-3.5.23/cfgaux/config.guess
--- squid-3.5.22/cfgaux/config.guess	2016-10-10 09:01:53.000000000 +1300
+++ squid-3.5.23/cfgaux/config.guess	2016-12-16 22:28:02.000000000 +1300
@@ -2,7 +2,7 @@
 # Attempt to guess a canonical system name.
 #   Copyright 1992-2016 Free Software Foundation, Inc.
 
-timestamp='2016-04-02'
+timestamp='2016-10-02'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -186,9 +186,12 @@
 	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
 	esac
 	# The Operating System including object format, if it has switched
-	# to ELF recently, or will in the future.
+	# to ELF recently (or will in the future) and ABI.
 	case "${UNAME_MACHINE_ARCH}" in
-	    arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax)
+	    earm*)
+		os=netbsdelf
+		;;
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
 		eval $set_cc_for_build
 		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
 			| grep -q __ELF__
@@ -997,6 +1000,9 @@
 	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
 	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
 	;;
+    mips64el:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
     openrisc*:Linux:*:*)
 	echo or1k-unknown-linux-${LIBC}
 	exit ;;
@@ -1029,6 +1035,9 @@
     ppcle:Linux:*:*)
 	echo powerpcle-unknown-linux-${LIBC}
 	exit ;;
+    riscv32:Linux:*:* | riscv64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
     s390:Linux:*:* | s390x:Linux:*:*)
 	echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
 	exit ;;
@@ -1408,18 +1417,17 @@
 cat >&2 <<EOF
 $0: unable to guess system type
 
-This script, last modified $timestamp, has failed to recognize
-the operating system you are using. It is advised that you
-download the most up to date version of the config scripts from
+This script (version $timestamp), has failed to recognize the
+operating system you are using. If your script is old, overwrite
+config.guess and config.sub with the latest versions from:
 
   http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
 and
   http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
 
-If the version you run ($0) is already up to date, please
-send the following data and any information you think might be
-pertinent to <config-patches@gnu.org> in order to provide the needed
-information to handle your system.
+If $0 has already been updated, send the following data and any
+information you think might be pertinent to config-patches@gnu.org to
+provide the necessary information to handle your system.
 
 config.guess timestamp = $timestamp
 
diff -u -r -N squid-3.5.22/cfgaux/config.sub squid-3.5.23/cfgaux/config.sub
--- squid-3.5.22/cfgaux/config.sub	2016-10-10 09:01:53.000000000 +1300
+++ squid-3.5.23/cfgaux/config.sub	2016-12-16 22:28:02.000000000 +1300
@@ -2,7 +2,7 @@
 # Configuration validation subroutine script.
 #   Copyright 1992-2016 Free Software Foundation, Inc.
 
-timestamp='2016-03-30'
+timestamp='2016-11-04'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -117,7 +117,7 @@
   nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
   linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
   knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
-  kopensolaris*-gnu* | \
+  kopensolaris*-gnu* | cloudabi*-eabi* | \
   storm-chaos* | os2-emx* | rtmk-nova*)
     os=-$maybe_os
     basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
@@ -301,6 +301,7 @@
 	| open8 | or1k | or1knd | or32 \
 	| pdp10 | pdp11 | pj | pjl \
 	| powerpc | powerpc64 | powerpc64le | powerpcle \
+	| pru \
 	| pyramid \
 	| riscv32 | riscv64 \
 	| rl78 | rx \
@@ -428,6 +429,7 @@
 	| orion-* \
 	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
 	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+	| pru-* \
 	| pyramid-* \
 	| riscv32-* | riscv64-* \
 	| rl78-* | romp-* | rs6000-* | rx-* \
@@ -643,6 +645,14 @@
 		basic_machine=m68k-bull
 		os=-sysv3
 		;;
+	e500v[12])
+		basic_machine=powerpc-unknown
+		os=$os"spe"
+		;;
+	e500v[12]-*)
+		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=$os"spe"
+		;;
 	ebmon29k)
 		basic_machine=a29k-amd
 		os=-ebmon
@@ -1022,7 +1032,7 @@
 	ppc-* | ppcbe-*)
 		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
-	ppcle | powerpclittle | ppc-le | powerpc-little)
+	ppcle | powerpclittle)
 		basic_machine=powerpcle-unknown
 		;;
 	ppcle-* | powerpclittle-*)
@@ -1032,7 +1042,7 @@
 		;;
 	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
-	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+	ppc64le | powerpc64little)
 		basic_machine=powerpc64le-unknown
 		;;
 	ppc64le-* | powerpc64little-*)
@@ -1389,7 +1399,7 @@
 	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
 	      | -chorusos* | -chorusrdb* | -cegcc* \
 	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-	      | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+	      | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
 	      | -linux-newlib* | -linux-musl* | -linux-uclibc* \
 	      | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
 	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
@@ -1399,7 +1409,7 @@
 	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
 	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
 	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
-	      | -onefs* | -tirtos*)
+	      | -onefs* | -tirtos* | -phoenix* | -fuchsia*)
 	# Remember, each alternative MUST END IN *, to match a version number.
 		;;
 	-qnx*)
diff -u -r -N squid-3.5.22/ChangeLog squid-3.5.23/ChangeLog
--- squid-3.5.22/ChangeLog	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/ChangeLog	2016-12-16 22:25:05.000000000 +1300
@@ -1,3 +1,26 @@
+Changes to squid-3.5.23 (16 Dec 2016):
+
+	- Bug 4627: fix generate-host-certificates and dynamic_cert_mem_cache_size docs
+	- Bug 4620: NetBSD build error with --enable-ipf-transparent
+	- Bug 4567: Strange IPv6 shown in access.log
+	- Bug 4406: SIGSEV in TunnelStateData::handleConnectResponse() during reconfigure and restart
+	- Bug 4174 partial: fix Write.cc:41 "!ccb->active()" assertion.
+	- Bug 4169: HIT marked as MISS when If-None-Match does not match
+	- Bug 4007: Hang on DNS query with dead-end CNAME
+	- Bug 4004 partial: Fix segfault via Ftp::Client::readControlReply
+	- Bug 3940 partial: hostHeaderVerify failures MISS when they should be HIT
+	- Bug 3533: Cache still valid after HTTP/1.1 303 See Other
+	- Bug 3379: Combination of If-Match and a Cache Hit result in TCP Connection Failure
+	- Bug 3290: authenticate_ttl not working for digest authentication
+	- Bug 2258: bypassing cache but not destroying cache entry
+	- HTTP/1.1: make Vary:* objects cacheable
+	- HTTP/1.1: Add registered codes entry for new 103 (Early Hints) status code
+	- Support IPv6 NAT with PF for NetBSD and FreeBSD
+	- TLS: Make key= before cert= an error instead of quietly hiding the issue
+	- ... and some debug updates
+	- ... and some build fixes
+	- ... and several documentation updates
+
 Changes to squid-3.5.22 (09 Oct 2016):
 
 	- Bug 4594: build failure with clang 3.9
diff -u -r -N squid-3.5.22/configure squid-3.5.23/configure
--- squid-3.5.22/configure	2016-10-10 09:04:24.000000000 +1300
+++ squid-3.5.23/configure	2016-12-16 22:29:49.000000000 +1300
@@ -1,7 +1,7 @@
 #! /bin/sh
 # From configure.ac Revision.
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for Squid Web Proxy 3.5.22.
+# Generated by GNU Autoconf 2.69 for Squid Web Proxy 3.5.23.
 #
 # Report bugs to <http://bugs.squid-cache.org/>.
 #
@@ -595,8 +595,8 @@
 # Identity of this package.
 PACKAGE_NAME='Squid Web Proxy'
 PACKAGE_TARNAME='squid'
-PACKAGE_VERSION='3.5.22'
-PACKAGE_STRING='Squid Web Proxy 3.5.22'
+PACKAGE_VERSION='3.5.23'
+PACKAGE_STRING='Squid Web Proxy 3.5.23'
 PACKAGE_BUGREPORT='http://bugs.squid-cache.org/'
 PACKAGE_URL=''
 
@@ -1636,7 +1636,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures Squid Web Proxy 3.5.22 to adapt to many kinds of systems.
+\`configure' configures Squid Web Proxy 3.5.23 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1707,7 +1707,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of Squid Web Proxy 3.5.22:";;
+     short | recursive ) echo "Configuration of Squid Web Proxy 3.5.23:";;
    esac
   cat <<\_ACEOF
 
@@ -2119,7 +2119,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-Squid Web Proxy configure 3.5.22
+Squid Web Proxy configure 3.5.23
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -3223,7 +3223,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by Squid Web Proxy $as_me 3.5.22, which was
+It was created by Squid Web Proxy $as_me 3.5.23, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -4090,7 +4090,7 @@
 
 # Define the identity of the package.
  PACKAGE='squid'
- VERSION='3.5.22'
+ VERSION='3.5.23'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -41876,7 +41876,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by Squid Web Proxy $as_me 3.5.22, which was
+This file was extended by Squid Web Proxy $as_me 3.5.23, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -41942,7 +41942,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-Squid Web Proxy config.status 3.5.22
+Squid Web Proxy config.status 3.5.23
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff -u -r -N squid-3.5.22/configure.ac squid-3.5.23/configure.ac
--- squid-3.5.22/configure.ac	2016-10-10 09:04:22.000000000 +1300
+++ squid-3.5.23/configure.ac	2016-12-16 22:29:49.000000000 +1300
@@ -5,7 +5,7 @@
 ## Please see the COPYING and CONTRIBUTORS files for details.
 ##
 
-AC_INIT([Squid Web Proxy],[3.5.22],[http://bugs.squid-cache.org/],[squid])
+AC_INIT([Squid Web Proxy],[3.5.23],[http://bugs.squid-cache.org/],[squid])
 AC_PREREQ(2.61)
 AC_CONFIG_HEADERS([include/autoconf.h])
 AC_CONFIG_AUX_DIR(cfgaux)
diff -u -r -N squid-3.5.22/contrib/url-normalizer.pl squid-3.5.23/contrib/url-normalizer.pl
--- squid-3.5.22/contrib/url-normalizer.pl	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/contrib/url-normalizer.pl	2016-12-16 22:25:05.000000000 +1300
@@ -1,4 +1,11 @@
 #!/usr/local/bin/perl -Tw
+#
+# * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+# *
+# * Squid software is distributed under GPLv2+ license and includes
+# * contributions from numerous individuals and organizations.
+# * Please see the COPYING and CONTRIBUTORS files for details.
+#
 
 # From:    Markus Gyger <mgyger@itr.ch>
 #
diff -u -r -N squid-3.5.22/contrib/user-agents.pl squid-3.5.23/contrib/user-agents.pl
--- squid-3.5.22/contrib/user-agents.pl	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/contrib/user-agents.pl	2016-12-16 22:25:05.000000000 +1300
@@ -1,5 +1,13 @@
 #!/usr/bin/perl
 #
+# * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+# *
+# * Squid software is distributed under GPLv2+ license and includes
+# * contributions from numerous individuals and organizations.
+# * Please see the COPYING and CONTRIBUTORS files for details.
+#
+
+#
 # John@MCC.ac.uk
 # John@Pharmweb.NET
 
diff -u -r -N squid-3.5.22/CONTRIBUTORS squid-3.5.23/CONTRIBUTORS
--- squid-3.5.22/CONTRIBUTORS	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/CONTRIBUTORS	2016-12-16 22:25:05.000000000 +1300
@@ -211,6 +211,8 @@
     Joe Ramey <ramey@jello.csc.ti.com>
     Joerg Lehrke <jlehrke@noc.de>
     Johnathan Conley <johnathan.conley@gmail.com>
+    John@MCC.ac.uk
+    John@Pharmweb.NET
     John Dilley <jad@hpl.hp.com>
     John M Cooper <john.cooper@yourcommunications.co.uk>
     John Saunders <johns@rd.scitec.com.au>
diff -u -r -N squid-3.5.22/doc/release-notes/release-3.5.html squid-3.5.23/doc/release-notes/release-3.5.html
--- squid-3.5.22/doc/release-notes/release-3.5.html	2016-10-10 12:34:07.000000000 +1300
+++ squid-3.5.23/doc/release-notes/release-3.5.html	2016-12-17 06:31:15.000000000 +1300
@@ -2,10 +2,10 @@
 <HTML>
 <HEAD>
  <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 0.9.72">
- <TITLE>Squid 3.5.22 release notes</TITLE>
+ <TITLE>Squid 3.5.23 release notes</TITLE>
 </HEAD>
 <BODY>
-<H1>Squid 3.5.22 release notes</H1>
+<H1>Squid 3.5.23 release notes</H1>
 
 <H2>Squid Developers</H2>
 <HR>
@@ -64,7 +64,7 @@
 <HR>
 <H2><A NAME="s1">1.</A> <A HREF="#toc1">Notice</A></H2>
 
-<P>The Squid Team are pleased to announce the release of Squid-3.5.22.</P>
+<P>The Squid Team are pleased to announce the release of Squid-3.5.23.</P>
 <P>This new release is available for download from 
 <A HREF="http://www.squid-cache.org/Versions/v3/3.5/">http://www.squid-cache.org/Versions/v3/3.5/</A> or the
 <A HREF="http://www.squid-cache.org/Download/http-mirrors.html">mirrors</A>.</P>
@@ -715,6 +715,9 @@
 <P>Deprecated. ICAP client is now auto-enabled.
 Use --disable-icap-client to disable if you need to.</P>
 
+<DT><B>--with-nat-devpf</B><DD>
+<P>IPv6 NAT interception support added for BSD built with this option.</P>
+
 </DL>
 </P>
 <H2><A NAME="removedoptions"></A> <A NAME="ss4.3">4.3</A> <A HREF="#toc4.3">Removed options</A>
diff -u -r -N squid-3.5.22/helpers/basic_auth/DB/basic_db_auth.8 squid-3.5.23/helpers/basic_auth/DB/basic_db_auth.8
--- squid-3.5.22/helpers/basic_auth/DB/basic_db_auth.8	2016-10-10 12:34:14.000000000 +1300
+++ squid-3.5.23/helpers/basic_auth/DB/basic_db_auth.8	2016-12-17 06:31:25.000000000 +1300
@@ -129,7 +129,7 @@
 .\" ========================================================================
 .\"
 .IX Title "BASIC_DB_AUTH 8"
-.TH BASIC_DB_AUTH 8 "2016-10-09" "perl v5.24.1" "User Contributed Perl Documentation"
+.TH BASIC_DB_AUTH 8 "2016-12-16" "perl v5.24.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.22/helpers/basic_auth/MSNT-multi-domain/basic_msnt_multi_domain_auth.8 squid-3.5.23/helpers/basic_auth/MSNT-multi-domain/basic_msnt_multi_domain_auth.8
--- squid-3.5.22/helpers/basic_auth/MSNT-multi-domain/basic_msnt_multi_domain_auth.8	2016-10-10 12:34:22.000000000 +1300
+++ squid-3.5.23/helpers/basic_auth/MSNT-multi-domain/basic_msnt_multi_domain_auth.8	2016-12-17 06:31:39.000000000 +1300
@@ -129,7 +129,7 @@
 .\" ========================================================================
 .\"
 .IX Title "BASIC_MSNT_MULTI_DOMAIN_AUTH 1"
-.TH BASIC_MSNT_MULTI_DOMAIN_AUTH 1 "2016-10-09" "perl v5.24.1" "User Contributed Perl Documentation"
+.TH BASIC_MSNT_MULTI_DOMAIN_AUTH 1 "2016-12-16" "perl v5.24.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.22/helpers/basic_auth/POP3/basic_pop3_auth.8 squid-3.5.23/helpers/basic_auth/POP3/basic_pop3_auth.8
--- squid-3.5.22/helpers/basic_auth/POP3/basic_pop3_auth.8	2016-10-10 12:34:31.000000000 +1300
+++ squid-3.5.23/helpers/basic_auth/POP3/basic_pop3_auth.8	2016-12-17 06:31:52.000000000 +1300
@@ -129,7 +129,7 @@
 .\" ========================================================================
 .\"
 .IX Title "BASIC_POP3_AUTH 8"
-.TH BASIC_POP3_AUTH 8 "2016-10-09" "perl v5.24.1" "User Contributed Perl Documentation"
+.TH BASIC_POP3_AUTH 8 "2016-12-16" "perl v5.24.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.22/helpers/external_acl/delayer/ext_delayer_acl.8 squid-3.5.23/helpers/external_acl/delayer/ext_delayer_acl.8
--- squid-3.5.22/helpers/external_acl/delayer/ext_delayer_acl.8	2016-10-10 12:34:52.000000000 +1300
+++ squid-3.5.23/helpers/external_acl/delayer/ext_delayer_acl.8	2016-12-17 06:32:27.000000000 +1300
@@ -129,7 +129,7 @@
 .\" ========================================================================
 .\"
 .IX Title "EXT_DELAYER_ACL 8"
-.TH EXT_DELAYER_ACL 8 "2016-10-09" "perl v5.24.1" "User Contributed Perl Documentation"
+.TH EXT_DELAYER_ACL 8 "2016-12-16" "perl v5.24.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.22/helpers/external_acl/SQL_session/ext_sql_session_acl.8 squid-3.5.23/helpers/external_acl/SQL_session/ext_sql_session_acl.8
--- squid-3.5.22/helpers/external_acl/SQL_session/ext_sql_session_acl.8	2016-10-10 12:35:06.000000000 +1300
+++ squid-3.5.23/helpers/external_acl/SQL_session/ext_sql_session_acl.8	2016-12-17 06:32:48.000000000 +1300
@@ -129,7 +129,7 @@
 .\" ========================================================================
 .\"
 .IX Title "EXT_SQL_SESSION_ACL 8"
-.TH EXT_SQL_SESSION_ACL 8 "2016-10-09" "perl v5.24.1" "User Contributed Perl Documentation"
+.TH EXT_SQL_SESSION_ACL 8 "2016-12-16" "perl v5.24.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.22/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8 squid-3.5.23/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8
--- squid-3.5.22/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8	2016-10-10 12:35:12.000000000 +1300
+++ squid-3.5.23/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8	2016-12-17 06:32:57.000000000 +1300
@@ -129,7 +129,7 @@
 .\" ========================================================================
 .\"
 .IX Title "EXT_WBINFO_GROUP_ACL 8"
-.TH EXT_WBINFO_GROUP_ACL 8 "2016-10-09" "perl v5.24.1" "User Contributed Perl Documentation"
+.TH EXT_WBINFO_GROUP_ACL 8 "2016-12-16" "perl v5.24.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.22/helpers/log_daemon/DB/log_db_daemon.8 squid-3.5.23/helpers/log_daemon/DB/log_db_daemon.8
--- squid-3.5.22/helpers/log_daemon/DB/log_db_daemon.8	2016-10-10 12:35:15.000000000 +1300
+++ squid-3.5.23/helpers/log_daemon/DB/log_db_daemon.8	2016-12-17 06:33:03.000000000 +1300
@@ -129,7 +129,7 @@
 .\" ========================================================================
 .\"
 .IX Title "LOG_DB_DAEMON 8"
-.TH LOG_DB_DAEMON 8 "2016-10-09" "perl v5.24.1" "User Contributed Perl Documentation"
+.TH LOG_DB_DAEMON 8 "2016-12-16" "perl v5.24.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.22/helpers/storeid_rewrite/file/storeid_file_rewrite.8 squid-3.5.23/helpers/storeid_rewrite/file/storeid_file_rewrite.8
--- squid-3.5.22/helpers/storeid_rewrite/file/storeid_file_rewrite.8	2016-10-10 12:35:38.000000000 +1300
+++ squid-3.5.23/helpers/storeid_rewrite/file/storeid_file_rewrite.8	2016-12-17 06:33:38.000000000 +1300
@@ -129,7 +129,7 @@
 .\" ========================================================================
 .\"
 .IX Title "STOREID_FILE_REWRITE 8"
-.TH STOREID_FILE_REWRITE 8 "2016-10-09" "perl v5.24.1" "User Contributed Perl Documentation"
+.TH STOREID_FILE_REWRITE 8 "2016-12-16" "perl v5.24.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.22/include/version.h squid-3.5.23/include/version.h
--- squid-3.5.22/include/version.h	2016-10-10 09:04:24.000000000 +1300
+++ squid-3.5.23/include/version.h	2016-12-16 22:29:49.000000000 +1300
@@ -7,7 +7,7 @@
  */
 
 #ifndef SQUID_RELEASE_TIME
-#define SQUID_RELEASE_TIME 1476043069
+#define SQUID_RELEASE_TIME 1481880292
 #endif
 
 /*
diff -u -r -N squid-3.5.22/RELEASENOTES.html squid-3.5.23/RELEASENOTES.html
--- squid-3.5.22/RELEASENOTES.html	2016-10-10 12:34:07.000000000 +1300
+++ squid-3.5.23/RELEASENOTES.html	2016-12-17 06:31:15.000000000 +1300
@@ -2,10 +2,10 @@
 <HTML>
 <HEAD>
  <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 0.9.72">
- <TITLE>Squid 3.5.22 release notes</TITLE>
+ <TITLE>Squid 3.5.23 release notes</TITLE>
 </HEAD>
 <BODY>
-<H1>Squid 3.5.22 release notes</H1>
+<H1>Squid 3.5.23 release notes</H1>
 
 <H2>Squid Developers</H2>
 <HR>
@@ -64,7 +64,7 @@
 <HR>
 <H2><A NAME="s1">1.</A> <A HREF="#toc1">Notice</A></H2>
 
-<P>The Squid Team are pleased to announce the release of Squid-3.5.22.</P>
+<P>The Squid Team are pleased to announce the release of Squid-3.5.23.</P>
 <P>This new release is available for download from 
 <A HREF="http://www.squid-cache.org/Versions/v3/3.5/">http://www.squid-cache.org/Versions/v3/3.5/</A> or the
 <A HREF="http://www.squid-cache.org/Download/http-mirrors.html">mirrors</A>.</P>
@@ -715,6 +715,9 @@
 <P>Deprecated. ICAP client is now auto-enabled.
 Use --disable-icap-client to disable if you need to.</P>
 
+<DT><B>--with-nat-devpf</B><DD>
+<P>IPv6 NAT interception support added for BSD built with this option.</P>
+
 </DL>
 </P>
 <H2><A NAME="removedoptions"></A> <A NAME="ss4.3">4.3</A> <A HREF="#toc4.3">Removed options</A>
diff -u -r -N squid-3.5.22/src/AccessLogEntry.cc squid-3.5.23/src/AccessLogEntry.cc
--- squid-3.5.22/src/AccessLogEntry.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/AccessLogEntry.cc	2016-12-16 22:25:05.000000000 +1300
@@ -32,12 +32,15 @@
 #endif
         if (tcpClient != NULL)
             log_ip = tcpClient->remote;
-        else if (cache.caddr.isNoAddr()) { // e.g., ICAP OPTIONS lack client
-            strncpy(buf, "-", bufsz);
-            return;
-        } else
+        else
             log_ip = cache.caddr;
 
+    // internally generated requests (and some ICAP) lack client IP
+    if (log_ip.isNoAddr()) {
+        strncpy(buf, "-", bufsz);
+        return;
+    }
+
     // Apply so-called 'privacy masking' to IPv4 clients
     // - localhost IP is always shown in full
     // - IPv4 clients masked with client_netmask
diff -u -r -N squid-3.5.22/src/acl/Checklist.cc squid-3.5.23/src/acl/Checklist.cc
--- squid-3.5.22/src/acl/Checklist.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/acl/Checklist.cc	2016-12-16 22:25:05.000000000 +1300
@@ -397,7 +397,7 @@
 ACLChecklist::bannedAction(const allow_t &action) const
 {
     const bool found = std::find(bannedActions_.begin(), bannedActions_.end(), action) != bannedActions_.end();
-    debugs(28, 5, "Action '" << action << "/" << action.kind << (found ? " is " : "is not") << " banned");
+    debugs(28, 5, "Action '" << action << "/" << action.kind << (found ? "' is " : "' is not") << " banned");
     return found;
 }
 
diff -u -r -N squid-3.5.22/src/acl/ServerName.cc squid-3.5.23/src/acl/ServerName.cc
--- squid-3.5.22/src/acl/ServerName.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/acl/ServerName.cc	2016-12-16 22:25:05.000000000 +1300
@@ -90,27 +90,28 @@
 {
     assert(checklist != NULL && checklist->request != NULL);
 
-    if (checklist->conn() && checklist->conn()->serverBump()) {
-        if (X509 *peer_cert = checklist->conn()->serverBump()->serverCert.get()) {
-            if (Ssl::matchX509CommonNames(peer_cert, (void *)data, check_cert_domain<MatchType>))
-                return 1;
+    const char *serverName = NULL;
+    SBuf serverNameKeeper; // because c_str() is not constant
+    if (ConnStateData *conn = checklist->conn()) {
+        if (conn->serverBump()) {
+            if (X509 *peer_cert = conn->serverBump()->serverCert.get())
+                return Ssl::matchX509CommonNames(peer_cert, (void *)data, check_cert_domain<MatchType>);
         }
-    }
 
-    const char *serverName = NULL;
-    if (checklist->conn() && !checklist->conn()->sslCommonName().isEmpty()) {
-        SBuf scn = checklist->conn()->sslCommonName();
-        serverName = scn.c_str();
+        if (conn->sslCommonName().isEmpty()) {
+            const char *host = checklist->request->GetHost();
+            if (host && *host) // paranoid first condition: host() is never nil
+                serverName = host;
+        } else {
+            serverNameKeeper = conn->sslCommonName();
+            serverName = serverNameKeeper.c_str();
+        }
     }
 
-    if (serverName == NULL)
-        serverName = checklist->request->GetHost();
-
-    if (serverName && data->match(serverName)) {
-        return 1;
-    }
+    if (!serverName)
+        serverName = "none";
 
-    return data->match("none");
+    return data->match(serverName);
 }
 
 ACLServerNameStrategy *
diff -u -r -N squid-3.5.22/src/adaptation/icap/ModXact.cc squid-3.5.23/src/adaptation/icap/ModXact.cc
--- squid-3.5.22/src/adaptation/icap/ModXact.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/adaptation/icap/ModXact.cc	2016-12-16 22:25:05.000000000 +1300
@@ -1303,7 +1303,8 @@
         virgin_msg = virgin_request_;
     assert(virgin_msg != virgin.cause);
     al.http.clientRequestSz.header = virgin_msg->hdr_sz;
-    al.http.clientRequestSz.payloadData = virgin_msg->body_pipe->producedSize();
+    if (virgin_msg->body_pipe != NULL)
+        al.http.clientRequestSz.payloadData = virgin_msg->body_pipe->producedSize();
 
     // leave al.icap.bodyBytesRead negative if no body
     if (replyHttpHeaderSize >= 0 || replyHttpBodySize >= 0) {
diff -u -r -N squid-3.5.22/src/auth/digest/Config.cc squid-3.5.23/src/auth/digest/Config.cc
--- squid-3.5.22/src/auth/digest/Config.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/auth/digest/Config.cc	2016-12-16 22:25:05.000000000 +1300
@@ -204,7 +204,7 @@
     if (!digest_nonce_cache) {
         digest_nonce_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string);
         assert(digest_nonce_cache);
-        eventAdd("Digest none cache maintenance", authenticateDigestNonceCacheCleanup, NULL, static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->nonceGCInterval, 1);
+        eventAdd("Digest nonce cache maintenance", authenticateDigestNonceCacheCleanup, NULL, static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->nonceGCInterval, 1);
     }
 }
 
@@ -268,7 +268,7 @@
     debugs(29, 3, "Finished cleaning the nonce cache.");
 
     if (static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->active())
-        eventAdd("Digest none cache maintenance", authenticateDigestNonceCacheCleanup, NULL, static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->nonceGCInterval, 1);
+        eventAdd("Digest nonce cache maintenance", authenticateDigestNonceCacheCleanup, NULL, static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->nonceGCInterval, 1);
 }
 
 static void
@@ -1058,6 +1058,10 @@
          * the user agent won't change user name without warning.
          */
         authDigestUserLinkNonce(digest_user, nonce);
+
+        /* auth_user is now linked, we reset these values
+         * after external auth occurs anyway */
+        auth_user->expiretime = current_time.tv_sec;
     } else {
         debugs(29, 9, "Found user '" << username << "' in the user cache as '" << auth_user << "'");
         digest_user = static_cast<Auth::Digest::User *>(auth_user.getRaw());
diff -u -r -N squid-3.5.22/src/auth/digest/UserRequest.cc squid-3.5.23/src/auth/digest/UserRequest.cc
--- squid-3.5.22/src/auth/digest/UserRequest.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/auth/digest/UserRequest.cc	2016-12-16 22:25:05.000000000 +1300
@@ -187,12 +187,7 @@
     auth_user->credentials(Auth::Ok);
 
     /* password was checked and did match */
-    debugs(29, 4, HERE << "user '" << auth_user->username() << "' validated OK");
-
-    /* auth_user is now linked, we reset these values
-     * after external auth occurs anyway */
-    auth_user->expiretime = current_time.tv_sec;
-    return;
+    debugs(29, 4, "user '" << auth_user->username() << "' validated OK");
 }
 
 Auth::Direction
diff -u -r -N squid-3.5.22/src/cache_cf.cc squid-3.5.23/src/cache_cf.cc
--- squid-3.5.22/src/cache_cf.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/cache_cf.cc	2016-12-16 22:25:05.000000000 +1300
@@ -2257,6 +2257,9 @@
             safe_free(p->sslcert);
             p->sslcert = xstrdup(token + 8);
         } else if (strncmp(token, "sslkey=", 7) == 0) {
+            if (!p->sslcert) {
+                debugs(3, DBG_CRITICAL, "ERROR: " << cfg_directive << ": sslcert= option must be set before sslkey= is used.");
+            }
             safe_free(p->sslkey);
             p->sslkey = xstrdup(token + 7);
         } else if (strncmp(token, "sslversion=", 11) == 0) {
@@ -3729,6 +3732,9 @@
         safe_free(s->cert);
         s->cert = xstrdup(token + 5);
     } else if (strncmp(token, "key=", 4) == 0) {
+        if (!s->cert) {
+            debugs(3, DBG_CRITICAL, "ERROR: " << cfg_directive << ": cert= option must be set before key= is used.");
+        }
         safe_free(s->key);
         s->key = xstrdup(token + 4);
     } else if (strncmp(token, "version=", 8) == 0) {
diff -u -r -N squid-3.5.22/src/cf.data.pre squid-3.5.23/src/cf.data.pre
--- squid-3.5.22/src/cf.data.pre	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/cf.data.pre	2016-12-16 22:25:05.000000000 +1300
@@ -678,7 +678,7 @@
 
 	  children-max=n
 			Maximum number of acl helper processes spawned to service
-			external acl lookups of this type. (default 20)
+			external acl lookups of this type. (default 5)
 
 	  children-startup=n
 			Minimum number of acl helper processes to spawn during
@@ -1167,6 +1167,9 @@
 	  # During each Ssl-Bump step, Squid may improve its understanding of a
 	  # "true server name". Unlike dstdomain, this ACL does not perform
 	  # DNS lookups.
+	  # The "none" name can be used to match transactions where Squid
+	  # could not compute the server name using any information source
+	  # already available at the ACL evaluation time.
 
 	acl aclname ssl::server_name_regex [-i] \.foo\.com ...
 	  # regex matches server name obtained from various sources [fast]
@@ -1787,13 +1790,12 @@
 			certificate equals lifetime of the CA certificate. If
 			generated certificate is selfsigned lifetime is three 
 			years.
-			This option is enabled by default when ssl-bump is used.
-			See the ssl-bump option above for more information.
+			This option is disabled by default. See the ssl-bump
+			option above for more information.
 			
 	   dynamic_cert_mem_cache_size=SIZE
 			Approximate total RAM size spent on cached generated
-			certificates. If set to zero, caching is disabled. The
-			default value is 4MB.
+			certificates. If set to zero, caching is disabled.
 
 	TLS / SSL Options:
 
@@ -2063,13 +2065,12 @@
 			certificate equals lifetime of CA certificate. If
 			generated certificate is selfsigned lifetime is three
 			years.
-			This option is enabled by default when SslBump is used.
-			See the sslBump option above for more information.
+			This option is disabled by default. See the ssl-bump
+			option above for more information.
 
 	   dynamic_cert_mem_cache_size=SIZE
 			Approximate total RAM size spent on cached generated
-			certificates. If set to zero, caching is disabled. The
-			default value is 4MB.
+			certificates. If set to zero, caching is disabled.
 
 	See http_port for a list of available options.
 DOC_END
diff -u -r -N squid-3.5.22/src/clients/FtpClient.cc squid-3.5.23/src/clients/FtpClient.cc
--- squid-3.5.22/src/clients/FtpClient.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/clients/FtpClient.cc	2016-12-16 22:25:05.000000000 +1300
@@ -442,6 +442,11 @@
     char *buf;
     debugs(9, 3, status());
 
+    if (!Comm::IsConnOpen(ctrl.conn)) {
+        debugs(9, 5, "The control connection to the remote end is closed");
+        return false;
+    }
+
     if (code != 227) {
         debugs(9, 2, "PASV not supported by remote end");
         return false;
@@ -473,6 +478,11 @@
     char *buf;
     debugs(9, 3, status());
 
+    if (!Comm::IsConnOpen(ctrl.conn)) {
+        debugs(9, 5, "The control connection to the remote end is closed");
+        return false;
+    }
+
     if (code != 229 && code != 522) {
         if (code == 200) {
             /* handle broken servers (RFC 2428 says OK code for EPSV MUST be 229 not 200) */
@@ -733,6 +743,11 @@
 void
 Ftp::Client::connectDataChannel()
 {
+    if (!Comm::IsConnOpen(ctrl.conn)) {
+        debugs(9, 5, "The control connection to the remote end is closed");
+        return;
+    }
+
     safe_free(ctrl.last_command);
 
     safe_free(ctrl.last_reply);
diff -u -r -N squid-3.5.22/src/clients/FtpGateway.cc squid-3.5.23/src/clients/FtpGateway.cc
--- squid-3.5.22/src/clients/FtpGateway.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/clients/FtpGateway.cc	2016-12-16 22:25:05.000000000 +1300
@@ -212,7 +212,9 @@
 static FTPSM ftpReadMdtm;
 static FTPSM ftpSendSize;
 static FTPSM ftpReadSize;
+#if 0
 static FTPSM ftpSendEPRT;
+#endif
 static FTPSM ftpReadEPRT;
 static FTPSM ftpSendPORT;
 static FTPSM ftpReadPORT;
@@ -450,6 +452,11 @@
 void
 Ftp::Gateway::listenForDataChannel(const Comm::ConnectionPointer &conn)
 {
+    if (!Comm::IsConnOpen(ctrl.conn)) {
+        debugs(9, 5, "The control connection to the remote end is closed");
+        return;
+    }
+
     assert(!Comm::IsConnOpen(data.conn));
 
     typedef CommCbMemFunT<Gateway, CommAcceptCbParams> AcceptDialer;
@@ -1183,7 +1190,7 @@
 
     checkUrlpath();
     buildTitleUrl();
-    debugs(9, 5, HERE << "FD " << ctrl.conn->fd << " : host=" << request->GetHost() <<
+    debugs(9, 5, "FD " << (ctrl.conn != NULL ? ctrl.conn->fd : -1) << " : host=" << request->GetHost() <<
            ", path=" << request->urlpath << ", user=" << user << ", passwd=" << password);
     state = BEGIN;
     Ftp::Client::start();
@@ -1750,7 +1757,9 @@
     if (ftpState->handlePasvReply(srvAddr))
         ftpState->connectDataChannel();
     else {
-        ftpSendEPRT(ftpState);
+        ftpFail(ftpState);
+        // Currently disabled, does not work correctly:
+        // ftpSendEPRT(ftpState);
         return;
     }
 }
@@ -1790,6 +1799,11 @@
     }
     safe_free(ftpState->data.host);
 
+    if (!Comm::IsConnOpen(ftpState->ctrl.conn)) {
+        debugs(9, 5, "The control connection to the remote end is closed");
+        return;
+    }
+
     /*
      * Set up a listen socket on the same local address as the
      * control connection.
@@ -1875,9 +1889,14 @@
     ftpRestOrList(ftpState);
 }
 
+#if 0
 static void
 ftpSendEPRT(Ftp::Gateway * ftpState)
 {
+    /* check the server control channel is still available */
+    if (!ftpState || !ftpState->haveControlChannel("ftpSendEPRT"))
+        return;
+
     if (Config.Ftp.epsv_all && ftpState->flags.epsv_all_sent) {
         debugs(9, DBG_IMPORTANT, "FTP does not allow EPRT method after 'EPSV ALL' has been sent.");
         return;
@@ -1913,6 +1932,7 @@
     ftpState->writeCommand(cbuf);
     ftpState->state = Ftp::Client::SENT_EPRT;
 }
+#endif
 
 static void
 ftpReadEPRT(Ftp::Gateway * ftpState)
@@ -1939,10 +1959,8 @@
 {
     debugs(9, 3, HERE);
 
-    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
-        abortAll("entry aborted when accepting data conn");
-        data.listenConn->close();
-        data.listenConn = NULL;
+    if (!Comm::IsConnOpen(ctrl.conn)) { /*Close handlers will cleanup*/
+        debugs(9, 5, "The control connection to the remote end is closed");
         return;
     }
 
@@ -1955,6 +1973,14 @@
         return;
     }
 
+    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
+        abortAll("entry aborted when accepting data conn");
+        data.listenConn->close();
+        data.listenConn = NULL;
+        io.conn->close();
+        return;
+    }
+
     /* data listening conn is no longer even open. abort. */
     if (!Comm::IsConnOpen(data.listenConn)) {
         data.listenConn = NULL; // ensure that it's cleared and not just closed.
@@ -2705,8 +2731,8 @@
 Ftp::Gateway::completeForwarding()
 {
     if (fwd == NULL || flags.completed_forwarding) {
-        debugs(9, 3, HERE << "completeForwarding avoids " <<
-               "double-complete on FD " << ctrl.conn->fd << ", Data FD " << data.conn->fd <<
+        debugs(9, 3, "avoid double-complete on FD " <<
+               (ctrl.conn != NULL ? ctrl.conn->fd : -1) << ", Data FD " << data.conn->fd <<
                ", this " << this << ", fwd " << fwd);
         return;
     }
diff -u -r -N squid-3.5.22/src/client_side.cc squid-3.5.23/src/client_side.cc
--- squid-3.5.22/src/client_side.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/client_side.cc	2016-12-16 22:25:05.000000000 +1300
@@ -340,7 +340,21 @@
     AsyncCall::Pointer call = commCbCall(33, 5, "ClientSocketContext::wroteControlMsg",
                                          CommIoCbPtrFun(&WroteControlMsg, this));
 
-    getConn()->writeControlMsgAndCall(this, rep.getRaw(), call);
+    if (!getConn()->writeControlMsgAndCall(this, rep.getRaw(), call)) {
+        // but still inform the caller (so it may resume its operation)
+        doneWithControlMsg();
+    }
+}
+
+void
+ClientSocketContext::doneWithControlMsg()
+{
+    ScheduleCallHere(cbControlMsgSent);
+    cbControlMsgSent = NULL;
+
+    debugs(33, 3, clientConnection << ": calling PushDeferredIfNeeded after control msg wrote");
+    ClientSocketContextPushDeferredIfNeeded(this, getConn());
+
 }
 
 /// called when we wrote the 1xx response
@@ -351,7 +365,7 @@
         return;
 
     if (errflag == Comm::OK) {
-        ScheduleCallHere(cbControlMsgSent);
+        doneWithControlMsg();
         return;
     }
 
@@ -415,6 +429,7 @@
         statCounter.client_http.nearHitSvcTime.count(svc_time);
         break;
 
+    case LOG_TCP_INM_HIT:
     case LOG_TCP_IMS_HIT:
         statCounter.client_http.nearMissSvcTime.count(svc_time);
         break;
@@ -1455,6 +1470,8 @@
 
     if (context != http->getConn()->getCurrentContext())
         context->deferRecipientForLater(node, rep, receivedData);
+    else if (context->controlMsgIsPending())
+        context->deferRecipientForLater(node, rep, receivedData);
     else
         http->getConn()->handleReply(rep, receivedData);
 
diff -u -r -N squid-3.5.22/src/client_side.h squid-3.5.23/src/client_side.h
--- squid-3.5.22/src/client_side.h	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/client_side.h	2016-12-16 22:25:05.000000000 +1300
@@ -129,9 +129,13 @@
     /// starts writing 1xx control message to the client
     void writeControlMsg(HttpControlMsg &msg);
 
+    /// true if 1xx to the user is pending
+    bool controlMsgIsPending() {return cbControlMsgSent != NULL;}
+
 protected:
     static IOCB WroteControlMsg;
     void wroteControlMsg(const Comm::ConnectionPointer &conn, char *bufnotused, size_t size, Comm::Flag errflag, int xerrno);
+    void doneWithControlMsg();
 
 private:
     void prepareReply(HttpReply * rep);
@@ -387,7 +391,7 @@
     void connectionTag(const char *aTag) { connectionTag_ = aTag; }
 
     /// handle a control message received by context from a peer and call back
-    virtual void writeControlMsgAndCall(ClientSocketContext *context, HttpReply *rep, AsyncCall::Pointer &call) = 0;
+    virtual bool writeControlMsgAndCall(ClientSocketContext *context, HttpReply *rep, AsyncCall::Pointer &call) = 0;
 
     /// ClientStream calls this to supply response header (once) and data
     /// for the current ClientSocketContext.
diff -u -r -N squid-3.5.22/src/client_side_reply.cc squid-3.5.23/src/client_side_reply.cc
--- squid-3.5.22/src/client_side_reply.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/client_side_reply.cc	2016-12-16 22:25:05.000000000 +1300
@@ -396,6 +396,15 @@
     if (result.flags.error && !EBIT_TEST(http->storeEntry()->flags, ENTRY_ABORTED))
         return;
 
+    if (collapsedRevalidation == crSlave && EBIT_TEST(http->storeEntry()->flags, KEY_PRIVATE)) {
+        debugs(88, 3, "CF slave hit private " << *http->storeEntry() << ". MISS");
+        // restore context to meet processMiss() expectations
+        restoreState();
+        http->logType = LOG_TCP_MISS;
+        processMiss();
+        return;
+    }
+
     /* update size of the request */
     reqsize = result.length + reqofs;
 
@@ -518,6 +527,16 @@
         return;
     }
 
+    // The previously identified hit suddenly became unsharable!
+    // This is common for collapsed forwarding slaves but might also
+    // happen to regular hits because we are called asynchronously.
+    if (EBIT_TEST(e->flags, KEY_PRIVATE)) {
+        debugs(88, 3, "unsharable " << *e << ". MISS");
+        http->logType = LOG_TCP_MISS;
+        processMiss();
+        return;
+    }
+
     if (result.length == 0) {
         debugs(88, 5, "store IO buffer has no content. MISS");
         /* the store couldn't get enough data from the file for us to id the
@@ -589,6 +608,7 @@
         debugs(88, 5, "negative-HIT");
         http->logType = LOG_TCP_NEGATIVE_HIT;
         sendMoreData(result);
+        return;
     } else if (blockedHit()) {
         debugs(88, 5, "send_hit forces a MISS");
         http->logType = LOG_TCP_MISS;
@@ -641,27 +661,29 @@
             http->logType = LOG_TCP_MISS;
             processMiss();
         }
+        return;
     } else if (r->conditional()) {
         debugs(88, 5, "conditional HIT");
-        processConditional(result);
-    } else {
-        /*
-         * plain ol' cache hit
-         */
-        debugs(88, 5, "plain old HIT");
+        if (processConditional(result))
+            return;
+    }
+
+    /*
+     * plain ol' cache hit
+     */
+    debugs(88, 5, "plain old HIT");
 
 #if USE_DELAY_POOLS
-        if (e->store_status != STORE_OK)
-            http->logType = LOG_TCP_MISS;
-        else
+    if (e->store_status != STORE_OK)
+        http->logType = LOG_TCP_MISS;
+    else
 #endif
-            if (e->mem_status == IN_MEMORY)
-                http->logType = LOG_TCP_MEM_HIT;
-            else if (Config.onoff.offline)
-                http->logType = LOG_TCP_OFFLINE_HIT;
+        if (e->mem_status == IN_MEMORY)
+            http->logType = LOG_TCP_MEM_HIT;
+        else if (Config.onoff.offline)
+            http->logType = LOG_TCP_OFFLINE_HIT;
 
-        sendMoreData(result);
-    }
+    sendMoreData(result);
 }
 
 /**
@@ -755,17 +777,16 @@
 }
 
 /// process conditional request from client
-void
+bool
 clientReplyContext::processConditional(StoreIOBuffer &result)
 {
     StoreEntry *const e = http->storeEntry();
 
     if (e->getReply()->sline.status() != Http::scOkay) {
-        debugs(88, 4, "clientReplyContext::processConditional: Reply code " <<
-               e->getReply()->sline.status() << " != 200");
+        debugs(88, 4, "Reply code " << e->getReply()->sline.status() << " != 200");
         http->logType = LOG_TCP_MISS;
         processMiss();
-        return;
+        return true;
     }
 
     HttpRequest &r = *http->request;
@@ -773,51 +794,39 @@
     if (r.header.has(HDR_IF_MATCH) && !e->hasIfMatchEtag(r)) {
         // RFC 2616: reply with 412 Precondition Failed if If-Match did not match
         sendPreconditionFailedError();
-        return;
+        return true;
     }
 
-    bool matchedIfNoneMatch = false;
     if (r.header.has(HDR_IF_NONE_MATCH)) {
-        if (!e->hasIfNoneMatchEtag(r)) {
-            // RFC 2616: ignore IMS if If-None-Match did not match
-            r.flags.ims = false;
-            r.ims = -1;
-            r.imslen = 0;
-            r.header.delById(HDR_IF_MODIFIED_SINCE);
-            http->logType = LOG_TCP_MISS;
-            sendMoreData(result);
-            return;
-        }
+        // RFC 7232: If-None-Match recipient MUST ignore IMS
+        r.flags.ims = false;
+        r.ims = -1;
+        r.imslen = 0;
+        r.header.delById(HDR_IF_MODIFIED_SINCE);
 
-        if (!r.flags.ims) {
-            // RFC 2616: if If-None-Match matched and there is no IMS,
-            // reply with 304 Not Modified or 412 Precondition Failed
+        if (e->hasIfNoneMatchEtag(r)) {
             sendNotModifiedOrPreconditionFailedError();
-            return;
+            return true;
         }
 
-        // otherwise check IMS below to decide if we reply with 304 or 412
-        matchedIfNoneMatch = true;
+        // None-Match is true (no ETag matched); treat as an unconditional hit
+        return false;
     }
 
     if (r.flags.ims) {
         // handle If-Modified-Since requests from the client
         if (e->modifiedSince(r.ims, r.imslen)) {
-            http->logType = LOG_TCP_IMS_HIT;
-            sendMoreData(result);
-            return;
-        }
+            // Modified-Since is true; treat as an unconditional hit
+            return false;
 
-        if (matchedIfNoneMatch) {
-            // If-None-Match matched, reply with 304 Not Modified or
-            // 412 Precondition Failed
-            sendNotModifiedOrPreconditionFailedError();
-            return;
+        } else {
+            // otherwise reply with 304 Not Modified
+            sendNotModified();
         }
-
-        // otherwise reply with 304 Not Modified
-        sendNotModified();
+        return true;
     }
+
+    return false;
 }
 
 /// whether squid.conf send_hit prevents us from serving this hit
@@ -1345,7 +1354,7 @@
     hdr->delById(HDR_ETAG);
 #endif
 
-    if (is_hit)
+    if (is_hit || collapsedRevalidation == crSlave)
         hdr->delById(HDR_SET_COOKIE);
     // TODO: RFC 2965 : Must honour Cache-Control: no-cache="set-cookie2" and remove header.
 
@@ -1646,7 +1655,9 @@
 {
     HttpRequest *r = http->request;
 
-    if (r->flags.cachable || r->flags.internal) {
+    // client sent CC:no-cache or some other condition has been
+    // encountered which prevents delivering a public/cached object.
+    if (!r->flags.noCache || r->flags.internal) {
         lookingforstore = 5;
         StoreEntry::getPublicByRequest (this, r);
     } else {
@@ -1969,7 +1980,12 @@
     StoreEntry *e = http->storeEntry();
     const time_t timestamp = e->timestamp;
     HttpReply *const temprep = e->getReply()->make304();
-    http->logType = LOG_TCP_IMS_HIT;
+    // log as TCP_INM_HIT if code 304 generated for
+    // If-None-Match request
+    if (!http->request->flags.ims)
+        http->logType = LOG_TCP_INM_HIT;
+    else
+        http->logType = LOG_TCP_IMS_HIT;
     removeClientStoreReference(&sc, http);
     createStoreEntry(http->request->method, RequestFlags());
     e = http->storeEntry();
diff -u -r -N squid-3.5.22/src/client_side_reply.h squid-3.5.23/src/client_side_reply.h
--- squid-3.5.22/src/client_side_reply.h	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/client_side_reply.h	2016-12-16 22:25:05.000000000 +1300
@@ -114,7 +114,7 @@
     bool alwaysAllowResponse(Http::StatusCode sline) const;
     int checkTransferDone();
     void processOnlyIfCachedMiss();
-    void processConditional(StoreIOBuffer &result);
+    bool processConditional(StoreIOBuffer &result);
     void cacheHit(StoreIOBuffer result);
     void handleIMSReply(StoreIOBuffer result);
     void sendMoreData(StoreIOBuffer result);
diff -u -r -N squid-3.5.22/src/external_acl.cc squid-3.5.23/src/external_acl.cc
--- squid-3.5.22/src/external_acl.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/external_acl.cc	2016-12-16 22:25:05.000000000 +1300
@@ -474,13 +474,13 @@
         if (node->children.n_max != DEFAULT_EXTERNAL_ACL_CHILDREN)
             storeAppendPrintf(sentry, " children-max=%d", node->children.n_max);
 
-        if (node->children.n_startup != 1)
+        if (node->children.n_startup != 0) // sync with helper/ChildConfig.cc default
             storeAppendPrintf(sentry, " children-startup=%d", node->children.n_startup);
 
-        if (node->children.n_idle != (node->children.n_max + node->children.n_startup) )
+        if (node->children.n_idle != 1) // sync with helper/ChildConfig.cc default
             storeAppendPrintf(sentry, " children-idle=%d", node->children.n_idle);
 
-        if (node->children.concurrency)
+        if (node->children.concurrency != 0)
             storeAppendPrintf(sentry, " concurrency=%d", node->children.concurrency);
 
         if (node->cache)
diff -u -r -N squid-3.5.22/src/format/Format.cc squid-3.5.23/src/format/Format.cc
--- squid-3.5.22/src/format/Format.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/format/Format.cc	2016-12-16 22:25:05.000000000 +1300
@@ -318,7 +318,7 @@
 actualReplyHeader(const AccessLogEntry::Pointer &al)
 {
     const HttpMsg *msg = al->reply;
-#if USE_ADAPTATION
+#if ICAP_CLIENT
     // al->icap.reqMethod is methodNone in access.log context
     if (!msg && al->icap.reqMethod == Adaptation::methodReqmod)
         msg = al->adapted_request;
@@ -331,7 +331,7 @@
 static const HttpMsg *
 actualRequestHeader(const AccessLogEntry::Pointer &al)
 {
-#if USE_ADAPTATION
+#if ICAP_CLIENT
     // al->icap.reqMethod is methodNone in access.log context
     if (al->icap.reqMethod == Adaptation::methodRespmod) {
         // XXX: for now AccessLogEntry lacks virgin response headers
@@ -819,7 +819,7 @@
         break;
 
         case LFT_REQUEST_ALL_HEADERS:
-#if USE_ADAPTATION
+#if ICAP_CLIENT
             if (al->icap.reqMethod == Adaptation::methodRespmod) {
                 // XXX: since AccessLogEntry::Headers lacks virgin response
                 // headers, do nothing for now
@@ -843,7 +843,7 @@
 
         case LFT_REPLY_ALL_HEADERS:
             out = al->headers.reply;
-#if USE_ADAPTATION
+#if ICAP_CLIENT
             if (!out && al->icap.reqMethod == Adaptation::methodReqmod)
                 out = al->headers.adapted_request;
 #endif
diff -u -r -N squid-3.5.22/src/http/StatusCode.cc squid-3.5.23/src/http/StatusCode.cc
--- squid-3.5.22/src/http/StatusCode.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/http/StatusCode.cc	2016-12-16 22:25:05.000000000 +1300
@@ -33,6 +33,10 @@
         return "Processing";
         break;
 
+    case Http::scEarlyHints: // 103
+        return "Early Hints";
+        break;
+
     // 200-299
     case Http::scOkay:
         return "OK";
diff -u -r -N squid-3.5.22/src/http/StatusCode.h squid-3.5.23/src/http/StatusCode.h
--- squid-3.5.22/src/http/StatusCode.h	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/http/StatusCode.h	2016-12-16 22:25:05.000000000 +1300
@@ -22,6 +22,7 @@
     scContinue = 100,
     scSwitchingProtocols = 101,
     scProcessing = 102,      /**< RFC2518 section 10.1 */
+    scEarlyHints = 103,      /**< draft-kazuho-early-hints-status-code */
     scOkay = 200,
     scCreated = 201,
     scAccepted = 202,
diff -u -r -N squid-3.5.22/src/http.cc squid-3.5.23/src/http.cc
--- squid-3.5.22/src/http.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/http.cc	2016-12-16 22:25:05.000000000 +1300
@@ -191,6 +191,12 @@
     if (!EBIT_TEST(e->flags, KEY_PRIVATE))
         return;
 
+    // If the new/incoming response cannot be stored, then it does not
+    // compete with the old stored response for the public key, and the
+    // old stored response should be left as is.
+    if (e->mem_obj->request && !e->mem_obj->request->flags.cachable)
+        return;
+
     switch (status) {
 
     case Http::scOkay:
@@ -203,6 +209,8 @@
 
     case Http::scFound:
 
+    case Http::scSeeOther:
+
     case Http::scGone:
 
     case Http::scNotFound:
@@ -594,7 +602,7 @@
     while (strListGetItem(&vary, ',', &item, &ilen, &pos)) {
         SBuf name(item, ilen);
         if (name == asterisk) {
-            vstr.clear();
+            vstr = asterisk;
             break;
         }
         name.toLower();
@@ -917,6 +925,12 @@
             varyFailure = true;
         } else {
             entry->mem_obj->vary_headers = vary;
+
+            // RFC 7231 section 7.1.4
+            // Vary:* can be cached, but has mandatory revalidation
+            static const SBuf asterisk("*");
+            if (vary == asterisk)
+                EBIT_SET(entry->flags, ENTRY_REVALIDATE_ALWAYS);
         }
     }
 
diff -u -r -N squid-3.5.22/src/HttpRequest.cc squid-3.5.23/src/HttpRequest.cc
--- squid-3.5.22/src/HttpRequest.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/HttpRequest.cc	2016-12-16 22:25:05.000000000 +1300
@@ -576,8 +576,13 @@
         if (!method.respMaybeCacheable())
             return false;
 
-        // XXX: this would seem the correct place to detect request cache-controls
-        //      no-store, private and related which block cacheability
+        // RFC 7234 section 5.2.1.5:
+        // "cache MUST NOT store any part of either this request or any response to it"
+        //
+        // NP: refresh_pattern ignore-no-store only applies to response messages
+        //     this test is handling request message CC header.
+        if (!flags.ignoreCc && cache_control && cache_control->noStore())
+            return false;
         break;
 
     case AnyP::PROTO_GOPHER:
diff -u -r -N squid-3.5.22/src/ip/Intercept.cc squid-3.5.23/src/ip/Intercept.cc
--- squid-3.5.22/src/ip/Intercept.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/ip/Intercept.cc	2016-12-16 22:25:05.000000000 +1300
@@ -25,6 +25,9 @@
 #define IPFILTER_VERSION        5000004
 #endif
 
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
 #if HAVE_SYS_IOCCOM_H
 #include <sys/ioccom.h>
 #endif
@@ -336,13 +339,20 @@
     }
 
     memset(&nl, 0, sizeof(struct pfioc_natlook));
-    newConn->remote.getInAddr(nl.saddr.v4);
-    nl.sport = htons(newConn->remote.port());
 
-    newConn->local.getInAddr(nl.daddr.v4);
+    if (newConn->remote.isIPv6()) {
+        newConn->remote.getInAddr(nl.saddr.v6);
+        newConn->local.getInAddr(nl.daddr.v6);
+        nl.af = AF_INET6;
+    } else {
+        newConn->remote.getInAddr(nl.saddr.v4);
+        newConn->local.getInAddr(nl.daddr.v4);
+        nl.af = AF_INET;
+    }
+
+    nl.sport = htons(newConn->remote.port());
     nl.dport = htons(newConn->local.port());
 
-    nl.af = AF_INET;
     nl.proto = IPPROTO_TCP;
     nl.direction = PF_OUT;
 
@@ -358,7 +368,10 @@
         debugs(89, 9, HERE << "address: " << newConn);
         return false;
     } else {
-        newConn->local = nl.rdaddr.v4;
+        if (newConn->remote.isIPv6())
+            newConn->local = nl.rdaddr.v6;
+        else
+            newConn->local = nl.rdaddr.v4;
         newConn->local.port(ntohs(nl.rdport));
         debugs(89, 5, HERE << "address NAT: " << newConn);
         return true;
diff -u -r -N squid-3.5.22/src/ipcache.cc squid-3.5.23/src/ipcache.cc
--- squid-3.5.22/src/ipcache.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/ipcache.cc	2016-12-16 22:25:05.000000000 +1300
@@ -123,7 +123,6 @@
 static FREE ipcacheFreeEntry;
 static IDNSCB ipcacheHandleReply;
 static int ipcacheExpiredEntry(ipcache_entry *);
-static int ipcacheParse(ipcache_entry *, const rfc1035_rr *, int, const char *error);
 static ipcache_entry *ipcache_get(const char *);
 static void ipcacheLockEntry(ipcache_entry *);
 static void ipcacheStatPrint(ipcache_entry *, StoreEntry *);
@@ -328,8 +327,7 @@
     ipcacheUnlockEntry(i);
 }
 
-/// \ingroup IPCacheAPI
-static int
+static void
 ipcacheParse(ipcache_entry *i, const rfc1035_rr * answers, int nr, const char *error_message)
 {
     int k;
@@ -350,25 +348,25 @@
     i->addrs.count = 0;
 
     if (nr < 0) {
-        debugs(14, 3, "ipcacheParse: Lookup failed '" << error_message << "' for '" << (const char *)i->hash.key << "'");
+        debugs(14, 3, "Lookup failed '" << error_message << "' for '" << (const char *)i->hash.key << "'");
         i->error_message = xstrdup(error_message);
-        return -1;
+        return;
     }
 
     if (nr == 0) {
-        debugs(14, 3, "ipcacheParse: No DNS records in response to '" << name << "'");
+        debugs(14, 3, "No DNS records in response to '" << name << "'");
         i->error_message = xstrdup("No DNS records");
-        return -1;
+        return;
     }
 
-    debugs(14, 3, "ipcacheParse: " << nr << " answers for '" << name << "'");
+    debugs(14, 3, nr << " answers for '" << name << "'");
     assert(answers);
 
     for (k = 0; k < nr; ++k) {
 
         if (Ip::EnableIpv6 && answers[k].type == RFC1035_TYPE_AAAA) {
             if (answers[k].rdlength != sizeof(struct in6_addr)) {
-                debugs(14, DBG_IMPORTANT, "ipcacheParse: Invalid IPv6 address in response to '" << name << "'");
+                debugs(14, DBG_IMPORTANT, MYNAME << "Invalid IPv6 address in response to '" << name << "'");
                 continue;
             }
             ++na;
@@ -378,7 +376,7 @@
 
         if (answers[k].type == RFC1035_TYPE_A) {
             if (answers[k].rdlength != sizeof(struct in_addr)) {
-                debugs(14, DBG_IMPORTANT, "ipcacheParse: Invalid IPv4 address in response to '" << name << "'");
+                debugs(14, DBG_IMPORTANT, MYNAME << "Invalid IPv4 address in response to '" << name << "'");
                 continue;
             }
             ++na;
@@ -394,14 +392,14 @@
         }
 
         // otherwise its an unknown RR. debug at level 9 since we usually want to ignore these and they are common.
-        debugs(14, 9, HERE << "Unknown RR type received: type=" << answers[k].type << " starting at " << &(answers[k]) );
+        debugs(14, 9, "Unknown RR type received: type=" << answers[k].type << " starting at " << &(answers[k]) );
     }
     if (na == 0) {
-        debugs(14, DBG_IMPORTANT, "ipcacheParse: No Address records in response to '" << name << "'");
+        debugs(14, DBG_IMPORTANT, MYNAME << "No Address records in response to '" << name << "'");
         i->error_message = xstrdup("No Address records");
         if (cname_found)
             ++IpcacheStats.cname_only;
-        return 0;
+        return;
     }
 
     i->addrs.in_addrs = static_cast<Ip::Address *>(xcalloc(na, sizeof(Ip::Address)));
@@ -419,7 +417,7 @@
             memcpy(&temp, answers[k].rdata, sizeof(struct in_addr));
             i->addrs.in_addrs[j] = temp;
 
-            debugs(14, 3, "ipcacheParse: " << name << " #" << j << " " << i->addrs.in_addrs[j]);
+            debugs(14, 3, name << " #" << j << " " << i->addrs.in_addrs[j]);
             ++j;
 
         } else if (Ip::EnableIpv6 && answers[k].type == RFC1035_TYPE_AAAA) {
@@ -430,7 +428,7 @@
             memcpy(&temp, answers[k].rdata, sizeof(struct in6_addr));
             i->addrs.in_addrs[j] = temp;
 
-            debugs(14, 3, "ipcacheParse: " << name << " #" << j << " " << i->addrs.in_addrs[j] );
+            debugs(14, 3, name << " #" << j << " " << i->addrs.in_addrs[j] );
             ++j;
         }
         if (ttl == 0 || (int) answers[k].ttl < ttl)
@@ -453,8 +451,6 @@
     i->expires = squid_curtime + ttl;
 
     i->flags.negcached = false;
-
-    return i->addrs.count;
 }
 
 /// \ingroup IPCacheInternal
@@ -467,13 +463,9 @@
     const int age = i->age();
     statCounter.dns.svcTime.count(age);
 
-    int done = ipcacheParse(i, answers, na, error_message);
-
-    /* If we have not produced either IPs or Error immediately, wait for recursion to finish. */
-    if (done != 0 || error_message != NULL) {
-        ipcacheAddEntry(i);
-        ipcacheCallback(i, age);
-    }
+    ipcacheParse(i, answers, na, error_message);
+    ipcacheAddEntry(i);
+    ipcacheCallback(i, age);
 }
 
 /**
diff -u -r -N squid-3.5.22/src/LogTags.h squid-3.5.23/src/LogTags.h
--- squid-3.5.22/src/LogTags.h	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/LogTags.h	2016-12-16 22:25:05.000000000 +1300
@@ -28,6 +28,7 @@
     LOG_TCP_REFRESH_IGNORED,    // refresh from origin ignored, stale entry sent
     LOG_TCP_CLIENT_REFRESH_MISS,
     LOG_TCP_IMS_HIT,
+    LOG_TCP_INM_HIT,
     LOG_TCP_SWAPFAIL_MISS,
     LOG_TCP_NEGATIVE_HIT,
     LOG_TCP_MEM_HIT,
@@ -54,6 +55,7 @@
     return
         (code == LOG_TCP_HIT) ||
         (code == LOG_TCP_IMS_HIT) ||
+        (code == LOG_TCP_INM_HIT) ||
         (code == LOG_TCP_REFRESH_FAIL_OLD) ||
         (code == LOG_TCP_REFRESH_UNMODIFIED) ||
         (code == LOG_TCP_NEGATIVE_HIT) ||
diff -u -r -N squid-3.5.22/src/SBuf.cc squid-3.5.23/src/SBuf.cc
--- squid-3.5.22/src/SBuf.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/SBuf.cc	2016-12-16 22:25:05.000000000 +1300
@@ -178,7 +178,8 @@
     if (!mustRealloc && len_ >= req.maxCapacity)
         return spaceSize(); // but we cannot reallocate
 
-    const size_type newSpace = std::min(req.idealSpace, maxSize - len_);
+    const size_type desiredSpace = std::max(req.minSpace, req.idealSpace);
+    const size_type newSpace = std::min(desiredSpace, maxSize - len_);
     reserveCapacity(std::min(len_ + newSpace, req.maxCapacity));
     debugs(24, 7, id << " now: " << off_ << '+' << len_ << '+' << spaceSize() <<
            '=' << store_->capacity);
diff -u -r -N squid-3.5.22/src/SBuf.h squid-3.5.23/src/SBuf.h
--- squid-3.5.22/src/SBuf.h	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/SBuf.h	2016-12-16 22:25:05.000000000 +1300
@@ -635,9 +635,10 @@
     /*
      * Parameters are listed in the reverse order of importance: Satisfaction of
      * the lower-listed requirements may violate the higher-listed requirements.
+     * For example, idealSpace has no effect unless it exceeds minSpace.
      */
     size_type idealSpace; ///< if allocating anyway, provide this much space
-    size_type minSpace; ///< allocate if spaceSize() is smaller
+    size_type minSpace; ///< allocate [at least this much] if spaceSize() is smaller
     size_type maxCapacity; ///< do not allocate more than this
     bool allowShared; ///< whether sharing our storage with others is OK
 };
diff -u -r -N squid-3.5.22/src/servers/FtpServer.cc squid-3.5.23/src/servers/FtpServer.cc
--- squid-3.5.22/src/servers/FtpServer.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/servers/FtpServer.cc	2016-12-16 22:25:05.000000000 +1300
@@ -1152,12 +1152,13 @@
     writeErrorReply(reply, 451);
 }
 
-void
+bool
 Ftp::Server::writeControlMsgAndCall(ClientSocketContext *context, HttpReply *reply, AsyncCall::Pointer &call)
 {
     // the caller guarantees that we are dealing with the current context only
     // the caller should also make sure reply->header.has(HDR_FTP_STATUS)
     writeForwardedReplyAndCall(reply, call);
+    return true;
 }
 
 void
diff -u -r -N squid-3.5.22/src/servers/FtpServer.h squid-3.5.23/src/servers/FtpServer.h
--- squid-3.5.22/src/servers/FtpServer.h	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/servers/FtpServer.h	2016-12-16 22:25:05.000000000 +1300
@@ -94,7 +94,7 @@
     virtual void clientPinnedConnectionClosed(const CommCloseCbParams &io);
     virtual void handleReply(HttpReply *header, StoreIOBuffer receivedData);
     virtual int pipelinePrefetchMax() const;
-    virtual void writeControlMsgAndCall(ClientSocketContext *context, HttpReply *rep, AsyncCall::Pointer &call);
+    virtual bool writeControlMsgAndCall(ClientSocketContext *context, HttpReply *rep, AsyncCall::Pointer &call);
     virtual time_t idleTimeout() const;
 
     /* BodyPipe API */
diff -u -r -N squid-3.5.22/src/servers/HttpServer.cc squid-3.5.23/src/servers/HttpServer.cc
--- squid-3.5.22/src/servers/HttpServer.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/servers/HttpServer.cc	2016-12-16 22:25:05.000000000 +1300
@@ -35,7 +35,7 @@
     virtual ClientSocketContext *parseOneRequest(Http::ProtocolVersion &ver);
     virtual void processParsedRequest(ClientSocketContext *context, const Http::ProtocolVersion &ver);
     virtual void handleReply(HttpReply *rep, StoreIOBuffer receivedData);
-    virtual void writeControlMsgAndCall(ClientSocketContext *context, HttpReply *rep, AsyncCall::Pointer &call);
+    virtual bool writeControlMsgAndCall(ClientSocketContext *context, HttpReply *rep, AsyncCall::Pointer &call);
     virtual time_t idleTimeout() const;
 
     /* BodyPipe API */
@@ -167,9 +167,16 @@
     context->sendStartOfMessage(rep, receivedData);
 }
 
-void
+bool
 Http::Server::writeControlMsgAndCall(ClientSocketContext *context, HttpReply *rep, AsyncCall::Pointer &call)
 {
+    // Ignore this late control message if we have started sending a
+    // reply to the user already (e.g., after an error).
+    if (context->reply) {
+        debugs(11, 2, "drop 1xx made late by " << context->reply);
+        return false;
+    }
+
     // apply selected clientReplyContext::buildReplyHeader() mods
     // it is not clear what headers are required for control messages
     rep->header.removeHopByHopEntries();
@@ -184,6 +191,7 @@
     Comm::Write(context->clientConnection, mb, call);
 
     delete mb;
+    return true;
 }
 
 ConnStateData *
diff -u -r -N squid-3.5.22/src/ssl/support.cc squid-3.5.23/src/ssl/support.cc
--- squid-3.5.22/src/ssl/support.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/ssl/support.cc	2016-12-16 22:25:05.000000000 +1300
@@ -2011,10 +2011,17 @@
     pem_password_cb *cb = ::Config.Program.ssl_password ? &ssl_ask_password_cb : NULL;
     pkey.reset(readSslPrivateKey(keyFilename, cb));
     cert.reset(readSslX509CertificatesChain(certFilename, chain.get()));
-    if (!pkey || !cert || !X509_check_private_key(cert.get(), pkey.get())) {
-        pkey.reset(NULL);
-        cert.reset(NULL);
-    }
+    if (!cert) {
+        debugs(83, DBG_IMPORTANT, "WARNING: missing cert in '" << certFilename << "'");
+    } else if (!pkey) {
+        debugs(83, DBG_IMPORTANT, "WARNING: missing private key in '" << keyFilename << "'");
+    } else if (!X509_check_private_key(cert.get(), pkey.get())) {
+        debugs(83, DBG_IMPORTANT, "WARNING: X509_check_private_key() failed to verify signing cert");
+    } else
+        return; // everything is okay
+
+    pkey.reset(NULL);
+    cert.reset(NULL);
 }
 
 bool Ssl::generateUntrustedCert(X509_Pointer &untrustedCert, EVP_PKEY_Pointer &untrustedPkey, X509_Pointer const  &cert, EVP_PKEY_Pointer const & pkey)
diff -u -r -N squid-3.5.22/src/tunnel.cc squid-3.5.23/src/tunnel.cc
--- squid-3.5.22/src/tunnel.cc	2016-10-10 08:58:01.000000000 +1300
+++ squid-3.5.23/src/tunnel.cc	2016-12-16 22:25:05.000000000 +1300
@@ -475,7 +475,8 @@
     *status_ptr = rep.sline.status();
 
     // we need to relay the 401/407 responses when login=PASS(THRU)
-    const char *pwd = server.conn->getPeer()->login;
+    const CachePeer *peer = server.conn->getPeer();
+    const char *pwd = (peer ? peer->login : NULL);
     const bool relay = pwd && (strcmp(pwd, "PASS") == 0 || strcmp(pwd, "PASSTHRU") == 0) &&
                        (*status_ptr == Http::scProxyAuthenticationRequired ||
                         *status_ptr == Http::scUnauthorized);
