unrealircd

- supernets unrealircd source & configuration
git clone git://git.acid.vegas/unrealircd.git
Log | Files | Refs | Archive | README | LICENSE

commit d3c16ac744dec56893ef570fb17a7754f409d164
parent 0e1fefd2d4878a0680ed5959cbbeabc4606763e2
Author: acidvegas <acid.vegas@acid.vegas>
Date: Sun, 21 Mar 2021 13:05:35 -0400

Updated to 5.0.9

Diffstat:
MConfig | 4++--
MMakefile.in | 3++-
Mconfigure | 27++++++++++++++-------------
Mconfigure.ac | 9+++++----
Mdoc/Config.header | 2+-
Adoc/KEYS | 47+++++++++++++++++++++++++++++++++++++++++++++++
Mdoc/RELEASE-NOTES.md | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Mdoc/conf/except.conf | 3---
Mdoc/conf/tls/curl-ca-bundle.crt | 620+++++++++++++++++++++++++------------------------------------------------------
Mdoc/conf/unrealircd.remote.conf | 4++--
Mextras/build-tests/windows/compilecmd/vs2019.bat | 2+-
Mextras/c-ares.tar.gz | 0
Mextras/curlinstall | 2+-
Mextras/doxygen/Doxyfile | 2+-
Mextras/pcre2.tar.gz | 0
Aextras/unrealircd-upgrade-script.in | 105+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Minclude/config.h | 4++--
Minclude/dynconf.h | 12++++++------
Minclude/fdlist.h | 12------------
Minclude/h.h | 8++++++--
Minclude/modules.h | 16+++++++++++++---
Minclude/struct.h | 53+++++++++++++++++++++++++++++++++++------------------
Minclude/windows/setup.h | 2+-
Msrc/conf.c | 166+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Msrc/crashreport.c | 18+++++++++++++-----
Msrc/ircd.c | 13+++++++++++++
Msrc/list.c | 56++++++++++++++++++++++++++++++++++++++++++++++++++------
Msrc/misc.c | 149+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/modules/blacklist.c | 8+++++++-
Msrc/modules/chanmodes/floodprot.c | 405++++++++++++++++++++++++++++---------------------------------------------------
Msrc/modules/channeldb.c | 13++++++++++---
Msrc/modules/nick.c | 35+++++++++++++++++++++++------------
Msrc/modules/nocodes.c | 6+++---
Msrc/modules/reputation.c | 10+++++++++-
Msrc/modules/stats.c | 19++++++++++++-------
Msrc/modules/svsmode.c | 2+-
Msrc/modules/tkl.c | 74+++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Msrc/modules/tkldb.c | 42++++++++++++++++++++++++++----------------
Msrc/modules/websocket.c | 1-
Msrc/numeric.c | 2+-
Msrc/parse.c | 27+++++++++++++--------------
Msrc/send.c | 21++++++---------------
Msrc/socket.c | 18++++++++++++------
Msrc/support.c | 14++++++++++++++
Msrc/user.c | 47+++++++++++++++++++++++++++++++++++++++++++++++
Msrc/version.c.SH | 2+-
Msrc/windows/UnrealIRCd.exe.manifest | 2+-
Msrc/windows/gui.c | 2++
Msrc/windows/unrealinst.iss | 2+-
Msrc/windows/unrealsvc.c | 5+++--
Munrealircd.in | 10+++++++---

51 files changed, 1156 insertions(+), 1026 deletions(-)

diff --git a/Config b/Config
@@ -336,7 +336,7 @@ echo "We will now ask you a number of questions. You can just press ENTER to acc
 echo ""
 
 # This needs to be updated each release so auto-upgrading works for settings, modules, etc!!:
-UNREALRELEASES="unrealircd-5.0.8-rc1 unrealircd-5.0.7 unrealircd-5.0.7-rc1 unrealircd-5.0.6 unrealircd-5.0.5.1 unrealircd-5.0.5 unrealircd-5.0.4 unrealircd-5.0.3.1 unrealircd-5.0.3 unrealircd-5.0.2 unrealircd-5.0.1 unrealircd-5.0.0"
+UNREALRELEASES="unrealircd-5.0.9-rc1 unrealircd-5.0.8 unrealircd-5.0.8-rc1 unrealircd-5.0.7 unrealircd-5.0.7-rc1 unrealircd-5.0.6 unrealircd-5.0.5.1 unrealircd-5.0.5 unrealircd-5.0.4 unrealircd-5.0.3.1 unrealircd-5.0.3 unrealircd-5.0.2 unrealircd-5.0.1 unrealircd-5.0.0"
 if [ -f "config.settings" ]; then
 	. ./config.settings
 else
@@ -707,7 +707,7 @@ while [ -z "$TEST" ] ; do
 	echo "What is the maximum number of sockets (and file descriptors) that"
 	echo "UnrealIRCd may use?"
 	echo "It is recommended to leave this at the default setting 'auto',"
-	echo "which at present results in a limit of up to 8192, depending on"
+	echo "which at present results in a limit of up to 16384, depending on"
 	echo "the system. When you boot UnrealIRCd later you will always see"
 	echo "the effective limit."
 	echo $n "[$TEST] -> $c"
diff --git a/Makefile.in b/Makefile.in
@@ -166,8 +166,9 @@ depend:
 install: all
 	$(INSTALL) -m 0700 -d $(DESTDIR)@BINDIR@
 	$(INSTALL) -m 0700 src/ircd $(DESTDIR)@BINDIR@/unrealircd
+	$(INSTALL) -m 0700 extras/unrealircd-upgrade-script $(DESTDIR)@BINDIR@/unrealircd-upgrade-script
 	$(INSTALL) -m 0700 -d $(DESTDIR)@DOCDIR@
-	$(INSTALL) -m 0600 doc/Authors doc/coding-guidelines doc/tao.of.irc $(DESTDIR)@DOCDIR@
+	$(INSTALL) -m 0600 doc/Authors doc/coding-guidelines doc/tao.of.irc doc/KEYS doc/RELEASE-NOTES.md $(DESTDIR)@DOCDIR@
 	$(INSTALL) -m 0700 -d $(DESTDIR)@CONFDIR@
 	$(INSTALL) -m 0600 doc/conf/*.conf $(DESTDIR)@CONFDIR@
 	$(INSTALL) -m 0600 doc/conf/*.motd $(DESTDIR)@CONFDIR@
diff --git a/configure b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for unrealircd 5.0.8.
+# Generated by GNU Autoconf 2.69 for unrealircd 5.0.9.
 #
 # Report bugs to <https://bugs.unrealircd.org/>.
 #
@@ -580,8 +580,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='unrealircd'
 PACKAGE_TARNAME='unrealircd'
-PACKAGE_VERSION='5.0.8'
-PACKAGE_STRING='unrealircd 5.0.8'
+PACKAGE_VERSION='5.0.9'
+PACKAGE_STRING='unrealircd 5.0.9'
 PACKAGE_BUGREPORT='https://bugs.unrealircd.org/'
 PACKAGE_URL='https://unrealircd.org/'
 
@@ -1325,7 +1325,7 @@ if test "$ac_init_help" = "long"; then
   # 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 unrealircd 5.0.8 to adapt to many kinds of systems.
+\`configure' configures unrealircd 5.0.9 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1391,7 +1391,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of unrealircd 5.0.8:";;
+     short | recursive ) echo "Configuration of unrealircd 5.0.9:";;
    esac
   cat <<\_ACEOF
 
@@ -1544,7 +1544,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-unrealircd configure 5.0.8
+unrealircd configure 5.0.9
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1913,7 +1913,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by unrealircd $as_me 5.0.8, which was
+It was created by unrealircd $as_me 5.0.9, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2321,7 +2321,7 @@ _ACEOF
 
 
 # Minor version number (e.g.: Z in X.Y.Z)
-UNREAL_VERSION_MINOR="8"
+UNREAL_VERSION_MINOR="9"
 
 cat >>confdefs.h <<_ACEOF
 #define UNREAL_VERSION_MINOR $UNREAL_VERSION_MINOR
@@ -7044,7 +7044,7 @@ fi
 
 if test "$has_system_pcre2" = "no"; then :
 
-pcre2_version="10.33"
+pcre2_version="10.36"
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: extracting PCRE2 regex library" >&5
 $as_echo "extracting PCRE2 regex library" >&6; }
 cur_dir=`pwd`
@@ -7281,7 +7281,7 @@ fi
 
 if test "$has_system_cares" = "no"; then :
 
-cares_version="1.16.0"
+cares_version="1.17.1"
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: extracting c-ares resolver library" >&5
 $as_echo "extracting c-ares resolver library" >&6; }
 cur_dir=`pwd`
@@ -7984,7 +7984,7 @@ fi
 
 
 
-ac_config_files="$ac_config_files Makefile src/Makefile src/modules/Makefile src/modules/chanmodes/Makefile src/modules/usermodes/Makefile src/modules/snomasks/Makefile src/modules/extbans/Makefile src/modules/third/Makefile unrealircd"
+ac_config_files="$ac_config_files Makefile src/Makefile src/modules/Makefile src/modules/chanmodes/Makefile src/modules/usermodes/Makefile src/modules/snomasks/Makefile src/modules/extbans/Makefile src/modules/third/Makefile extras/unrealircd-upgrade-script unrealircd"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -8492,7 +8492,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by unrealircd $as_me 5.0.8, which was
+This file was extended by unrealircd $as_me 5.0.9, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -8555,7 +8555,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-unrealircd config.status 5.0.8
+unrealircd config.status 5.0.9
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -8685,6 +8685,7 @@ do
     "src/modules/snomasks/Makefile") CONFIG_FILES="$CONFIG_FILES src/modules/snomasks/Makefile" ;;
     "src/modules/extbans/Makefile") CONFIG_FILES="$CONFIG_FILES src/modules/extbans/Makefile" ;;
     "src/modules/third/Makefile") CONFIG_FILES="$CONFIG_FILES src/modules/third/Makefile" ;;
+    "extras/unrealircd-upgrade-script") CONFIG_FILES="$CONFIG_FILES extras/unrealircd-upgrade-script" ;;
     "unrealircd") CONFIG_FILES="$CONFIG_FILES unrealircd" ;;
 
   *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
diff --git a/configure.ac b/configure.ac
@@ -7,7 +7,7 @@ dnl src/windows/unrealinst.iss
 dnl doc/Config.header
 dnl src/version.c.SH
 
-AC_INIT([unrealircd], [5.0.8], [https://bugs.unrealircd.org/], [], [https://unrealircd.org/])
+AC_INIT([unrealircd], [5.0.9], [https://bugs.unrealircd.org/], [], [https://unrealircd.org/])
 AC_CONFIG_SRCDIR([src/ircd.c])
 AC_CONFIG_HEADER([include/setup.h])
 AC_CONFIG_AUX_DIR([autoconf])
@@ -34,7 +34,7 @@ UNREAL_VERSION_MAJOR=["0"]
 AC_DEFINE_UNQUOTED([UNREAL_VERSION_MAJOR], [$UNREAL_VERSION_MAJOR], [Major version number (e.g.: Y for X.Y.Z)])
 
 # Minor version number (e.g.: Z in X.Y.Z)
-UNREAL_VERSION_MINOR=["8"]
+UNREAL_VERSION_MINOR=["9"]
 AC_DEFINE_UNQUOTED([UNREAL_VERSION_MINOR], [$UNREAL_VERSION_MINOR], [Minor version number (e.g.: Z for X.Y.Z)])
 
 # The version suffix such as a beta marker or release candidate
@@ -544,7 +544,7 @@ AS_IF([test "x$PRIVATELIBDIR" != "x"], [rm -f "$PRIVATELIBDIR/"libpcre2*])],[has
 
 AS_IF([test "$has_system_pcre2" = "no"], [
 dnl REMEMBER TO CHANGE WITH A NEW PCRE2 RELEASE!
-pcre2_version="10.33"
+pcre2_version="10.36"
 AC_MSG_RESULT(extracting PCRE2 regex library)
 cur_dir=`pwd`
 cd extras
@@ -635,7 +635,7 @@ AS_IF([test "$has_system_cares" = "no"], [
 dnl REMEMBER TO CHANGE WITH A NEW C-ARES RELEASE!
 dnl NOTE: when changing this here, ALSO change it in extras/curlinstall
 dnl       and in the comment in this file around line 400!
-cares_version="1.16.0"
+cares_version="1.17.1"
 AC_MSG_RESULT(extracting c-ares resolver library)
 cur_dir=`pwd`
 cd extras
@@ -730,6 +730,7 @@ AC_CONFIG_FILES([Makefile
 	src/modules/snomasks/Makefile
 	src/modules/extbans/Makefile
 	src/modules/third/Makefile
+	extras/unrealircd-upgrade-script
 	unrealircd])
 AC_OUTPUT
 chmod 0700 unrealircd
diff --git a/doc/Config.header b/doc/Config.header
@@ -7,7 +7,7 @@
  \___/|_| |_|_|  \___|\__,_|_|\___/\_| \_| \____/\__,_|
 
                                Configuration Program
-                                for UnrealIRCd 5.0.8
+                                for UnrealIRCd 5.0.9
                                     
 This program will help you to compile your IRC server, and ask you
 questions regarding the compile-time settings of it during the process. 
diff --git a/doc/KEYS b/doc/KEYS
@@ -0,0 +1,47 @@
+pub   rsa4096 2015-07-02 [SC] [expires: 2025-06-29]
+      1D2D2B03A0B68ED11D68A24BA7A21B0A108FF4A9
+uid           UnrealIRCd releases (for verification of software downloads only!) <releases@unrealircd.org>
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+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
+=foLZ
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/doc/RELEASE-NOTES.md b/doc/RELEASE-NOTES.md
@@ -1,6 +1,69 @@
-UnrealIRCd 5.0.8 Release Notes
+UnrealIRCd 5.0.9 Release Notes
 ===============================
 
+This release comes with several nice feature enhancements. There are no major bug fixes.
+
+Enhancements:
+* Changes to the "Client connecting" notice on IRC (for IRCOps):
+  * The format changed slightly, instead of ```{clients}``` it
+    now shows ```[class: clients]```
+  * SSL/TLS information is still shown via ```[secure]```
+  * New: ```[reputation: NNN]``` to show the current
+    [reputation score](https://www.unrealircd.org/docs/Reputation_score)
+  * New: ```[account: abcdef]``` to show the services account,
+    but only if [SASL](https://www.unrealircd.org/docs/SASL) was used.
+* In the log file the format also changed slightly:
+  * IP information is now added as ```[127.0.0.1]``` in both the
+    connect and disconnect log messages.
+  * The vhost is logged as ```[vhost: xyz]``` instead of ```[VHOST xyz]```
+  * All the other values are now logged as well on-connect,
+    similar to the "Client connecting" notice, so: secure, reputation,
+    account (if applicable).
+* New option [allow::global-maxperip](https://www.unrealircd.org/docs/Allow_block):
+  this imposes a global (network-wide) restriction on the number of
+  connections per IP address.
+  If you don't have a global-maxperip setting in the allow block then it
+  will default to maxperip plus one. So, if you currently have an
+  allow::maxperip of 3 then global-maxperip will be 4.
+* [Handshake delay](https://www.unrealircd.org/docs/Set_block#set::handshake-delay)
+  is automatically disabled for users that are exempt from blacklist checking.
+* Always exempt 127.* from gline, kline, etc.
+* You can now have dated logfiles thanks to strftime formatting.
+  For example ```log "ircd.%Y-%m-%d.log" { }``` will create a log
+  file like called ircd.2020-01-31.log, a new one every day.
+* The Windows build now supports TLSv1.3 too.
+
+Fixes:
+* Windows: some warnings and error messages on boot were previously
+  missing.
+
+Changes:
+* Add doc/KEYS which contains the public key(s) used to sign UnrealIRCd releases
+* The options set::anti-flood::unknown-flood-* have been renamed and
+integrated in a new block called
+[set::anti-flood::handshake-data-flood](https://www.unrealircd.org/docs/Set_block#set::anti-flood::handshake-data-flood).
+The ban-action can now also be changed. Note that almost nobody will have to
+change this setting since it has a good default.
+* On *NIX bump the default maximum connections from 8192 to 16384.
+That is, when in "auto" mode, which is like for 99% of the users.
+Note that the system may still limit the actual number of connections
+to a lower value, epending on the value of ```ulimit -n -H```.
+
+Reminder: UnrealIRCd 4 is no longer supported
+----------------------------------------------
+
+UnrealIRCd 4.x is [no longer supported](https://www.unrealircd.org/docs/UnrealIRCd_4_EOL).
+Admins must upgrade to UnrealIRCd 5.
+
+Upgrading from 4.x to 5.x?
+Then check out the *UnrealIRCd 5* release notes [further down](#unrealircd-5).
+Or, at the very least, check out
+[Upgrading from 4.x](https://www.unrealircd.org/docs/Upgrading_from_4.x).
+
+
+UnrealIRCd 5.0.8
+-----------------
+
 The main purpose of this release is to enhance the
 [reputation](https://www.unrealircd.org/docs/Reputation_score)
 functionality. There have also been some other changes and minor
@@ -53,17 +116,6 @@ Module coders / Developers:
   [Hook API](https://www.unrealircd.org/api/5/group__HookAPI.html)
   is now 100% documented.
 
-Reminder: UnrealIRCd 4 is no longer supported
-----------------------------------------------
-
-UnrealIRCd 4.x is [no longer supported](https://www.unrealircd.org/docs/UnrealIRCd_4_EOL).
-Admins must upgrade to UnrealIRCd 5.
-
-Upgrading from 4.x to 5.x?
-Then check out the *UnrealIRCd 5* release notes [further down](#unrealircd-5).
-Or, at the very least, check out
-[Upgrading from 4.x](https://www.unrealircd.org/docs/Upgrading_from_4.x).
-
 UnrealIRCd 5.0.7
 -----------------
 
diff --git a/doc/conf/except.conf b/doc/conf/except.conf
@@ -1,6 +1,3 @@
-# Localhost
-except ban { mask *@127.0.0.1; }
-
 # IRCCloud
 except ban { mask *@192.184.9.108;      } # highgate.irccloud.com
 except ban { mask *@192.184.9.110;      } # ealing.irccloud.com
diff --git a/doc/conf/tls/curl-ca-bundle.crt b/doc/conf/tls/curl-ca-bundle.crt
@@ -1,7 +1,7 @@
 ##
 ## Bundle of CA Root Certificates
 ##
-## Certificate data from Mozilla as of: Wed Jan  1 04:12:10 2020 GMT
+## Certificate data from Mozilla as of: Tue Jan 19 04:12:04 2021 GMT
 ##
 ## This is a bundle of X.509 certificates of public Certificate Authorities
 ## (CA). These were automatically extracted from Mozilla's root certificates
@@ -13,8 +13,8 @@
 ## an Apache+mod_ssl webserver for SSL client authentication.
 ## Just configure this file as the SSLCACertificateFile.
 ##
-## Conversion done with mk-ca-bundle.pl version 1.27.
-## SHA256: f3bdcd74612952da8476a9d4147f50b29ad0710b7dd95b4c8690500209986d70
+## Conversion done with mk-ca-bundle.pl version 1.28.
+## SHA256: 3bdc63d1de27058fec943a999a2a8a01fcc6806a611b19221a7727d3d9bbbdfd
 ##
 
 
@@ -61,30 +61,6 @@ BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp
 TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
 -----END CERTIFICATE-----
 
-Verisign Class 3 Public Primary Certification Authority - G3
-============================================================
------BEGIN CERTIFICATE-----
-MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
-UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
-cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
-IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
-dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
-CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
-dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
-cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg
-Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1
-EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc
-cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw
-EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj
-055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
-ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f
-j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
-/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0
-xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa
-t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
------END CERTIFICATE-----
-
 Entrust.net Premium 2048 Secure Server CA
 =========================================
 -----BEGIN CERTIFICATE-----
@@ -130,30 +106,6 @@ Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
 RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
 -----END CERTIFICATE-----
 
-AddTrust External Root
-======================
------BEGIN CERTIFICATE-----
-MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
-QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD
-VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw
-NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU
-cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg
-Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821
-+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw
-Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo
-aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy
-2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7
-7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P
-BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL
-VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk
-VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB
-IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl
-j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
-6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355
-e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u
-G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
------END CERTIFICATE-----
-
 Entrust Root Certification Authority
 ====================================
 -----BEGIN CERTIFICATE-----
@@ -180,87 +132,6 @@ W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0
 tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8
 -----END CERTIFICATE-----
 
-GeoTrust Global CA
-==================
------BEGIN CERTIFICATE-----
-MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
-Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw
-MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
-LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo
-BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet
-8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc
-T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU
-vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD
-AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk
-DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q
-zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4
-d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2
-mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p
-XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm
-Mw==
------END CERTIFICATE-----
-
-GeoTrust Universal CA
-=====================
------BEGIN CERTIFICATE-----
-MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
-R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1
-MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu
-Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
-ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t
-JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e
-RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs
-7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d
-8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V
-qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga
-Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB
-Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu
-KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08
-ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0
-XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB
-hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
-aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2
-qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL
-oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK
-xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF
-KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2
-DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK
-xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU
-p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI
-P/rmMuGNG2+k5o7Y+SlIis5z/iw=
------END CERTIFICATE-----
-
-GeoTrust Universal CA 2
-=======================
------BEGIN CERTIFICATE-----
-MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
-R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0
-MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg
-SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA
-A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0
-DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17
-j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q
-JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a
-QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2
-WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP
-20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn
-ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC
-SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG
-8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2
-+/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E
-BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
-dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ
-4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+
-mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq
-A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg
-Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP
-pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d
-FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp
-gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm
-X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
------END CERTIFICATE-----
-
 Comodo AAA Services root
 ========================
 -----BEGIN CERTIFICATE-----
@@ -496,36 +367,6 @@ KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3
 QBFGmh95DmK/D5fs4C8fF5Q=
 -----END CERTIFICATE-----
 
-Taiwan GRCA
-===========
------BEGIN CERTIFICATE-----
-MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG
-EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X
-DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv
-dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD
-ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN
-w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5
-BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O
-1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO
-htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov
-J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7
-Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t
-B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB
-O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8
-lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV
-HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2
-09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ
-TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj
-Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2
-Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU
-D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz
-DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk
-Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk
-7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ
-CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy
-+fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS
------END CERTIFICATE-----
-
 DigiCert Assured ID Root CA
 ===========================
 -----BEGIN CERTIFICATE-----
@@ -674,78 +515,6 @@ DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub
 DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
 -----END CERTIFICATE-----
 
-GeoTrust Primary Certification Authority
-========================================
------BEGIN CERTIFICATE-----
-MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG
-EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD
-ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx
-CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ
-cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN
-b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9
-nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge
-RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt
-tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
-AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI
-hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K
-Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN
-NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa
-Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG
-1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
------END CERTIFICATE-----
-
-thawte Primary Root CA
-======================
------BEGIN CERTIFICATE-----
-MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE
-BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
-aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
-cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3
-MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg
-SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv
-KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT
-FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs
-oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ
-1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc
-q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K
-aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p
-afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
-VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF
-AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE
-uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
-xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89
-jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH
-z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA==
------END CERTIFICATE-----
-
-VeriSign Class 3 Public Primary Certification Authority - G5
-============================================================
------BEGIN CERTIFICATE-----
-MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
-BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
-ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
-IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp
-ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB
-yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln
-biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh
-dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt
-YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz
-j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD
-Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/
-Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r
-fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/
-BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv
-Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
-aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
-SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+
-X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE
-KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC
-Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE
-ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
------END CERTIFICATE-----
-
 SecureTrust CA
 ==============
 -----BEGIN CERTIFICATE-----
@@ -854,29 +623,6 @@ FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA
 U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
 -----END CERTIFICATE-----
 
-OISTE WISeKey Global Root GA CA
-===============================
------BEGIN CERTIFICATE-----
-MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE
-BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG
-A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH
-bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD
-VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw
-IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5
-IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9
-Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg
-Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD
-d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ
-/yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R
-LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
-AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
-KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm
-MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4
-+vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa
-hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY
-okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0=
------END CERTIFICATE-----
-
 Certigna
 ========
 -----BEGIN CERTIFICATE-----
@@ -972,70 +718,6 @@ vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz
 TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD
 -----END CERTIFICATE-----
 
-GeoTrust Primary Certification Authority - G3
-=============================================
------BEGIN CERTIFICATE-----
-MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE
-BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0
-IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy
-eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz
-NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo
-YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT
-LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI
-hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j
-K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE
-c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C
-IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu
-dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC
-MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr
-2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9
-cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE
-Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
-AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s
-t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt
------END CERTIFICATE-----
-
-thawte Primary Root CA - G2
-===========================
------BEGIN CERTIFICATE-----
-MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC
-VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu
-IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg
-Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV
-MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG
-b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt
-IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS
-LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5
-8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU
-mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN
-G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K
-rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
------END CERTIFICATE-----
-
-thawte Primary Root CA - G3
-===========================
------BEGIN CERTIFICATE-----
-MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE
-BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
-aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
-cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w
-ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
-d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD
-VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG
-A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
-MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At
-P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC
-+BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY
-7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW
-vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E
-BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ
-KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK
-A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
-t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC
-8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm
-er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A=
------END CERTIFICATE-----
-
 GeoTrust Primary Certification Authority - G2
 =============================================
 -----BEGIN CERTIFICATE-----
@@ -1081,27 +763,6 @@ wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4
 mJO37M2CYfE45k+XmCpajQ==
 -----END CERTIFICATE-----
 
-VeriSign Class 3 Public Primary Certification Authority - G4
-============================================================
------BEGIN CERTIFICATE-----
-MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC
-VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3
-b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz
-ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj
-YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL
-MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU
-cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo
-b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5
-IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8
-Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz
-rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB
-/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw
-HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u
-Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD
-A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx
-AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
------END CERTIFICATE-----
-
 NetLock Arany (Class Gold) Főtanúsítvány
 ========================================
 -----BEGIN CERTIFICATE-----
@@ -1126,38 +787,6 @@ NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu
 dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
 -----END CERTIFICATE-----
 
-Staat der Nederlanden Root CA - G2
-==================================
------BEGIN CERTIFICATE-----
-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
-66+KAQ==
------END CERTIFICATE-----
-
 Hongkong Post Root CA 1
 =======================
 -----BEGIN CERTIFICATE-----
@@ -1789,30 +1418,6 @@ P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
 e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw==
 -----END CERTIFICATE-----
 
-EE Certification Centre Root CA
-===============================
------BEGIN CERTIFICATE-----
-MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG
-EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy
-dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw
-MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB
-UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy
-ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB
-DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM
-TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2
-rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw
-93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN
-P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T
-AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ
-MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF
-BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj
-xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM
-lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u
-uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU
-3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM
-dcGWxZ0=
------END CERTIFICATE-----
-
 D-TRUST Root Class 3 CA 2 2009
 ==============================
 -----BEGIN CERTIFICATE-----
@@ -2831,37 +2436,6 @@ MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1
 AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA==
 -----END CERTIFICATE-----
 
-LuxTrust Global Root 2
-======================
------BEGIN CERTIFICATE-----
-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
------END CERTIFICATE-----
-
 TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
 =============================================
 -----BEGIN CERTIFICATE-----
@@ -3464,3 +3038,191 @@ JOgc47OlIQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk5F6G
 +TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuYn/PIjhs4ViFqUZPT
 kcpG2om3PVODLAgfi49T3f+sHw==
 -----END CERTIFICATE-----
+
+Microsoft ECC Root Certificate Authority 2017
+=============================================
+-----BEGIN CERTIFICATE-----
+MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV
+UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQgRUND
+IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4
+MjMxNjA0WjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw
+NAYDVQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQ
+BgcqhkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZRogPZnZH6
+thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYbhGBKia/teQ87zvH2RPUB
+eMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIy5lycFIM
++Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlf
+Xu5gKcs68tvWMoQZP3zVL8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaR
+eNtUjGUBiudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M=
+-----END CERTIFICATE-----
+
+Microsoft RSA Root Certificate Authority 2017
+=============================================
+-----BEGIN CERTIFICATE-----
+MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBlMQswCQYDVQQG
+EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQg
+UlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIw
+NzE4MjMwMDIzWjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u
+MTYwNAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcw
+ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZNt9GkMml
+7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0ZdDMbRnMlfl7rEqUrQ7e
+S0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw7
+1VdyvD/IybLeS2v4I2wDwAW9lcfNcztmgGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+
+dkC0zVJhUXAoP8XFWvLJjEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49F
+yGcohJUcaDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaGYaRS
+MLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6W6IYZVcSn2i51BVr
+lMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4KUGsTuqwPN1q3ErWQgR5WrlcihtnJ
+0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH+FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJ
+ClTUFLkqqNfs+avNJVgyeY+QW5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYw
+DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC
+NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZCLgLNFgVZJ8og
+6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OCgMNPOsduET/m4xaRhPtthH80
+dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk
++ONVFT24bcMKpBLBaYVu32TxU5nhSnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex
+/2kskZGT4d9Mozd2TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDy
+AmH3pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGRxpl/j8nW
+ZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiAppGWSZI1b7rCoucL5mxAyE
+7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKT
+c0QWbej09+CVgI+WXTik9KveCjCHk9hNAHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D
+5KbvtwEwXlGjefVwaaZBRA+GsCyRxj3qrg+E
+-----END CERTIFICATE-----
+
+e-Szigno Root CA 2017
+=====================
+-----BEGIN CERTIFICATE-----
+MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNVBAYTAkhVMREw
+DwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUt
+MjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJvb3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZa
+Fw00MjA4MjIxMjA3MDZaMHExCzAJBgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UE
+CgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3pp
+Z25vIFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtvxie+RJCx
+s1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+HWyx7xf58etqjYzBhMA8G
+A1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSHERUI0arBeAyxr87GyZDv
+vzAEwDAfBgNVHSMEGDAWgBSHERUI0arBeAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEA
+tVfd14pVCzbhhkT61NlojbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxO
+svxyqltZ+efcMQ==
+-----END CERTIFICATE-----
+
+certSIGN Root CA G2
+===================
+-----BEGIN CERTIFICATE-----
+MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNVBAYTAlJPMRQw
+EgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjAeFw0xNzAy
+MDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJBgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lH
+TiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBAMDFdRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05
+N0IwvlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZuIt4Imfk
+abBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhpn+Sc8CnTXPnGFiWeI8Mg
+wT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKscpc/I1mbySKEwQdPzH/iV8oScLumZfNp
+dWO9lfsbl83kqK/20U6o2YpxJM02PbyWxPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91Qqh
+ngLjYl/rNUssuHLoPj1PrCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732
+jcZZroiFDsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fxDTvf
+95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgyLcsUDFDYg2WD7rlc
+z8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6CeWRgKRM+o/1Pcmqr4tTluCRVLERL
+iohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1Ud
+DgQWBBSCIS1mxteg4BXrzkwJd8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOB
+ywaK8SJJ6ejqkX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC
+b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQlqiCA2ClV9+BB
+/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0OJD7uNGzcgbJceaBxXntC6Z5
+8hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+cNywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5
+BiKDUyUM/FHE5r7iOZULJK2v0ZXkltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklW
+atKcsWMy5WHgUyIOpwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tU
+Sxfj03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZkPuXaTH4M
+NMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE1LlSVHJ7liXMvGnjSG4N
+0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MXQRBdJ3NghVdJIgc=
+-----END CERTIFICATE-----
+
+Trustwave Global Certification Authority
+========================================
+-----BEGIN CERTIFICATE-----
+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
+29FpHOTKyeC2nOnOcXHebD8WpHk=
+-----END CERTIFICATE-----
+
+Trustwave Global ECC P256 Certification Authority
+=================================================
+-----BEGIN CERTIFICATE-----
+MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYDVQQGEwJVUzER
+MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI
+b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYD
+VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy
+dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1
+NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH77bOYj
+43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoNFWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqm
+P62jQzBBMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt
+0UrrdaVKEJmzsaGLSvcwCgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjz
+RM4q3wghDDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7
+-----END CERTIFICATE-----
+
+Trustwave Global ECC P384 Certification Authority
+=================================================
+-----BEGIN CERTIFICATE-----
+MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYDVQQGEwJVUzER
+MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI
+b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYD
+VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy
+dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4
+NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuBBAAiA2IABGvaDXU1CDFH
+Ba5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJj9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr
+/TklZvFe/oyujUF5nQlgziip04pt89ZF1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNV
+HQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNn
+ADBkAjA3AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsCMGcl
+CrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVuSw==
+-----END CERTIFICATE-----
+
+NAVER Global Root Certification Authority
+=========================================
+-----BEGIN CERTIFICATE-----
+MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEMBQAwaTELMAkG
+A1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRGT1JNIENvcnAuMTIwMAYDVQQD
+DClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4
+NDJaFw0zNzA4MTgyMzU5NTlaMGkxCzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVT
+UyBQTEFURk9STSBDb3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVAiQqrDZBb
+UGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH38dq6SZeWYp34+hInDEW
++j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lEHoSTGEq0n+USZGnQJoViAbbJAh2+g1G7
+XNr4rRVqmfeSVPc0W+m/6imBEtRTkZazkVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2
+aacp+yPOiNgSnABIqKYPszuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4
+Yb8ObtoqvC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHfnZ3z
+VHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaGYQ5fG8Ir4ozVu53B
+A0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo0es+nPxdGoMuK8u180SdOqcXYZai
+cdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3aCJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejy
+YhbLgGvtPe31HzClrkvJE+2KAQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNV
+HQ4EFgQU0p+I36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB
+Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoNqo0hV4/GPnrK
+21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatjcu3cvuzHV+YwIHHW1xDBE1UB
+jCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm+LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bx
+hYTeodoS76TiEJd6eN4MUZeoIUCLhr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTg
+E34h5prCy8VCZLQelHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTH
+D8z7p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8piKCk5XQ
+A76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLRLBT/DShycpWbXgnbiUSY
+qqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oG
+I/hGoiLtk/bdmuYqh7GYVPEi92tF4+KOdh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmg
+kpzNNIaRkPpkUZ3+/uul9XXeifdy
+-----END CERTIFICATE-----
diff --git a/doc/conf/unrealircd.remote.conf b/doc/conf/unrealircd.remote.conf
@@ -14,8 +14,8 @@ alias os { target operserv; type services; }
 class clients { pingfreq 120; maxclients 100; sendq 1M; options { nofakelag; } }
 class servers { pingfreq 120; maxclients  10; sendq 1M; connfreq 30;           }
 
-allow { ip *;         class clients; maxperip 2;  }
-allow { ip 127.0.0.1; class clients; maxperip 10; }
+allow { ip *;         class clients; maxperip 2;  global-maxperip 2;  }
+allow { ip 127.0.0.1; class clients; maxperip 10; global-maxperip 10; }
 
 #require authentication {
 #	mask *@*;
diff --git a/extras/build-tests/windows/compilecmd/vs2019.bat b/extras/build-tests/windows/compilecmd/vs2019.bat
@@ -8,7 +8,7 @@ USE_REMOTEINC=1 ^
 LIBCURL_INC_DIR="c:\projects\unrealircd-5-libs\curl\include" ^
 LIBCURL_LIB_DIR="c:\projects\unrealircd-5-libs\curl\builds\libcurl-vc-x64-release-dll-ssl-dll-cares-dll-ipv6-obj-lib" ^
 CARES_LIB_DIR="c:\projects\unrealircd-5-libs\c-ares\msvc\cares\dll-release" ^
-CARES_INC_DIR="c:\projects\unrealircd-5-libs\c-ares" ^
+CARES_INC_DIR="c:\projects\unrealircd-5-libs\c-ares\include" ^
 CARESLIB="cares.lib" ^
 PCRE2_INC_DIR="c:\projects\unrealircd-5-libs\pcre2\include" ^
 PCRE2_LIB_DIR="c:\projects\unrealircd-5-libs\pcre2\lib" ^
diff --git a/extras/c-ares.tar.gz b/extras/c-ares.tar.gz
Binary files differ.
diff --git a/extras/curlinstall b/extras/curlinstall
@@ -4,7 +4,7 @@ OUTF="curl-latest.tar.gz"
 OUTD="curl-latest"
 ARESPATH="`pwd`/extras/c-ares"
 UNREALDIR="`pwd`"
-CARESVERSION="1.16.0"
+CARESVERSION="1.17.1"
 LIBDIR="$1"
 
 if [ "x$1" = "x" ]; then
diff --git a/extras/doxygen/Doxyfile b/extras/doxygen/Doxyfile
@@ -38,7 +38,7 @@ PROJECT_NAME           = "UnrealIRCd"
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 5.0.8
+PROJECT_NUMBER         = 5.0.9
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
diff --git a/extras/pcre2.tar.gz b/extras/pcre2.tar.gz
Binary files differ.
diff --git a/extras/unrealircd-upgrade-script.in b/extras/unrealircd-upgrade-script.in
@@ -0,0 +1,105 @@
+#!/bin/bash
+#
+# This is stage 1 of the UnrealIRCd upgrade script
+# It downloads stage 2 online, verifies the integrity, and then
+# passes control to it to proceed with the rest of the upgrade.
+#
+# This is a bash script, so it is less cross-platform than
+# the rest of UnrealIRCd. We also mostly assume Linux here.
+#
+
+BUILDDIR="@BUILDDIR@"
+SCRIPTDIR="@SCRIPTDIR@"
+DOCDIR="@DOCDIR@"
+TMPDIR="@TMPDIR@"
+
+function warn()
+{
+	echo
+	echo "WARNING: $*"
+	echo "This is for your information only. It is possible to continue."
+	echo "Press ENTER to continue, or CTRL+C to abort."
+	echo "If in doubt, see https://www.unrealircd.org/docs/FAQ#upgrade-verify-failed"
+	read xyz
+}
+
+function bigwarn()
+{
+	echo
+	echo "[!!!] WARNING: $*"
+	echo "Check https://www.unrealircd.org/docs/FAQ#upgrade-verify-failed !"
+	echo "Type 'IGNORE' in uppercase to continue if you think it is safe."
+	echo "Type anything else to abort."
+	read answer
+	if [ "$answer" != "IGNORE" ]; then
+		exit 1
+	fi
+}
+
+function fail()
+{
+	echo
+	echo "ERROR: $*"
+	echo "NOTE: Your existing UnrealIRCd is backed up to $BACKUPDIR"
+	echo "Perhaps check out the FAQ for common problems:"
+	echo "https://www.unrealircd.org/docs/FAQ#upgrade-failed"
+	echo "Otherwise, follow the manual upgrade procedure from"
+	echo "https://www.unrealircd.org/docs/Upgrading"
+	exit 1
+}
+
+if [ ! -d "$BUILDDIR" ]; then
+	echo "UnrealIRCd source not found at $BUILDDIR."
+	echo "Sorry, then it is not possible to know your existing settings and thus we cannot upgrade."
+	echo "Follow the manual upgrade procedure from https://www.unrealircd.org/docs/Upgrading"
+	exit 1
+fi
+
+if ! wget --help 1>/dev/null 2>&1; then
+	echo "The tool 'wget' is missing, which is used by this script."
+	echo "On Linux consider running 'sudo apt install wget' or 'sudo yum install wget'"
+	echo "and run this script again."
+	echo "Or, don't use this script and follow the manual upgrade procedure from"
+	echo "https://www.unrealircd.org/docs/Upgrading"
+	exit 1
+fi
+
+# Weird way to get version, but ok.
+cd "$BUILDDIR" || fail "Could not cd to builddir"
+UNREALVER="`./configure --version|head -n1|awk '{ print $3 }'`"
+cd .. || fail "Could not cd back"
+
+# Set and export all variables with settings
+export UNREALVER BUILDDIR SCRIPTDIR DOCDIR TMPDIR
+
+# Download the install script
+wget -O unrealircd-upgrade-script.stage2 "https://www.unrealircd.org/downloads/unrealircd-upgrade-script.stage2?from=$UNREALVER" || fail "Could not download online installer"
+wget -O unrealircd-upgrade-script.stage2.asc "https://www.unrealircd.org/downloads/unrealircd-upgrade-script.stage2.asc" || fail "Could not download online installer signature"
+
+# GPG verification - if available
+if gpg --version 1>/dev/null 2>&1; then
+	if [ -f "$DOCDIR/KEYS" ]; then
+		gpg --import "$DOCDIR/KEYS"
+		echo
+		if gpg --batch --exit-on-status-write-error --verify unrealircd-upgrade-script.stage2.asc unrealircd-upgrade-script.stage2; then
+			echo "GPG: Verification succeeded. Download is genuine."
+			export NOGPG=0
+		else
+			bigwarn "GPG/PGP verification failed. This could be a security issue."
+			export NOGPG=1
+		fi
+	else
+		warn "Unable to check download integrity with GPG/PGP. Missing $DOCDIR/KEYS file."
+		export NOGPG=1
+	fi
+else
+	echo "WARNING: The GnuPG (GPG/PGP) verification tool 'gpg' is not installed."
+	echo "Consider running 'sudo apt install gpg' or 'yum install gnupg2'"
+	echo "When 'gpg' is installed then the UnrealIRCd upgrade script can"
+	echo "verify the digital signature of the download file."
+	warn "Unable to check download integrity"
+	export NOGPG=1
+fi
+
+chmod +x unrealircd-upgrade-script.stage2
+./unrealircd-upgrade-script.stage2 $*
diff --git a/include/config.h b/include/config.h
@@ -162,11 +162,11 @@
       (defined(HAVE_POLL) || defined(HAVE_EPOLL) || defined(HAVE_KQUEUE))
   /* Have poll/epoll/kqueue and either no --with-maxconnections or
    * --with-maxconnections=0, either of which indicates 'automatic' mode.
-   * At the time of writing we will try a limit of 8192.
+   * At the time of writing we will try a limit of 16384.
    * It will automatically be lowered at boottime if we can only use
    * 4096, 2048 or 1024. No problem.
    */
-  #define MAXCONNECTIONS 8192
+  #define MAXCONNECTIONS 16384
  #elif defined(MAXCONNECTIONS_REQUEST) && (MAXCONNECTIONS_REQUEST >= 1)
   /* --with-maxconnections=something */
   #define MAXCONNECTIONS MAXCONNECTIONS_REQUEST
diff --git a/include/dynconf.h b/include/dynconf.h
@@ -113,8 +113,9 @@ struct Configuration {
 	char *restrict_channelmodes;
 	char *restrict_extendedbans;
 	char *channel_command_prefix;
-	long unknown_flood_bantime;
-	long unknown_flood_amount;
+	long handshake_data_flood_amount;
+	long handshake_data_flood_ban_time;
+	int handshake_data_flood_ban_action;
 	struct ChMode modes_on_join;
 	int level_on_join;
 	unsigned char away_count;
@@ -230,8 +231,6 @@ extern MODVAR int ipv6_disabled;
 #define THROTTLING_PERIOD		iConf.throttle_period
 #define THROTTLING_COUNT		iConf.throttle_count
 #define USE_BAN_VERSION			iConf.use_ban_version
-#define UNKNOWN_FLOOD_BANTIME		iConf.unknown_flood_bantime
-#define UNKNOWN_FLOOD_AMOUNT		iConf.unknown_flood_amount
 #define MODES_ON_JOIN			iConf.modes_on_join.mode
 #define LEVEL_ON_JOIN			iConf.level_on_join
 
@@ -326,8 +325,9 @@ struct SetCheck {
 	unsigned has_restrict_channelmodes:1;
 	unsigned has_restrict_extendedbans:1;
 	unsigned has_channel_command_prefix:1;
-	unsigned has_anti_flood_unknown_flood_bantime:1;
-	unsigned has_anti_flood_unknown_flood_amount:1;
+	unsigned has_anti_flood_handshake_data_flood_amount:1;
+	unsigned has_anti_flood_handshake_data_flood_ban_action:1;
+	unsigned has_anti_flood_handshake_data_flood_ban_time:1;
 	unsigned has_modes_on_join:1;
 	unsigned has_level_on_join:1;
 	unsigned has_anti_flood_away_count:1;
diff --git a/include/fdlist.h b/include/fdlist.h
@@ -32,18 +32,6 @@ extern int fd_fileopen(const char *path, unsigned int flags);
 #define FD_SELECT_READ		0x1
 #define FD_SELECT_WRITE		0x2
 
-/* Socket buffer sizes for clients and servers
- * Note that these have been carefully chosen so you shouldn't touch these.
- * If you make these much higher then be aware that this means you loose
- * send queue / receive queue protection, otherwise known as "Excess flood"
- * and "SendQ Exceeded", since these queues are ON TOP of UnrealIRCd's
- * own queueing mechanism, it uses the OS TCP Socket queue.
- */
-#define USER_SOCKET_RECEIVE_BUFFER	8192
-#define USER_SOCKET_SEND_BUFFER		32768
-#define SERVER_SOCKET_RECEIVE_BUFFER	131072
-#define SERVER_SOCKET_SEND_BUFFER	131072
-
 extern void fd_setselect(int fd, int flags, IOCallbackFunc iocb, void *data);
 extern void fd_select(time_t delay);		/* backend-specific */
 extern void fd_refresh(int fd);			/* backend-specific */
diff --git a/include/h.h b/include/h.h
@@ -113,7 +113,6 @@ extern void config_error_empty(const char *filename, int line, const char *block
 extern void config_warn_duplicate(const char *filename, int line, const char *entry);
 extern int config_is_blankorempty(ConfigEntry *cep, const char *block);
 extern MODVAR int config_verbose;
-extern void config_progress(FORMAT_STRING(const char *format), ...) __attribute__((format(printf,1,2)));
 extern void config_entry_free(ConfigEntry *ce);
 extern void config_entry_free_all(ConfigEntry *ce);
 extern ConfigFile *config_load(char *filename, char *displayname);
@@ -886,7 +885,6 @@ extern CMD_FUNC(cmd_rehash);
 extern CMD_FUNC(cmd_die);
 extern CMD_FUNC(cmd_restart);
 extern void cmd_alias(Client *client, MessageTag *recv_mtags, int parc, char *parv[], char *cmd); /* special! */
-extern void ban_flooder(Client *cptr);
 extern char *pcre2_version(void);
 extern int get_terminal_width(void);
 extern int has_common_channels(Client *c1, Client *c2);
@@ -1000,3 +998,9 @@ extern void free_security_group(SecurityGroup *s);
 extern void set_security_group_defaults(void);
 extern int user_allowed_by_security_group(Client *client, SecurityGroup *s);
 extern int user_allowed_by_security_group_name(Client *client, char *secgroupname);
+extern void add_nvplist(NameValuePrioList **lst, int priority, char *name, char *value);
+extern void add_fmt_nvplist(NameValuePrioList **lst, int priority, char *name, FORMAT_STRING(const char *format), ...) __attribute__((format(printf,4,5)));
+extern NameValuePrioList *find_nvplist(NameValuePrioList *list, char *name);
+extern void free_nvplist(NameValuePrioList *lst);
+extern char *get_connect_extinfo(Client *client);
+extern char *unreal_strftime(char *str);
diff --git a/include/modules.h b/include/modules.h
@@ -1124,12 +1124,12 @@ extern void SavePersistentLongX(ModuleInfo *modinfo, char *varshortname, long va
 #define HOOKTYPE_ACCOUNT_LOGIN	102
 /** See hooktype_close_connection() */
 #define HOOKTYPE_CLOSE_CONNECTION	103
-
+/** See hooktype_connect_extinfo() */
+#define HOOKTYPE_CONNECT_EXTINFO	104
 /* Adding a new hook here?
  * 1) Add the #define HOOKTYPE_.... with a new number
  * 2) Add a hook prototype (see below)
  * 3) Add type checking (even more below)
- * 4) Document the hook at https://www.unrealircd.org/docs/Dev:Hook_API
  */
 
 /* Hook prototypes */
@@ -2056,6 +2056,15 @@ int hooktype_account_login(Client *client, MessageTag *mtags);
  */
 int hooktype_close_connection(Client *client);
 
+/** Called when a user connects to add extra information (function prototype for HOOKTYPE_CONNECT_EXTINFO).
+ * If you want to use this, then use the nvplist_add() or nvplist_add_fmt() function
+ * to add the information to the list. See also get_connect_extinfo() for inspiration.
+ * @param client		The client
+ * @param list			The name/value/prio list that you can add information to
+ * @return The return value is ignored (use return 0)
+ */
+int hooktype_connect_extinfo(Client *client, NameValuePrioList **list);
+
 /** @} */
 
 #ifdef GCC_TYPECHECKING
@@ -2164,7 +2173,8 @@ _UNREAL_ERROR(_hook_error_incompatible, "Incompatible hook function. Check argum
         ((hooktype == HOOKTYPE_IDENT_LOOKUP) && !ValidateHook(hooktype_ident_lookup, func)) || \
         ((hooktype == HOOKTYPE_CONFIGRUN_EX) && !ValidateHook(hooktype_configrun_ex, func)) || \
         ((hooktype == HOOKTYPE_ACCOUNT_LOGIN) && !ValidateHook(hooktype_account_login, func)) || \
-        ((hooktype == HOOKTYPE_CLOSE_CONNECTION) && !ValidateHook(hooktype_close_connection, func)) ) \
+        ((hooktype == HOOKTYPE_CLOSE_CONNECTION) && !ValidateHook(hooktype_close_connection, func)) || \
+        ((hooktype == HOOKTYPE_CONNECT_EXTINFO) && !ValidateHook(hooktype_connect_extinfo, func)) ) \
         _hook_error_incompatible();
 #endif /* GCC_TYPECHECKING */
 
diff --git a/include/struct.h b/include/struct.h
@@ -321,6 +321,7 @@ typedef enum ClientStatus {
 #define CLIENT_FLAG_DCCBLOCK		0x04000000	/**< Block all DCC send requests */
 #define CLIENT_FLAG_MAP			0x08000000	/**< Show this entry in /MAP (only used in map module) */
 #define CLIENT_FLAG_PINGWARN		0x10000000	/**< Server ping warning (remote server slow with responding to PINGs) */
+#define CLIENT_FLAG_NOHANDSHAKEDELAY	0x20000000	/**< No handshake delay */
 /** @} */
 
 #define SNO_DEFOPER "+kscfvGqobS"
@@ -421,6 +422,7 @@ typedef enum ClientStatus {
 #define IsOutgoing(x)			((x)->flags & CLIENT_FLAG_OUTGOING)
 #define IsPingSent(x)			((x)->flags & CLIENT_FLAG_PINGSENT)
 #define IsPingWarning(x)		((x)->flags & CLIENT_FLAG_PINGWARN)
+#define IsNoHandshakeDelay(x)		((x)->flags & CLIENT_FLAG_NOHANDSHAKEDELAY)
 #define IsProtoctlReceived(x)		((x)->flags & CLIENT_FLAG_PROTOCTL)
 #define IsQuarantined(x)		((x)->flags & CLIENT_FLAG_QUARANTINE)
 #define IsShunned(x)			((x)->flags & CLIENT_FLAG_SHUNNED)
@@ -451,6 +453,7 @@ typedef enum ClientStatus {
 #define SetOutgoing(x)			do { (x)->flags |= CLIENT_FLAG_OUTGOING; } while(0)
 #define SetPingSent(x)			do { (x)->flags |= CLIENT_FLAG_PINGSENT; } while(0)
 #define SetPingWarning(x)		do { (x)->flags |= CLIENT_FLAG_PINGWARN; } while(0)
+#define SetNoHandshakeDelay(x)		do { (x)->flags |= CLIENT_FLAG_NOHANDSHAKEDELAY; } while(0)
 #define SetProtoctlReceived(x)		do { (x)->flags |= CLIENT_FLAG_PROTOCTL; } while(0)
 #define SetQuarantined(x)		do { (x)->flags |= CLIENT_FLAG_QUARANTINE; } while(0)
 #define SetShunned(x)			do { (x)->flags |= CLIENT_FLAG_SHUNNED; } while(0)
@@ -480,6 +483,7 @@ typedef enum ClientStatus {
 #define ClearOutgoing(x)		do { (x)->flags &= ~CLIENT_FLAG_OUTGOING; } while(0)
 #define ClearPingSent(x)		do { (x)->flags &= ~CLIENT_FLAG_PINGSENT; } while(0)
 #define ClearPingWarning(x)		do { (x)->flags &= ~CLIENT_FLAG_PINGWARN; } while(0)
+#define ClearNoHandshakeDelay(x)	do { (x)->flags &= ~CLIENT_FLAG_NOHANDSHAKEDELAY; } while(0)
 #define ClearProtoctlReceived(x)	do { (x)->flags &= ~CLIENT_FLAG_PROTOCTL; } while(0)
 #define ClearQuarantined(x)		do { (x)->flags &= ~CLIENT_FLAG_QUARANTINE; } while(0)
 #define ClearShunned(x)			do { (x)->flags &= ~CLIENT_FLAG_SHUNNED; } while(0)
@@ -876,7 +880,7 @@ typedef void (*OverrideCmdFunc)(CommandOverride *ovr, Client *client, MessageTag
 #define TKL_BLACKLIST		0x0001000
 #define TKL_CONNECT_FLOOD	0x0002000
 #define TKL_MAXPERIP		0x0004000
-#define TKL_UNKNOWN_DATA_FLOOD	0x0008000
+#define TKL_HANDSHAKE_DATA_FLOOD	0x0008000
 #define TKL_ANTIRANDOM          0x0010000
 #define TKL_ANTIMIXEDUTF8       0x0020000
 #define TKL_BAN_VERSION         0x0040000
@@ -1014,6 +1018,21 @@ struct IRCCounts {
 /** The /LUSERS stats information */
 extern MODVAR IRCCounts irccounts;
 
+typedef struct NameValueList NameValueList;
+struct NameValueList {
+	NameValueList *prev, *next;
+	char *name;
+	char *value;
+};
+
+typedef struct NameValuePrioList NameValuePrioList;
+struct NameValuePrioList {
+	NameValuePrioList *prev, *next;
+	int priority;
+	char *name;
+	char *value;
+};
+
 #include "modules.h"
 
 /** A "real" command (internal interface, not for modules) */
@@ -1176,7 +1195,7 @@ struct User {
 	Link *invited;			/**< Channels has the user been invited to (linked list) */
 	Link *dccallow;			/**< DCCALLOW list (linked list) */
 	char *away;			/**< AWAY message, or NULL if not away */
-	char svid[SVIDLEN + 1];		/**< Unique value assigned by services (SVID) */
+	char svid[SVIDLEN + 1];		/**< Services account name or ID (SVID) */
 	unsigned short joined;		/**< Number of channels joined */
 	char username[USERLEN + 1];	/**< Username, the user portion in nick!user@host. */
 	char realhost[HOSTLEN + 1];	/**< Realhost, the real host of the user (IP or hostname) - usually this is not shown to other users */
@@ -1230,13 +1249,6 @@ struct MessageTag {
 	char *value;
 };
 
-typedef struct NameValueList NameValueList;
-struct NameValueList {
-	NameValueList *prev, *next;
-	char *name;
-	char *value;
-};
-
 /* conf preprocessor */
 typedef enum PreprocessorItem {
 	PREPROCESSOR_ERROR		= 0,
@@ -1387,15 +1399,19 @@ struct ConfigFlag_allow {
 	unsigned	reject_on_auth_failure :1;
 };
 
+/** allow { } block settings */
 struct ConfigItem_allow {
-	ConfigItem_allow	*prev, *next;
-	ConfigFlag			flag;
-	char				*ip, *hostname, *server;
-	AuthConfig		*auth;	
-	unsigned short		maxperip;
-	int					port;
-	ConfigItem_class	*class;
-	ConfigFlag_allow	flags;
+	ConfigItem_allow *prev, *next;
+	ConfigFlag flag;
+	char *ip;
+	char *hostname;
+	char *server;
+	AuthConfig *auth;
+	int maxperip; /**< Maximum connections permitted per IP address (locally) */
+	int global_maxperip; /**< Maximum connections permitted per IP address (globally) */
+	int port;
+	ConfigItem_class *class;
+	ConfigFlag_allow flags;
 	unsigned short ipv6_clone_mask;
 };
 
@@ -1630,7 +1646,8 @@ struct ConfigItem_allow_dcc {
 struct ConfigItem_log {
 	ConfigItem_log *prev, *next;
 	ConfigFlag flag;
-	char *file;
+	char *file; /**< Filename to log to (either generated or specified) */
+	char *filefmt; /**< Filename with dynamic % stuff */
 	long maxsize;
 	int  flags;
 	int  logfd;
diff --git a/include/windows/setup.h b/include/windows/setup.h
@@ -63,7 +63,7 @@
 #define UNREAL_VERSION_MAJOR 0
 
 /* Minor version number (e.g.: 1 for Unreal3.2.1) */
-#define UNREAL_VERSION_MINOR 8
+#define UNREAL_VERSION_MINOR 9
 
 /* Version suffix such as a beta marker or release candidate marker. (e.g.:
    -rcX for unrealircd-3.2.9-rcX) */
diff --git a/src/conf.c b/src/conf.c
@@ -1374,10 +1374,6 @@ void config_error(FORMAT_STRING(const char *format), ...)
 	va_end(ap);
 	if ((ptr = strchr(buffer, '\n')) != NULL)
 		*ptr = '\0';
-#ifdef _WIN32
-	if (!loop.ircd_booted)
-		win_log("[error] %s", buffer);
-#endif
 	ircd_log(LOG_ERROR, "config error: %s", buffer);
 	sendto_realops("error: %s", buffer);
 	if (remote_rehash_client)
@@ -1437,10 +1433,6 @@ void config_status(FORMAT_STRING(const char *format), ...)
 	va_end(ap);
 	if ((ptr = strchr(buffer, '\n')) != NULL)
 		*ptr = '\0';
-#ifdef _WIN32
-	if (!loop.ircd_booted)
-		win_log("* %s", buffer);
-#endif
 	ircd_log(LOG_ERROR, "%s", buffer);
 	sendto_realops("%s", buffer);
 	if (remote_rehash_client)
@@ -1458,10 +1450,6 @@ void config_warn(FORMAT_STRING(const char *format), ...)
 	va_end(ap);
 	if ((ptr = strchr(buffer, '\n')) != NULL)
 		*ptr = '\0';
-#ifdef _WIN32
-	if (!loop.ircd_booted)
-		win_log("[warning] %s", buffer);
-#endif
 	ircd_log(LOG_ERROR, "[warning] %s", buffer);
 	sendto_realops("[warning] %s", buffer);
 	if (remote_rehash_client)
@@ -1556,24 +1544,6 @@ int config_test_openfile(ConfigEntry *cep, int flags, mode_t mode, const char *e
 	return 0;
 }
 
-void config_progress(FORMAT_STRING(const char *format), ...)
-{
-	va_list		ap;
-	char		buffer[1024];
-	char		*ptr;
-
-	va_start(ap, format);
-	vsnprintf(buffer, 1023, format, ap);
-	va_end(ap);
-	if ((ptr = strchr(buffer, '\n')) != NULL)
-		*ptr = '\0';
-#ifdef _WIN32
-	if (!loop.ircd_booted)
-		win_log("* %s", buffer);
-#endif
-	sendto_realops("%s", buffer);
-}
-
 int config_is_blankorempty(ConfigEntry *cep, const char *block)
 {
 	if (!cep->ce_vardata)
@@ -1655,8 +1625,9 @@ void config_setdefaultsettings(Configuration *i)
 {
 	char tmp[512];
 
-	i->unknown_flood_amount = 4;
-	i->unknown_flood_bantime = 600;
+	i->handshake_data_flood_amount = 4096;
+	i->handshake_data_flood_ban_action = BAN_ACT_ZLINE;
+	i->handshake_data_flood_ban_time = 600;
 	safe_strdup(i->oper_snomask, SNO_DEFOPER);
 	i->ident_read_timeout = 7;
 	i->ident_connect_timeout = 3;
@@ -5333,6 +5304,8 @@ int	_conf_allow(ConfigFile *conf, ConfigEntry *ce)
 		}
 		else if (!strcmp(cep->ce_varname, "maxperip"))
 			allow->maxperip = atoi(cep->ce_vardata);
+		else if (!strcmp(cep->ce_varname, "global-maxperip"))
+			allow->global_maxperip = atoi(cep->ce_vardata);
 		else if (!strcmp(cep->ce_varname, "redirect-server"))
 			safe_strdup(allow->server, cep->ce_vardata);
 		else if (!strcmp(cep->ce_varname, "redirect-port"))
@@ -5368,6 +5341,14 @@ int	_conf_allow(ConfigFile *conf, ConfigEntry *ce)
 	if (!allow->ip)
 		safe_strdup(allow->ip, "*@NOMATCH");
 
+	/* Default: global-maxperip = maxperip+1 */
+	if (allow->global_maxperip == 0)
+		allow->global_maxperip = allow->maxperip+1;
+
+	/* global-maxperip < maxperip makes no sense */
+	if (allow->global_maxperip < allow->maxperip)
+		allow->global_maxperip = allow->maxperip;
+
 	AddListItem(allow, conf_allow);
 	return 1;
 }
@@ -5377,7 +5358,7 @@ int	_test_allow(ConfigFile *conf, ConfigEntry *ce)
 	ConfigEntry *cep, *cepp;
 	int		errors = 0;
 	Hook *h;
-	char has_ip = 0, has_hostname = 0, has_maxperip = 0, has_password = 0, has_class = 0;
+	char has_ip = 0, has_hostname = 0, has_maxperip = 0, has_global_maxperip = 0, has_password = 0, has_class = 0;
 	char has_redirectserver = 0, has_redirectport = 0, has_options = 0;
 	int hostname_possible_silliness = 0;
 
@@ -5450,9 +5431,26 @@ int	_test_allow(ConfigFile *conf, ConfigEntry *ce)
 				continue;
 			}
 			has_maxperip = 1;
-			if ((v <= 0) || (v > 65535))
+			if ((v <= 0) || (v > 1000000))
 			{
-				config_error("%s:%i: allow::maxperip with illegal value (must be 1-65535)",
+				config_error("%s:%i: allow::maxperip with illegal value (must be 1-1000000)",
+					cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
+				errors++;
+			}
+		}
+		else if (!strcmp(cep->ce_varname, "global-maxperip"))
+		{
+			int v = atoi(cep->ce_vardata);
+			if (has_global_maxperip)
+			{
+				config_warn_duplicate(cep->ce_fileptr->cf_filename,
+					cep->ce_varlinenum, "allow::global-maxperip");
+				continue;
+			}
+			has_global_maxperip = 1;
+			if ((v <= 0) || (v > 1000000))
+			{
+				config_error("%s:%i: allow::global-maxperip with illegal value (must be 1-1000000)",
 					cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
 				errors++;
 			}
@@ -6096,7 +6094,10 @@ int     _conf_log(ConfigFile *conf, ConfigEntry *ce)
 
 	ca = safe_alloc(sizeof(ConfigItem_log));
 	ca->logfd = -1;
-	safe_strdup(ca->file, ce->ce_vardata);
+	if (strchr(ce->ce_vardata, '%'))
+		safe_strdup(ca->filefmt, ce->ce_vardata);
+	else
+		safe_strdup(ca->file, ce->ce_vardata);
 
 	for (cep = ce->ce_entries; cep; cep = cep->ce_next)
 	{
@@ -6122,6 +6123,7 @@ int _test_log(ConfigFile *conf, ConfigEntry *ce) {
 	int fd, errors = 0;
 	ConfigEntry *cep, *cepp;
 	char has_flags = 0, has_maxsize = 0;
+	char *fname;
 
 	if (!ce->ce_vardata)
 	{
@@ -6192,21 +6194,25 @@ int _test_log(ConfigFile *conf, ConfigEntry *ce) {
 			continue;
 		}
 	}
+
 	if (!has_flags)
 	{
 		config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
 			"log::flags");
 		errors++;
 	}
-	if ((fd = fd_fileopen(ce->ce_vardata, O_WRONLY|O_CREAT)) == -1)
+
+	fname = unreal_strftime(ce->ce_vardata);
+	if ((fd = fd_fileopen(fname, O_WRONLY|O_CREAT)) == -1)
 	{
 		config_error("%s:%i: Couldn't open logfile (%s) for writing: %s",
 			ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
-			ce->ce_vardata, strerror(errno));
+			fname, strerror(errno));
 		errors++;
-	}
-	else
+	} else
+	{
 		fd_close(fd);
+	}
 
 	return errors;
 }
@@ -6622,7 +6628,7 @@ int     _conf_ban(ConfigFile *conf, ConfigEntry *ce)
 		else if (!strcmp(cep->ce_varname, "reason"))
 			safe_strdup(ca->reason, cep->ce_vardata);
 		else if (!strcmp(cep->ce_varname, "action"))
-			ca ->action = banact_stringtoval(cep->ce_vardata);
+			ca->action = banact_stringtoval(cep->ce_vardata);
 	}
 	AddListItem(ca, conf_ban);
 	return 0;
@@ -7498,11 +7504,20 @@ int	_conf_set(ConfigFile *conf, ConfigEntry *ce)
 			}
 		}
 		else if (!strcmp(cep->ce_varname, "anti-flood")) {
-			for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next) {
-				if (!strcmp(cepp->ce_varname, "unknown-flood-bantime"))
-					tempiConf.unknown_flood_bantime = config_checkval(cepp->ce_vardata,CFG_TIME);
-				else if (!strcmp(cepp->ce_varname, "unknown-flood-amount"))
-					tempiConf.unknown_flood_amount = atol(cepp->ce_vardata);
+			for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+			{
+				if (!strcmp(cepp->ce_varname, "handshake-data-flood"))
+				{
+					for (ceppp = cepp->ce_entries; ceppp; ceppp = ceppp->ce_next)
+					{
+						if (!strcmp(ceppp->ce_varname, "amount"))
+							tempiConf.handshake_data_flood_amount = config_checkval(ceppp->ce_vardata, CFG_SIZE);
+						else if (!strcmp(ceppp->ce_varname, "ban-time"))
+							tempiConf.handshake_data_flood_ban_time = config_checkval(ceppp->ce_vardata, CFG_TIME);
+						else if (!strcmp(ceppp->ce_varname, "ban-action"))
+							tempiConf.handshake_data_flood_ban_action = banact_stringtoval(ceppp->ce_vardata);
+					}
+				}
 				else if (!strcmp(cepp->ce_varname, "away-count"))
 					tempiConf.away_count = atol(cepp->ce_vardata);
 				else if (!strcmp(cepp->ce_varname, "away-period"))
@@ -8321,8 +8336,10 @@ int	_test_set(ConfigFile *conf, ConfigEntry *ce)
 			need_34_upgrade = 1;
 			continue;
 		}
-		else if (!strcmp(cep->ce_varname, "anti-flood")) {
-			for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next) {
+		else if (!strcmp(cep->ce_varname, "anti-flood"))
+		{
+			for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
+			{
 				if (!strcmp(cepp->ce_varname, "max-concurrent-conversations"))
 				{
 					for (ceppp = cepp->ce_entries; ceppp; ceppp = ceppp->ce_next)
@@ -8359,15 +8376,56 @@ int	_test_set(ConfigFile *conf, ConfigEntry *ce)
 					}
 					continue; /* required here, due to checknull directly below */
 				}
-				if (!strcmp(cepp->ce_varname, "unknown-flood-bantime"))
+				else if (!strcmp(cepp->ce_varname, "unknown-flood-amount") ||
+				         !strcmp(cepp->ce_varname, "unknown-flood-bantime"))
 				{
-					CheckNull(cepp);
-					CheckDuplicate(cepp, anti_flood_unknown_flood_bantime, "anti-flood::unknown-flood-bantime");
+					config_error("%s:%i: set::anti-flood::%s: this setting has been moved. "
+					             "See https://www.unrealircd.org/docs/Set_block#set::anti-flood::handshake-data-flood",
+					             cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum, cepp->ce_varname);
+					errors++;
+					continue;
 				}
-				else if (!strcmp(cepp->ce_varname, "unknown-flood-amount"))
+				else if (!strcmp(cepp->ce_varname, "handshake-data-flood"))
 				{
-					CheckNull(cepp);
-					CheckDuplicate(cepp, anti_flood_unknown_flood_amount, "anti-flood::unknown-flood-amount");
+					for (ceppp = cepp->ce_entries; ceppp; ceppp = ceppp->ce_next)
+					{
+						if (!strcmp(ceppp->ce_varname, "amount"))
+						{
+							long v;
+							CheckNull(ceppp);
+							CheckDuplicate(ceppp, anti_flood_handshake_data_flood_amount, "anti-flood::handshake-data-flood::amount");
+							v = config_checkval(ceppp->ce_vardata, CFG_SIZE);
+							if (v < 1024)
+							{
+								config_error("%s:%i: set::anti-flood::handshake-data-flood::amount must be at least 1024 bytes",
+									ceppp->ce_fileptr->cf_filename, ceppp->ce_varlinenum);
+								errors++;
+							}
+						} else
+						if (!strcmp(ceppp->ce_varname, "ban-action"))
+						{
+							CheckNull(ceppp);
+							CheckDuplicate(ceppp, anti_flood_handshake_data_flood_ban_action, "anti-flood::handshake-data-flood::ban-action");
+							if (!banact_stringtoval(ceppp->ce_vardata))
+							{
+								config_error("%s:%i: set::anti-flood::handshake-data-flood::ban-action has unknown action type '%s'",
+									ceppp->ce_fileptr->cf_filename, ceppp->ce_varlinenum,
+									ceppp->ce_vardata);
+								errors++;
+							}
+						} else
+						if (!strcmp(ceppp->ce_varname, "ban-time"))
+						{
+							CheckNull(ceppp);
+							CheckDuplicate(ceppp, anti_flood_handshake_data_flood_ban_time, "anti-flood::handshake-data-flood::ban-time");
+						} else
+						{
+							config_error_unknownopt(ceppp->ce_fileptr->cf_filename,
+								ceppp->ce_varlinenum, "set::anti-flood::handshake-data-flood",
+								ceppp->ce_varname);
+							errors++;
+						}
+					}
 				}
 				else if (!strcmp(cepp->ce_varname, "away-count"))
 				{
diff --git a/src/crashreport.c b/src/crashreport.c
@@ -292,7 +292,7 @@ int crash_report_asan_log(FILE *reportfd, char *coredump)
 	coretime = get_file_time(coredump);
 	asantime = get_file_time(asan_log);
 
-	fprintf(reportfd, "ASan log file found '%s' which is %ld newer than core file\n",
+	fprintf(reportfd, "ASan log file found '%s' which is %ld seconds older than core file\n",
 		asan_log,
 		(long)((long)(coretime) - (long)asantime));
 
@@ -719,6 +719,15 @@ void mark_coredump_as_read(char *coredump)
 
 static int report_pref = REPORT_ASK;
 
+void report_crash_not_sent(char *fname)
+{
+		printf("Crash report will not be sent to UnrealIRCd Team.\n"
+		       "\n"
+		       "Feel free to read the report at %s and delete it.\n"
+		       "Or, if you change your mind, you can submit it anyway at https://bugs.unrealircd.org/\n"
+		       " (if you do, please set the option 'View Status' at the end of the bug report page to 'private'!!)\n", fname);
+}
+
 void report_crash(void)
 {
 	char *coredump, *fname;
@@ -761,8 +770,8 @@ void report_crash(void)
 		
 	if (report_pref == REPORT_NEVER)
 	{
-		printf("Crash report will not be sent to UnrealIRCd Team.\n\n");
-		printf("Feel free to read the report at %s and if you change your mind you can submit it anyway at https://bugs.unrealircd.org/\n", fname);
+		report_crash_not_sent(fname);
+		return;
 	} else
 	if (report_pref == REPORT_ASK)
 	{
@@ -780,8 +789,7 @@ void report_crash(void)
 			
 			if (answer && (toupper(*answer) == 'N'))
 			{
-				printf("Ok, not sending bug report.\n\n");
-				printf("Feel free to read the report at %s and if you change your mind you can submit it anyway at https://bugs.unrealircd.org/\n", fname);
+				report_crash_not_sent(fname);
 				return;
 			}
 			if (answer && (toupper(*answer) == 'Y'))
diff --git a/src/ircd.c b/src/ircd.c
@@ -1120,6 +1120,19 @@ int InitUnrealIRCd(int argc, char *argv[])
 			  generate_cloakkeys();
 			  exit(0);
 #endif
+		  case 'K':
+			  {
+			  	char *p = NULL;
+			  	if (chdir(TMPDIR) < 0)
+			  	{
+			  		fprintf(stderr, "Could not change to directory '%s'\n", TMPDIR);
+			  		exit(1);
+			  	}
+			  	fprintf(stderr, "Starting crash test!\n");
+			  	*p = 'a';
+			  	fprintf(stderr, "It is impossible to get here\n");
+			  	exit(0);
+			  }
 		  case 'U':
 		      if (chdir(CONFDIR) < 0)
 	{
diff --git a/src/list.c b/src/list.c
@@ -244,11 +244,6 @@ Server *make_server(Client *client)
 		del_from_id_hash_table(client->id, client);
 		*client->id = '\0';
 	}
-	if (MyConnect(client) && (client->local->fd >= 0))
-	{
-		/* Give servers a large socket buffer for performance */
-		set_socket_buffers(client->local->fd, SERVER_SOCKET_RECEIVE_BUFFER, SERVER_SOCKET_SEND_BUFFER);
-	}
 	return client->serv;
 }
 
@@ -550,7 +545,7 @@ NameList *find_name_list(NameList *list, char *name)
 	return NULL;
 }
 
-/** Find an entry in a NameList by running match_simpl() on it.
+/** Find an entry in a NameList by running match_simple() on it.
  * @ingroup ListFunctions
  */
 NameList *find_name_list_match(NameList *list, char *name)
@@ -567,3 +562,52 @@ NameList *find_name_list_match(NameList *list, char *name)
 	return NULL;
 }
 
+void add_nvplist(NameValuePrioList **lst, int priority, char *name, char *value)
+{
+	va_list vl;
+	NameValuePrioList *e = safe_alloc(sizeof(NameValuePrioList));
+	safe_strdup(e->name, name);
+	if (value && *value)
+		safe_strdup(e->value, value);
+	AddListItemPrio(e, *lst, priority);
+}
+
+NameValuePrioList *find_nvplist(NameValuePrioList *list, char *name)
+{
+	NameValuePrioList *e;
+
+	for (e = list; e; e = e->next)
+	{
+		if (!strcasecmp(e->name, name))
+		{
+			return e;
+		}
+	}
+	return NULL;
+}
+
+void add_fmt_nvplist(NameValuePrioList **lst, int priority, char *name, FORMAT_STRING(const char *format), ...)
+{
+	char value[512];
+	va_list vl;
+	*value = '\0';
+	if (format)
+	{
+		va_start(vl, format);
+		vsnprintf(value, sizeof(value), format, vl);
+		va_end(vl);
+	}
+	add_nvplist(lst, priority, name, value);
+}
+
+void free_nvplist(NameValuePrioList *lst)
+{
+	NameValuePrioList *e, *e_next;
+	for (e = lst; e; e = e_next)
+	{
+		e_next = e->next;
+		safe_free(e->name);
+		safe_free(e->value);
+		safe_free(e);
+	}
+}
diff --git a/src/misc.c b/src/misc.c
@@ -137,7 +137,13 @@ void ircd_log(int flags, FORMAT_STRING(const char *format), ...)
 	strlcat(buf, "\n", sizeof(buf));
 
 	if (!loop.ircd_forked && (flags & LOG_ERROR))
+	{
+#ifdef _WIN32
+		win_log("* %s", buf);
+#else
 		fprintf(stderr, "%s", buf);
+#endif
+	}
 
 	/* In case of './unrealircd configtest': don't write to log file, only to stderr */
 	if (loop.config_test)
@@ -146,83 +152,66 @@ void ircd_log(int flags, FORMAT_STRING(const char *format), ...)
 		return;
 	}
 
-	for (logs = conf_log; logs; logs = logs->next) {
+	for (logs = conf_log; logs; logs = logs->next)
+	{
+		if (!(logs->flags & flags))
+			continue;
+
 #ifdef HAVE_SYSLOG
-		if (!strcasecmp(logs->file, "syslog") && logs->flags & flags) {
+		if (logs->file && !strcasecmp(logs->file, "syslog"))
+		{
 			syslog(LOG_INFO, "%s", buf);
 			written++;
 			continue;
 		}
 #endif
-		if (logs->flags & flags)
+
+		/* This deals with dynamic log file names, such as ircd.%Y-%m-%d.log */
+		if (logs->filefmt)
 		{
-			if (stat(logs->file, &fstats) != -1 && logs->maxsize && fstats.st_size >= logs->maxsize)
+			char *fname = unreal_strftime(logs->filefmt);
+			if (logs->file && (logs->logfd != -1) && strcmp(logs->file, fname))
 			{
-				char oldlog[512];
-				if (logs->logfd == -1)
-				{
-					/* Try to open, so we can write the 'Max file size reached' message. */
-#ifndef _WIN32
-					logs->logfd = fd_fileopen(logs->file, O_CREAT|O_APPEND|O_WRONLY);
-#else
-					logs->logfd = fd_fileopen(logs->file, O_CREAT|O_APPEND|O_WRONLY);
-#endif
-				}
-				if (logs->logfd != -1)
-				{
-					if (write(logs->logfd, "Max file size reached, starting new log file\n", 45) < 0)
-					{
-						/* We already handle the unable to write to log file case for normal data.
-						 * I think we can get away with not handling this one.
-						 */
-						;
-					}
-					fd_close(logs->logfd);
-				}
-
-				/* Rename log file to xxxxxx.old */
-				snprintf(oldlog, sizeof(oldlog), "%s.old", logs->file);
-				rename(logs->file, oldlog);
-
-				logs->logfd = fd_fileopen(logs->file, O_CREAT|O_WRONLY|O_TRUNC);
-				if (logs->logfd == -1)
-					continue;
+				/* We are logging already and need to switch over */
+				fd_close(logs->logfd);
+				logs->logfd = -1;
 			}
-			else if (logs->logfd == -1) {
-#ifndef _WIN32
-				logs->logfd = fd_fileopen(logs->file, O_CREAT|O_APPEND|O_WRONLY);
-#else
-				logs->logfd = fd_fileopen(logs->file, O_CREAT|O_APPEND|O_WRONLY);
-#endif
-				if (logs->logfd == -1)
-				{
-					if (!loop.ircd_booted)
-					{
-						config_status("WARNING: Unable to write to '%s': %s", logs->file, strerror(ERRNO));
-					} else {
-						if (last_log_file_warning + 300 < TStime())
-						{
-							config_status("WARNING: Unable to write to '%s': %s. This warning will not re-appear for at least 5 minutes.", logs->file, strerror(ERRNO));
-							last_log_file_warning = TStime();
-						}
-					}
-					continue;
-				}
-			}
-			/* this shouldn't happen, but lets not waste unnecessary syscalls... */
+			safe_strdup(logs->file, fname);
+		}
+
+		/* log::maxsize code */
+		if (logs->maxsize && (stat(logs->file, &fstats) != -1) && fstats.st_size >= logs->maxsize)
+		{
+			char oldlog[512];
 			if (logs->logfd == -1)
-				continue;
-			if (write(logs->logfd, timebuf, strlen(timebuf)) < 0)
 			{
-				/* Let's ignore any write errors for this one. Next write() will catch it... */
-				;
+				/* Try to open, so we can write the 'Max file size reached' message. */
+				logs->logfd = fd_fileopen(logs->file, O_CREAT|O_APPEND|O_WRONLY);
 			}
-			n = write(logs->logfd, buf, strlen(buf));
-			if (n == strlen(buf))
+			if (logs->logfd != -1)
 			{
-				written++;
+				if (write(logs->logfd, "Max file size reached, starting new log file\n", 45) < 0)
+				{
+					/* We already handle the unable to write to log file case for normal data.
+					 * I think we can get away with not handling this one.
+					 */
+					;
+				}
+				fd_close(logs->logfd);
 			}
-			else
+			logs->logfd = -1;
+
+			/* Rename log file to xxxxxx.old */
+			snprintf(oldlog, sizeof(oldlog), "%s.old", logs->file);
+			unlink(oldlog); /* windows rename cannot overwrite, so unlink here.. ;) */
+			rename(logs->file, oldlog);
+		}
+
+		/* generic code for opening log if not open yet.. */
+		if (logs->logfd == -1)
+		{
+			logs->logfd = fd_fileopen(logs->file, O_CREAT|O_APPEND|O_WRONLY);
+			if (logs->logfd == -1)
 			{
 				if (!loop.ircd_booted)
 				{
@@ -234,6 +223,32 @@ void ircd_log(int flags, FORMAT_STRING(const char *format), ...)
 						last_log_file_warning = TStime();
 					}
 				}
+				continue;
+			}
+		}
+
+		/* Now actually WRITE to the log... */
+		if (write(logs->logfd, timebuf, strlen(timebuf)) < 0)
+		{
+			/* Let's ignore any write errors for this one. Next write() will catch it... */
+			;
+		}
+		n = write(logs->logfd, buf, strlen(buf));
+		if (n == strlen(buf))
+		{
+			written++;
+		}
+		else
+		{
+			if (!loop.ircd_booted)
+			{
+				config_status("WARNING: Unable to write to '%s': %s", logs->file, strerror(ERRNO));
+			} else {
+				if (last_log_file_warning + 300 < TStime())
+				{
+					config_status("WARNING: Unable to write to '%s': %s. This warning will not re-appear for at least 5 minutes.", logs->file, strerror(ERRNO));
+					last_log_file_warning = TStime();
+				}
 			}
 		}
 	}
@@ -754,14 +769,14 @@ void exit_client(Client *client, MessageTag *recv_mtags, char *comment)
 			hash_del_watch_list(client);
 			on_for = TStime() - client->local->firsttime;
 			if (IsHidden(client))
-				ircd_log(LOG_CLIENT, "Disconnect - (%lld:%lld:%lld) %s!%s@%s [VHOST %s] (%s)",
+				ircd_log(LOG_CLIENT, "Disconnect - (%lld:%lld:%lld) %s!%s@%s [%s] [vhost: %s] (%s)",
 					on_for / 3600, (on_for % 3600) / 60, on_for % 60,
 					client->name, client->user->username,
-					client->user->realhost, client->user->virthost, comment);
+					client->user->realhost, GetIP(client), client->user->virthost, comment);
 			else
-				ircd_log(LOG_CLIENT, "Disconnect - (%lld:%lld:%lld) %s!%s@%s (%s)",
+				ircd_log(LOG_CLIENT, "Disconnect - (%lld:%lld:%lld) %s!%s@%s [%s] (%s)",
 					on_for / 3600, (on_for % 3600) / 60, on_for % 60,
-					client->name, client->user->username, client->user->realhost, comment);
+					client->name, client->user->username, client->user->realhost, GetIP(client), comment);
 		} else
 		if (IsUnknown(client))
 		{
diff --git a/src/modules/blacklist.c b/src/modules/blacklist.c
@@ -558,9 +558,15 @@ int blacklist_start_check(Client *client)
 {
 	Blacklist *bl;
 
-	/* If the user is on 'except blacklist' then don't bother checking... */
 	if (find_tkl_exception(TKL_BLACKLIST, client))
+	{
+		/* If the user is exempt from DNSBL checking then:
+		 * 1) Don't bother checking DNSBL's
+		 * 2) Disable handshake delay for this user, since it serves no purpose.
+		 */
+		SetNoHandshakeDelay(client);
 		return 0;
+	}
 	
 	if (!BLUSER(client))
 	{
diff --git a/src/modules/chanmodes/floodprot.c b/src/modules/chanmodes/floodprot.c
@@ -45,6 +45,28 @@ struct {
 	long modef_boot_delay;
 } cfg;
 
+typedef struct FloodType {
+	char letter;
+	int index;
+	char *description;
+	char default_action;
+	char *actions;
+	int timedban_required;
+} FloodType;
+
+/* All the floodtypes that are tracked.
+ * IMPORTANT: MUST be in alphabetic order!!
+ */
+FloodType floodtypes[] = {
+	{ 'c', FLD_CTCP,	"CTCPflood",		'C',	"mM",	0, },
+	{ 'j', FLD_JOIN,	"joinflood",		'i',	"R",	0, },
+	{ 'k', FLD_KNOCK,	"knockflood",		'K',	"",	0, },
+	{ 'm', FLD_MSG,		"msg/noticeflood",	'm',	"M",	0, },
+	{ 'n', FLD_NICK,	"nickflood",		'N',	"",	0, },
+	{ 't', FLD_TEXT,	"msg/noticeflood",	'\0',	"bd",	1, },
+	{ 'r', FLD_REPEAT,	"repeating",		'\0',	"bd",	1, },
+};
+
 #define MODEF_DEFAULT_UNSETTIME		cfg.modef_default_unsettime
 #define MODEF_MAX_UNSETTIME		cfg.modef_max_unsettime
 #define MODEF_BOOT_DELAY		cfg.modef_boot_delay
@@ -102,9 +124,9 @@ void floodprottimer_del(Channel *channel, char mflag);
 void floodprottimer_stopchantimers(Channel *channel);
 static inline char *chmodefstrhelper(char *buf, char t, char tdef, unsigned short l, unsigned char a, unsigned char r);
 static int compare_floodprot_modes(ChannelFloodProtection *a, ChannelFloodProtection *b);
-static int do_floodprot(Channel *channel, int what);
+static int do_floodprot(Channel *channel, Client *client, int what);
 char *channel_modef_string(ChannelFloodProtection *x, char *str);
-void do_floodprot_action(Channel *channel, int what, char *text);
+void do_floodprot_action(Channel *channel, int what);
 void floodprottimer_add(Channel *channel, char mflag, time_t when);
 uint64_t gen_floodprot_msghash(char *text);
 int cmodef_is_ok(Client *client, Channel *channel, char mode, char *para, int type, int what);
@@ -299,6 +321,26 @@ int floodprot_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
 	return 1;
 }
 
+FloodType *find_floodprot_by_letter(char c)
+{
+	int i;
+	for (i=0; i < ARRAY_SIZEOF(floodtypes); i++)
+		if (floodtypes[i].letter == c)
+			return &floodtypes[i];
+
+	return NULL;
+}
+
+FloodType *find_floodprot_by_index(int index)
+{
+	int i;
+	for (i=0; i < ARRAY_SIZEOF(floodtypes); i++)
+		if (floodtypes[i].index == index)
+			return &floodtypes[i];
+
+	return NULL;
+}
+
 int cmodef_is_ok(Client *client, Channel *channel, char mode, char *param, int type, int what)
 {
 	if ((type == EXCHK_ACCESS) || (type == EXCHK_ACCESS_ERR))
@@ -316,6 +358,8 @@ int cmodef_is_ok(Client *client, Channel *channel, char mode, char *param, int t
 		int v;
 		unsigned short warnings = 0, breakit;
 		unsigned char r;
+		FloodType *floodtype;
+		int index;
 
 		memset(&newf, 0, sizeof(newf));
 
@@ -338,24 +382,21 @@ int cmodef_is_ok(Client *client, Channel *channel, char mode, char *param, int t
 			/* <number><1 letter>[optional: '#'+1 letter] */
 			p = x;
 			while(isdigit(*p)) { p++; }
-			if ((*p == '\0') ||
-			    !((*p == 'c') || (*p == 'j') || (*p == 'k') ||
-			      (*p == 'm') || (*p == 'n') || (*p == 't') ||
-			      (*p == 'r')))
+			c = *p;
+			floodtype = find_floodprot_by_letter(c);
+			if (!floodtype)
 			{
 				if (MyUser(client) && *p && (warnings++ < 3))
 					sendnotice(client, "warning: channelmode +f: floodtype '%c' unknown, ignored.", *p);
 				continue; /* continue instead of break for forward compatability. */
 			}
-			c = *p;
 			*p = '\0';
 			v = atoi(x);
 			if ((v < 1) || (v > 999)) /* out of range... */
 			{
 				if (MyUser(client))
 				{
-					sendnumeric(client, ERR_CANNOTCHANGECHANMODE,
-						   'f', "value should be from 1-999");
+					sendnumeric(client, ERR_CANNOTCHANGECHANMODE, 'f', "value should be from 1-999");
 					goto invalidsyntax;
 				} else
 					continue; /* just ignore for remote servers */
@@ -383,59 +424,14 @@ int cmodef_is_ok(Client *client, Channel *channel, char mode, char *param, int t
 				}
 			}
 
-			switch(c)
-			{
-				case 'c':
-					newf.limit[FLD_CTCP] = v;
-					if ((a == 'm') || (a == 'M'))
-						newf.action[FLD_CTCP] = a;
-					else
-						newf.action[FLD_CTCP] = 'C';
-					newf.remove_after[FLD_CTCP] = r;
-					break;
-				case 'j':
-					newf.limit[FLD_JOIN] = v;
-					if (a == 'R')
-						newf.action[FLD_JOIN] = a;
-					else
-						newf.action[FLD_JOIN] = 'i';
-					newf.remove_after[FLD_JOIN] = r;
-					break;
-				case 'k':
-					newf.limit[FLD_KNOCK] = v;
-					newf.action[FLD_KNOCK] = 'K';
-					newf.remove_after[FLD_KNOCK] = r;
-					break;
-				case 'm':
-					newf.limit[FLD_MSG] = v;
-					if (a == 'M')
-						newf.action[FLD_MSG] = a;
-					else
-						newf.action[FLD_MSG] = 'm';
-					newf.remove_after[FLD_MSG] = r;
-					break;
-				case 'n':
-					newf.limit[FLD_NICK] = v;
-					newf.action[FLD_NICK] = 'N';
-					newf.remove_after[FLD_NICK] = r;
-					break;
-				case 't':
-					newf.limit[FLD_TEXT] = v;
-					if (a == 'b' || a == 'd')
-						newf.action[FLD_TEXT] = a;
-					if (timedban_available)
-						newf.remove_after[FLD_TEXT] = r;
-					break;
-				case 'r':
-					newf.limit[FLD_REPEAT] = v;
-					if (a == 'b' || a == 'd')
-						newf.action[FLD_REPEAT] = a;
-					if (timedban_available)
-						newf.remove_after[FLD_REPEAT] = r;
-					break;
-				default:
-					goto invalidsyntax;
-			}
+			index = floodtype->index;
+			newf.limit[index] = v;
+			if (a && strchr(floodtype->actions, a))
+				newf.action[index] = a;
+			else
+				newf.action[index] = floodtype->default_action;
+			if (!floodtype->timedban_required || (floodtype->timedban_required && timedban_available))
+				newf.remove_after[index] = r;
 		} /* for */
 		/* parse 'per' */
 		p2++;
@@ -448,8 +444,7 @@ int cmodef_is_ok(Client *client, Channel *channel, char mode, char *param, int t
 		if ((v < 1) || (v > 999)) /* 'per' out of range */
 		{
 			if (MyUser(client))
-				sendnumeric(client, ERR_CANNOTCHANGECHANMODE, 'f',
-					   "time range should be 1-999");
+				sendnumeric(client, ERR_CANNOTCHANGECHANMODE, 'f', "time range should be 1-999");
 			goto invalidsyntax;
 		}
 		newf.per = v;
@@ -479,14 +474,13 @@ void *cmodef_put_param(void *fld_in, char *param)
 	int v;
 	unsigned short breakit;
 	unsigned char r;
+	FloodType *floodtype;
+	int index;
 
 	strlcpy(xbuf, param, sizeof(xbuf));
 
 	if (!fld)
-	{
-		/* Need to create one */
 		fld = safe_alloc(sizeof(ChannelFloodProtection));
-	}
 
 	/* always reset settings (l, a, r) */
 	for (v=0; v < NUMFLD; v++)
@@ -499,31 +493,21 @@ void *cmodef_put_param(void *fld_in, char *param)
 	/* '['<number><1 letter>[optional: '#'+1 letter],[next..]']'':'<number> */
 	p2 = strchr(xbuf+1, ']');
 	if (!p2)
-	{
-		memset(fld, 0, sizeof(ChannelFloodProtection));
-		return fld; /* FAIL */
-	}
+		goto fail_cmodef_put_param; /* FAIL */
 	*p2 = '\0';
 	if (*(p2+1) != ':')
-	{
-		memset(fld, 0, sizeof(ChannelFloodProtection));
-		return fld; /* FAIL */
-	}
+		goto fail_cmodef_put_param; /* FAIL */
+
 	breakit = 0;
 	for (x = strtok(xbuf+1, ","); x; x = strtok(NULL, ","))
 	{
 		/* <number><1 letter>[optional: '#'+1 letter] */
 		p = x;
 		while(isdigit(*p)) { p++; }
-		if ((*p == '\0') ||
-		    !((*p == 'c') || (*p == 'j') || (*p == 'k') ||
-		      (*p == 'm') || (*p == 'n') || (*p == 't') ||
-		      (*p == 'r')))
-		{
-			/* (unknown type) */
-			continue; /* continue instead of break for forward compatability. */
-		}
 		c = *p;
+		floodtype = find_floodprot_by_letter(c);
+		if (!floodtype)
+			continue; /* continue instead of break for forward compatability. */
 		*p = '\0';
 		v = atoi(x);
 		if (v < 1)
@@ -549,78 +533,28 @@ void *cmodef_put_param(void *fld_in, char *param)
 			}
 		}
 
-		switch(c)
-		{
-			case 'c':
-				fld->limit[FLD_CTCP] = v;
-				if ((a == 'm') || (a == 'M'))
-					fld->action[FLD_CTCP] = a;
-				else
-					fld->action[FLD_CTCP] = 'C';
-				fld->remove_after[FLD_CTCP] = r;
-				break;
-			case 'j':
-				fld->limit[FLD_JOIN] = v;
-				if (a == 'R')
-					fld->action[FLD_JOIN] = a;
-				else
-					fld->action[FLD_JOIN] = 'i';
-				fld->remove_after[FLD_JOIN] = r;
-				break;
-			case 'k':
-				fld->limit[FLD_KNOCK] = v;
-				fld->action[FLD_KNOCK] = 'K';
-				fld->remove_after[FLD_KNOCK] = r;
-				break;
-			case 'm':
-				fld->limit[FLD_MSG] = v;
-				if (a == 'M')
-					fld->action[FLD_MSG] = a;
-				else
-					fld->action[FLD_MSG] = 'm';
-				fld->remove_after[FLD_MSG] = r;
-				break;
-			case 'n':
-				fld->limit[FLD_NICK] = v;
-				fld->action[FLD_NICK] = 'N';
-				fld->remove_after[FLD_NICK] = r;
-				break;
-			case 't':
-				fld->limit[FLD_TEXT] = v;
-				if (a == 'b' || a == 'd')
-					fld->action[FLD_TEXT] = a;
-				if (timedban_available)
-					fld->remove_after[FLD_TEXT] = r;
-				break;
-			case 'r':
-				fld->limit[FLD_REPEAT] = v;
-				if (a == 'b' || a == 'd')
-					fld->action[FLD_REPEAT] = a;
-				if (timedban_available)
-					fld->remove_after[FLD_REPEAT] = r;
-				break;
-			default:
-				/* NOOP */
-				break;
-		}
+		index = floodtype->index;
+		fld->limit[index] = v;
+		if (a && strchr(floodtype->actions, a))
+			fld->action[index] = a;
+		else
+			fld->action[index] = floodtype->default_action;
+		if (!floodtype->timedban_required || (floodtype->timedban_required && timedban_available))
+			fld->remove_after[index] = r;
 	} /* for */
+
 	/* parse 'per' */
 	p2++;
 	if (*p2 != ':')
-	{
-		memset(fld, 0, sizeof(ChannelFloodProtection));
-		return fld; /* FAIL */
-	}
+		goto fail_cmodef_put_param; /* FAIL */
 	p2++;
 	if (!*p2)
-	{
-		memset(fld, 0, sizeof(ChannelFloodProtection));
-		return fld; /* FAIL */
-	}
+		goto fail_cmodef_put_param; /* FAIL */
 	v = atoi(p2);
 	if (v < 1)
 		v = 1;
-	/* if new 'per xxx seconds' is smaller than current 'per' then reset timers/counters (t, c) */
+
+	/* If new 'per xxx seconds' is smaller than current 'per' then reset timers/counters (t, c) */
 	if (v < fld->per)
 	{
 		int i;
@@ -638,12 +572,13 @@ void *cmodef_put_param(void *fld_in, char *param)
 		if (fld->limit[v])
 			breakit=0;
 	if (breakit)
-	{
-		memset(fld, 0, sizeof(ChannelFloodProtection));
-		return fld; /* FAIL */
-	}
+		goto fail_cmodef_put_param; /* FAIL */
 
 	return (void *)fld;
+
+fail_cmodef_put_param:
+	memset(fld, 0, sizeof(ChannelFloodProtection));
+	return fld; /* FAIL */
 }
 
 char *cmodef_get_param(void *r_in)
@@ -671,6 +606,8 @@ char *cmodef_conv_param(char *param_in, Client *client)
 	int v;
 	unsigned short breakit;
 	unsigned char r;
+	FloodType *floodtype;
+	int index;
 
 	memset(&newf, 0, sizeof(newf));
 
@@ -694,15 +631,10 @@ char *cmodef_conv_param(char *param_in, Client *client)
 		/* <number><1 letter>[optional: '#'+1 letter] */
 		p = x;
 		while(isdigit(*p)) { p++; }
-		if ((*p == '\0') ||
-		    !((*p == 'c') || (*p == 'j') || (*p == 'k') ||
-		      (*p == 'm') || (*p == 'n') || (*p == 't') ||
-		      (*p == 'r')))
-		{
-			/* (unknown type) */
-			continue; /* continue instead of break for forward compatability. */
-		}
 		c = *p;
+		floodtype = find_floodprot_by_letter(c);
+		if (!floodtype)
+			continue; /* continue instead of break for forward compatability. */
 		*p = '\0';
 		v = atoi(x);
 		if ((v < 1) || (v > 999)) /* out of range... */
@@ -733,59 +665,14 @@ char *cmodef_conv_param(char *param_in, Client *client)
 			}
 		}
 
-		switch(c)
-		{
-			case 'c':
-				newf.limit[FLD_CTCP] = v;
-				if ((a == 'm') || (a == 'M'))
-					newf.action[FLD_CTCP] = a;
-				else
-					newf.action[FLD_CTCP] = 'C';
-				newf.remove_after[FLD_CTCP] = r;
-				break;
-			case 'j':
-				newf.limit[FLD_JOIN] = v;
-				if (a == 'R')
-					newf.action[FLD_JOIN] = a;
-				else
-					newf.action[FLD_JOIN] = 'i';
-				newf.remove_after[FLD_JOIN] = r;
-				break;
-			case 'k':
-				newf.limit[FLD_KNOCK] = v;
-				newf.action[FLD_KNOCK] = 'K';
-				newf.remove_after[FLD_KNOCK] = r;
-				break;
-			case 'm':
-				newf.limit[FLD_MSG] = v;
-				if (a == 'M')
-					newf.action[FLD_MSG] = a;
-				else
-					newf.action[FLD_MSG] = 'm';
-				newf.remove_after[FLD_MSG] = r;
-				break;
-			case 'n':
-				newf.limit[FLD_NICK] = v;
-				newf.action[FLD_NICK] = 'N';
-				newf.remove_after[FLD_NICK] = r;
-				break;
-			case 't':
-				newf.limit[FLD_TEXT] = v;
-				if (a == 'b' || a == 'd')
-					newf.action[FLD_TEXT] = a;
-				if (timedban_available)
-					newf.remove_after[FLD_TEXT] = r;
-				break;
-			case 'r':
-				newf.limit[FLD_REPEAT] = v;
-				if (a == 'b' || a == 'd')
-					newf.action[FLD_REPEAT] = a;
-				if (timedban_available)
-					newf.remove_after[FLD_REPEAT] = r;
-				break;
-			default:
-				return NULL;
-		}
+		index = floodtype->index;
+		newf.limit[index] = v;
+		if (a && strchr(floodtype->actions, a))
+			newf.action[index] = a;
+		else
+			newf.action[index] = floodtype->default_action;
+		if (!floodtype->timedban_required || (floodtype->timedban_required && timedban_available))
+			newf.remove_after[index] = r;
 	} /* for */
 	/* parse 'per' */
 	p2++;
@@ -864,11 +751,9 @@ int floodprot_join(Client *client, Channel *channel, MessageTag *mtags, char *pa
 	if (IsFloodLimit(channel) &&
 	    (MyUser(client) || client->srvptr->serv->flags.synced) &&
 	    (client->srvptr->serv->boottime && (TStime() - client->srvptr->serv->boottime >= MODEF_BOOT_DELAY)) &&
-	    !IsULine(client) &&
-	    do_floodprot(channel, FLD_JOIN) &&
-	    MyUser(client))
+	    !IsULine(client))
 	{
-		do_floodprot_action(channel, FLD_JOIN, "join");
+	    do_floodprot(channel, client, FLD_JOIN);
 	}
 	return 0;
 }
@@ -913,25 +798,18 @@ char tmpbuf[16], *p2 = tmpbuf;
  */
 char *channel_modef_string(ChannelFloodProtection *x, char *retbuf)
 {
+	int i;
 	char *p = retbuf;
+	FloodType *f;
 
 	*p++ = '[';
 
-	/* (alphabetized) */
-	if (x->limit[FLD_CTCP])
-		p = chmodefstrhelper(p, 'c', 'C', x->limit[FLD_CTCP], x->action[FLD_CTCP], x->remove_after[FLD_CTCP]);
-	if (x->limit[FLD_JOIN])
-		p = chmodefstrhelper(p, 'j', 'i', x->limit[FLD_JOIN], x->action[FLD_JOIN], x->remove_after[FLD_JOIN]);
-	if (x->limit[FLD_KNOCK])
-		p = chmodefstrhelper(p, 'k', 'K', x->limit[FLD_KNOCK], x->action[FLD_KNOCK], x->remove_after[FLD_KNOCK]);
-	if (x->limit[FLD_MSG])
-		p = chmodefstrhelper(p, 'm', 'm', x->limit[FLD_MSG], x->action[FLD_MSG], x->remove_after[FLD_MSG]);
-	if (x->limit[FLD_NICK])
-		p = chmodefstrhelper(p, 'n', 'N', x->limit[FLD_NICK], x->action[FLD_NICK], x->remove_after[FLD_NICK]);
-	if (x->limit[FLD_TEXT])
-		p = chmodefstrhelper(p, 't', '\0', x->limit[FLD_TEXT], x->action[FLD_TEXT], x->remove_after[FLD_TEXT]);
-	if (x->limit[FLD_REPEAT])
-		p = chmodefstrhelper(p, 'r', '\0', x->limit[FLD_REPEAT], x->action[FLD_REPEAT], x->remove_after[FLD_REPEAT]);
+	for (i=0; i < ARRAY_SIZEOF(floodtypes); i++)
+	{
+		f = &floodtypes[i];
+		if (x->limit[f->index])
+			p = chmodefstrhelper(p, f->letter, f->default_action, x->limit[f->index], x->action[f->index], x->remove_after[f->index]);
+	}
 
 	if (*(p - 1) == ',')
 		p--;
@@ -1074,22 +952,18 @@ int floodprot_post_chanmsg(Client *client, Channel *channel, int sendflags, int 
 
 	/* HINT: don't be so stupid to reorder the items in the if's below.. you'll break things -- Syzop. */
 
-	if (do_floodprot(channel, FLD_MSG) && MyUser(client))
-		do_floodprot_action(channel, FLD_MSG, "msg/notice");
+	do_floodprot(channel, client, FLD_MSG);
 
-	if ((text[0] == '\001') && strncmp(text+1, "ACTION ", 7) &&
-	    do_floodprot(channel, FLD_CTCP) && MyUser(client))
-	{
-		do_floodprot_action(channel, FLD_CTCP, "CTCP");
-	}
+	if ((text[0] == '\001') && strncmp(text+1, "ACTION ", 7))
+		do_floodprot(channel, client, FLD_CTCP);
 
 	return 0;
 }
 
 int floodprot_knock(Client *client, Channel *channel, MessageTag *mtags, char *comment)
 {
-	if (IsFloodLimit(channel) && !IsULine(client) && do_floodprot(channel, FLD_KNOCK) && MyUser(client))
-		do_floodprot_action(channel, FLD_KNOCK, "knock");
+	if (IsFloodLimit(channel) && !IsULine(client))
+		do_floodprot(channel, client, FLD_KNOCK);
 	return 0;
 }
 
@@ -1104,10 +978,9 @@ int floodprot_nickchange(Client *client, char *oldnick)
 	{
 		Channel *channel = mp->channel;
 		if (channel && IsFloodLimit(channel) &&
-		    !(mp->flags & (CHFL_CHANOP|CHFL_VOICE|CHFL_CHANOWNER|CHFL_HALFOP|CHFL_CHANADMIN)) &&
-		    do_floodprot(channel, FLD_NICK) && MyUser(client))
+		    !(mp->flags & (CHFL_CHANOP|CHFL_VOICE|CHFL_CHANOWNER|CHFL_HALFOP|CHFL_CHANADMIN)))
 		{
-			do_floodprot_action(channel, FLD_NICK, "nick");
+			do_floodprot(channel, client, FLD_NICK);
 		}
 	}
 	return 0;
@@ -1316,42 +1189,46 @@ void floodprottimer_stopchantimers(Channel *channel)
 	}
 }
 
-int do_floodprot(Channel *channel, int what)
+int do_floodprot(Channel *channel, Client *client, int what)
 {
 	ChannelFloodProtection *chp = (ChannelFloodProtection *)GETPARASTRUCT(channel, 'f');
 
-	if (!chp || !chp->limit[what]) /* no +f or not restricted */
-		return 0;
-	if (TStime() - chp->timer[what] >= chp->per)
-	{
-		chp->timer[what] = TStime();
-		chp->counter[what] = 1;
-	} else
+	if (!chp)
+		return 0; /* no +f active */
+
+	if (chp->limit[what])
 	{
-		chp->counter[what]++;
-		if ((chp->counter[what] > chp->limit[what]) &&
-		    (TStime() - chp->timer[what] < chp->per))
+		if (TStime() - chp->timer[what] >= chp->per)
+		{
+			chp->timer[what] = TStime();
+			chp->counter[what] = 1;
+		} else
 		{
-			/* reset it too (makes it easier for chanops to handle the situation) */
-			/*
-			 *XXchp->timer[what] = TStime();
-			 *XXchp->counter[what] = 1;
-			 *
-			 * BAD.. there are some situations where we might 'miss' a flood
-			 * because of this. The reset has been moved to -i,-m,-N,-C,etc.
-			*/
-			return 1; /* flood detected! */
+			chp->counter[what]++;
+			if ((chp->counter[what] > chp->limit[what]) &&
+			    (TStime() - chp->timer[what] < chp->per))
+			{
+				if (MyUser(client))
+					do_floodprot_action(channel, what);
+				return 1; /* flood detected! */
+			}
 		}
 	}
 	return 0;
 }
 
-void do_floodprot_action(Channel *channel, int what, char *text)
+void do_floodprot_action(Channel *channel, int what)
 {
 	char m;
 	int mode = 0;
 	Cmode_t extmode = 0;
 	ChannelFloodProtection *chp = (ChannelFloodProtection *)GETPARASTRUCT(channel, 'f');
+	FloodType *floodtype = find_floodprot_by_index(what);
+	char *text;
+
+	if (!floodtype)
+		return;
+	text = floodtype->description;
 
 	m = chp->action[what];
 	if (!m)
@@ -1379,7 +1256,7 @@ void do_floodprot_action(Channel *channel, int what, char *text)
 		/* First the notice to the chanops */
 		mtags = NULL;
 		new_message(&me, NULL, &mtags);
-		ircsnprintf(comment, sizeof(comment), "*** Channel %sflood detected (limit is %d per %d seconds), setting mode +%c",
+		ircsnprintf(comment, sizeof(comment), "*** Channel %s detected (limit is %d per %d seconds), setting mode +%c",
 			text, chp->limit[what], chp->per, m);
 		ircsnprintf(target, sizeof(target), "%%%s", channel->chname);
 		sendto_channel(channel, &me, NULL, PREFIX_HALFOP|PREFIX_OP|PREFIX_ADMIN|PREFIX_OWNER,
diff --git a/src/modules/channeldb.c b/src/modules/channeldb.c
@@ -14,8 +14,15 @@ ModuleHeader MOD_HEADER = {
 	"unrealircd-5",
 };
 
+/* Database version */
 #define CHANNELDB_VERSION 100
-#define CHANNELDB_SAVE_EVERY 299
+/* Save channels to file every <this> seconds */
+#define CHANNELDB_SAVE_EVERY 300
+/* The very first save after boot, apply this delta, this
+ * so we don't coincide with other (potentially) expensive
+ * I/O events like saving tkldb.
+ */
+#define CHANNELDB_SAVE_EVERY_DELTA -15
 
 #define MAGIC_CHANNEL_START	0x11111111
 #define MAGIC_CHANNEL_END	0x22222222
@@ -102,7 +109,7 @@ MOD_LOAD()
 			else
 				config_warn("[channeldb] Failed to rename database from %s to %s: %s", cfg.database, fname, strerror(errno));
 		}
-		channeldb_next_event = TStime() + CHANNELDB_SAVE_EVERY;
+		channeldb_next_event = TStime() + CHANNELDB_SAVE_EVERY + CHANNELDB_SAVE_EVERY_DELTA;
 	}
 	EventAdd(modinfo->handle, "channeldb_write_channeldb", write_channeldb_evt, NULL, 1000, 0);
 	if (ModuleGetError(modinfo->handle) != MODERR_NOERROR)
@@ -209,7 +216,7 @@ int write_channeldb(void)
 #endif
 
 	// Write to a tempfile first, then rename it if everything succeeded
-	snprintf(tmpfname, sizeof(tmpfname), "%s.tmp", cfg.database);
+	snprintf(tmpfname, sizeof(tmpfname), "%s.%x.tmp", cfg.database, getrandom32());
 	fd = fopen(tmpfname, "wb");
 	if (!fd)
 	{
diff --git a/src/modules/nick.c b/src/modules/nick.c
@@ -679,13 +679,14 @@ nickkill2done:
 	register_user(client, client->name, username, umodes, virthost, ip);
 	if (IsDead(client))
 		return;
-	if (!IsULine(serv) && IsSynched(serv))
-		sendto_fconnectnotice(client, 0, NULL);
 
 	if (client->user->svid[0] != '0')
 		user_account_login(recv_mtags, client);
 
 	RunHook(HOOKTYPE_REMOTE_CONNECT, client);
+
+	if (!IsULine(serv) && IsSynched(serv))
+		sendto_fconnectnotice(client, 0, NULL);
 }
 
 /** The NICK command.
@@ -945,11 +946,14 @@ int _register_user(Client *client, char *nick, char *username, char *umode, char
 		}
 
 		if (IsHidden(client))
-			ircd_log(LOG_CLIENT, "Connect - %s!%s@%s [VHOST %s]", nick,
-				user->username, user->realhost, user->virthost);
-		else
-			ircd_log(LOG_CLIENT, "Connect - %s!%s@%s", nick, user->username,
-				user->realhost);
+		{
+			ircd_log(LOG_CLIENT, "Connect - %s!%s@%s [%s] [vhost: %s] %s",
+				nick, user->username, user->realhost, GetIP(client), user->virthost, get_connect_extinfo(client));
+		} else
+		{
+			ircd_log(LOG_CLIENT, "Connect - %s!%s@%s [%s] %s",
+				nick, user->username, user->realhost, GetIP(client), get_connect_extinfo(client));
+		}
 
 		RunHook2(HOOKTYPE_WELCOME, client, 0);
 		sendnumeric(client, RPL_WELCOME, ircnetwork, nick, user->username, user->realhost);
@@ -1278,17 +1282,24 @@ int check_init(Client *client, char *sockn, size_t size)
 int exceeds_maxperip(Client *client, ConfigItem_allow *aconf)
 {
 	Client *acptr;
-	int cnt = 1;
+	int local_cnt = 1;
+	int global_cnt = 1;
 
 	if (find_tkl_exception(TKL_MAXPERIP, client))
 		return 0; /* exempt */
 
-	list_for_each_entry(acptr, &lclient_list, lclient_node)
+	list_for_each_entry(acptr, &client_list, client_node)
 	{
 		if (IsUser(acptr) && !strcmp(GetIP(acptr), GetIP(client)))
 		{
-			cnt++;
-			if (cnt > aconf->maxperip)
+			if (MyUser(acptr))
+			{
+				local_cnt++;
+				if (local_cnt > aconf->maxperip)
+					return 1;
+			}
+			global_cnt++;
+			if (global_cnt > aconf->global_maxperip)
 				return 1;
 		}
 	}
@@ -1412,7 +1423,7 @@ int AllowClient(Client *client, char *username)
 			strlcpy(uhost, sockhost, sizeof(uhost));
 		set_sockhost(client, uhost);
 
-		if (aconf->maxperip && exceeds_maxperip(client, aconf))
+		if (exceeds_maxperip(client, aconf))
 		{
 			/* Already got too many with that ip# */
 			exit_client(client, NULL, iConf.reject_message_too_many_connections);
diff --git a/src/modules/nocodes.c b/src/modules/nocodes.c
@@ -23,8 +23,8 @@
 ModuleHeader MOD_HEADER
 = {
 	"nocodes",	/* Name of module */
-	"1.2", /* Version */
-	"Strip/block bold/underline/reverse - by Syzop", /* Short description of module */
+	"1.3", /* Version */
+	"Strip/block color/bold/underline/italic/reverse - by Syzop", /* Short description of module */
 	"UnrealIRCd Team", /* Author */
 	"unrealircd-5",
 };
@@ -95,7 +95,7 @@ int nocodes_can_send_to_channel(Client *client, Channel *channel, Membership *lp
 				break;
 		}
 
-		*errmsg = "Control codes (bold/underline/reverse) are not permitted in this channel";
+		*errmsg = "Control codes (color/bold/underline/italic/reverse) are not permitted in this channel";
 		return HOOK_DENY;
 	}
 	return HOOK_CONTINUE;
diff --git a/src/modules/reputation.c b/src/modules/reputation.c
@@ -117,6 +117,7 @@ CMD_FUNC(reputationunperm);
 int reputation_whois(Client *client, Client *target);
 int reputation_set_on_connect(Client *client);
 int reputation_pre_lconnect(Client *client);
+int reputation_connect_extinfo(Client *client, NameValuePrioList **list);
 int reputation_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs);
 int reputation_config_run(ConfigFile *cf, ConfigEntry *ce, int type);
 int reputation_config_posttest(int *errs);
@@ -165,6 +166,7 @@ MOD_INIT()
 	HookAdd(modinfo->handle, HOOKTYPE_HANDSHAKE, 0, reputation_set_on_connect);
 	HookAdd(modinfo->handle, HOOKTYPE_PRE_LOCAL_CONNECT, 2000000000, reputation_pre_lconnect); /* (prio: last) */
 	HookAdd(modinfo->handle, HOOKTYPE_REMOTE_CONNECT, -1000000000, reputation_set_on_connect); /* (prio: near-first) */
+	HookAdd(modinfo->handle, HOOKTYPE_CONNECT_EXTINFO, 0, reputation_connect_extinfo); /* (prio: near-first) */
 	CommandAdd(ModInf.handle, "REPUTATION", reputation_cmd, MAXPARA, CMD_USER|CMD_SERVER);
 	CommandAdd(ModInf.handle, "REPUTATIONUNPERM", reputationunperm, MAXPARA, CMD_USER|CMD_SERVER);
 	return MOD_SUCCESS;
@@ -399,7 +401,7 @@ void save_db(void)
 #endif
 
 	/* We write to a temporary file. Only to rename it later if everything was ok */
-	snprintf(tmpfname, sizeof(tmpfname), "%s.tmp", cfg.database);
+	snprintf(tmpfname, sizeof(tmpfname), "%s.%x.tmp", cfg.database, getrandom32());
 	
 	fd = fopen(tmpfname, "w");
 	if (!fd)
@@ -669,6 +671,12 @@ CMD_FUNC(reputationunperm)
 	               client->name);
 }
 
+int reputation_connect_extinfo(Client *client, NameValuePrioList **list)
+{
+	add_fmt_nvplist(list, 0, "reputation", "%d", GetReputation(client));
+	return 0;
+}
+
 int count_reputation_records(void)
 {
 	int i;
diff --git a/src/modules/stats.c b/src/modules/stats.c
@@ -488,9 +488,15 @@ int stats_allow(Client *client, char *para)
 {
 	ConfigItem_allow *allows;
 	for (allows = conf_allow; allows; allows = allows->next)
-		sendnumeric(client, RPL_STATSILINE, allows->ip, allows->hostname, allows->maxperip,
-			allows->class->name, allows->server ? allows->server
-			: defserv, allows->port ? allows->port : 6667);
+	{
+		sendnumeric(client, RPL_STATSILINE,
+		            allows->ip, allows->hostname,
+		            allows->maxperip,
+		            allows->global_maxperip,
+		            allows->class->name,
+		            allows->server ? allows->server : defserv,
+		            allows->port ? allows->port : 6667);
+	}
 	return 0;
 }
 
@@ -866,12 +872,11 @@ int stats_set(Client *client, char *para)
 	if (LINK_BINDIP)
 		sendtxtnumeric(client, "link::bind-ip: %s", LINK_BINDIP);
 	sendtxtnumeric(client, "anti-flood::connect-flood: %d per %s", THROTTLING_COUNT, pretty_time_val(THROTTLING_PERIOD));
-	sendtxtnumeric(client, "anti-flood::unknown-flood-bantime: %s", pretty_time_val(UNKNOWN_FLOOD_BANTIME));
-	sendtxtnumeric(client, "anti-flood::unknown-flood-amount: %ldKB", UNKNOWN_FLOOD_AMOUNT);
+	sendtxtnumeric(client, "anti-flood::handshake-data-flood::amount: %ld bytes", iConf.handshake_data_flood_amount);
+	sendtxtnumeric(client, "anti-flood::handshake-data-flood::ban-action: %s", banact_valtostring(iConf.handshake_data_flood_ban_action));
+	sendtxtnumeric(client, "anti-flood::handshake-data-flood::ban-time: %s", pretty_time_val(iConf.handshake_data_flood_ban_time));
 	if (AWAY_PERIOD)
-	{
 		sendtxtnumeric(client, "anti-flood::away-flood: %d per %s", AWAY_COUNT, pretty_time_val(AWAY_PERIOD));
-	}
 	sendtxtnumeric(client, "anti-flood::nick-flood: %d per %s", NICK_COUNT, pretty_time_val(NICK_PERIOD));
 	sendtxtnumeric(client, "handshake-timeout: %s", pretty_time_val(iConf.handshake_timeout));
 	sendtxtnumeric(client, "sasl-timeout: %s", pretty_time_val(iConf.sasl_timeout));
diff --git a/src/modules/svsmode.c b/src/modules/svsmode.c
@@ -504,7 +504,7 @@ void do_svsmode(Client *client, MessageTag *recv_mtags, int parc, char *parv[], 
 	   only if the old flags (setflags) are different than the newly-
 	   set ones */
 	if (setflags != target->umodes)
-		RunHook3(HOOKTYPE_UMODE_CHANGE, client, setflags, target->umodes);
+		RunHook3(HOOKTYPE_UMODE_CHANGE, target, setflags, target->umodes);
 
 	if (show_change)
 	{
diff --git a/src/modules/tkl.c b/src/modules/tkl.c
@@ -34,7 +34,7 @@ ModuleHeader MOD_HEADER
 
 /* Forward declarations */
 int tkl_config_test_spamfilter(ConfigFile *, ConfigEntry *, int, int *);
-int tkl_config_match_spamfilter(ConfigFile *, ConfigEntry *, int);
+int tkl_config_run_spamfilter(ConfigFile *, ConfigEntry *, int);
 int tkl_config_test_ban(ConfigFile *, ConfigEntry *, int, int *);
 int tkl_config_run_ban(ConfigFile *, ConfigEntry *, int);
 int tkl_config_test_except(ConfigFile *, ConfigEntry *, int, int *);
@@ -95,6 +95,7 @@ TKL *_find_tkl_banexception(int type, char *usermask, char *hostmask, int softba
 TKL *_find_tkl_nameban(int type, char *name, int hold);
 TKL *_find_tkl_spamfilter(int type, char *match_string, BanAction action, unsigned short target);
 int _find_tkl_exception(int ban_type, Client *client);
+static void add_default_exempts(void);
 
 /* Externals (only for us :D) */
 extern int MODVAR spamf_ugly_vchanoverride;
@@ -122,27 +123,27 @@ struct TKLTypeTable
  */
 TKLTypeTable tkl_types[] = {
 	/* <config name> <letter> <TKL_xxx type>               <logging name> <tkl option?> <exempt option?> */
-	{ "gline",              'G', TKL_KILL       | TKL_GLOBAL, "G-Line",             1, 1 },
-	{ "kline",              'k', TKL_KILL,                    "K-Line",             1, 1 },
-	{ "gzline",             'Z', TKL_ZAP        | TKL_GLOBAL, "Global Z-Line",      1, 1 },
-	{ "zline",              'z', TKL_ZAP,                     "Z-Line",             1, 1 },
-	{ "spamfilter",         'F', TKL_SPAMF      | TKL_GLOBAL, "Spamfilter",         1, 1 },
-	{ "qline",              'Q', TKL_NAME       | TKL_GLOBAL, "Q-Line",             1, 1 },
-	{ "except",             'E', TKL_EXCEPTION  | TKL_GLOBAL, "Exception",          1, 0 },
-	{ "shun",               's', TKL_SHUN       | TKL_GLOBAL, "Shun",               1, 1 },
-	{ "local-qline",        'q', TKL_NAME,                    "Local Q-Line",       1, 0 },
-	{ "local-spamfilter",   'e', TKL_EXCEPTION,               "Local Exception",    1, 0 },
-	{ "local-exception",    'f', TKL_SPAMF,                   "Local Spamfilter",   1, 0 },
-	{ "blacklist",          'b', TKL_BLACKLIST,               "Blacklist",          0, 1 },
-	{ "connect-flood",      'c', TKL_CONNECT_FLOOD,           "Connect flood",      0, 1 },
-	{ "maxperip",           'm', TKL_MAXPERIP,                "Max-per-IP",         0, 1 },
-	{ "unknown-data-flood", 'd', TKL_UNKNOWN_DATA_FLOOD,      "Unknown data flood", 0, 1 },
-	{ "antirandom",         'r', TKL_ANTIRANDOM,              "Antirandom",         0, 1 },
-	{ "antimixedutf8",      '8', TKL_ANTIMIXEDUTF8,           "Antimixedutf8",      0, 1 },
-	{ "ban-version",        'v', TKL_BAN_VERSION,             "Ban Version",        0, 1 },
-	{ NULL,                 '\0', 0,                          NULL,                 0, 0 },
+	{ "gline",                'G', TKL_KILL       | TKL_GLOBAL, "G-Line",               1, 1 },
+	{ "kline",                'k', TKL_KILL,                    "K-Line",               1, 1 },
+	{ "gzline",               'Z', TKL_ZAP        | TKL_GLOBAL, "Global Z-Line",        1, 1 },
+	{ "zline",                'z', TKL_ZAP,                     "Z-Line",               1, 1 },
+	{ "spamfilter",           'F', TKL_SPAMF      | TKL_GLOBAL, "Spamfilter",           1, 1 },
+	{ "qline",                'Q', TKL_NAME       | TKL_GLOBAL, "Q-Line",               1, 1 },
+	{ "except",               'E', TKL_EXCEPTION  | TKL_GLOBAL, "Exception",            1, 0 },
+	{ "shun",                 's', TKL_SHUN       | TKL_GLOBAL, "Shun",                 1, 1 },
+	{ "local-qline",          'q', TKL_NAME,                    "Local Q-Line",         1, 0 },
+	{ "local-spamfilter",     'e', TKL_EXCEPTION,               "Local Exception",      1, 0 },
+	{ "local-exception",      'f', TKL_SPAMF,                   "Local Spamfilter",     1, 0 },
+	{ "blacklist",            'b', TKL_BLACKLIST,               "Blacklist",            0, 1 },
+	{ "connect-flood",        'c', TKL_CONNECT_FLOOD,           "Connect flood",        0, 1 },
+	{ "maxperip",             'm', TKL_MAXPERIP,                "Max-per-IP",           0, 1 },
+	{ "handshake-data-flood", 'd', TKL_HANDSHAKE_DATA_FLOOD,    "Handshake data flood", 0, 1 },
+	{ "antirandom",           'r', TKL_ANTIRANDOM,              "Antirandom",           0, 1 },
+	{ "antimixedutf8",        '8', TKL_ANTIMIXEDUTF8,           "Antimixedutf8",        0, 1 },
+	{ "ban-version",          'v', TKL_BAN_VERSION,             "Ban Version",          0, 1 },
+	{ NULL,                   '\0', 0,                          NULL,                   0, 0 },
 };
-#define ALL_VALID_EXCEPTION_TYPES "kline, gline, zline, gzline, spamfilter, shun, qline, blacklist, connect-flood, unknown-data-flood, antirandom, antimixedutf8, ban-version"
+#define ALL_VALID_EXCEPTION_TYPES "kline, gline, zline, gzline, spamfilter, shun, qline, blacklist, connect-flood, handshake-data-flood, antirandom, antimixedutf8, ban-version"
 
 int max_stats_matches = 1000;
 
@@ -192,7 +193,7 @@ MOD_TEST()
 MOD_INIT()
 {
 	MARK_AS_OFFICIAL_MODULE(modinfo);
-	HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, tkl_config_match_spamfilter);
+	HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, tkl_config_run_spamfilter);
 	HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, tkl_config_run_ban);
 	HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, tkl_config_run_except);
 	HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, tkl_config_run_set);
@@ -205,6 +206,7 @@ MOD_INIT()
 	CommandAdd(modinfo->handle, "SPAMFILTER", cmd_spamfilter, 7, CMD_OPER);
 	CommandAdd(modinfo->handle, "ELINE", cmd_eline, 4, CMD_OPER);
 	CommandAdd(modinfo->handle, "TKL", _cmd_tkl, MAXPARA, CMD_OPER|CMD_SERVER);
+	add_default_exempts();
 	MARK_AS_OFFICIAL_MODULE(modinfo);
 	return MOD_SUCCESS;
 }
@@ -437,7 +439,7 @@ int tkl_config_test_spamfilter(ConfigFile *cf, ConfigEntry *ce, int type, int *e
 }
 
 /** Process a spamfilter { } block in the configuration file */
-int tkl_config_match_spamfilter(ConfigFile *cf, ConfigEntry *ce, int type)
+int tkl_config_run_spamfilter(ConfigFile *cf, ConfigEntry *ce, int type)
 {
 	ConfigEntry *cep;
 	ConfigEntry *cepp;
@@ -491,7 +493,7 @@ int tkl_config_match_spamfilter(ConfigFile *cf, ConfigEntry *ce, int type)
 	                    target,
 	                    action,
 	                    m,
-	                    me.name,
+	                    "-config-",
 	                    0,
 	                    TStime(),
 	                    bantime,
@@ -1525,14 +1527,14 @@ void eline_syntax(Client *client)
 	sendnotice(client, "F: Spamfilter");
 	sendnotice(client, "b: Blacklist checking");
 	sendnotice(client, "c: Connect flood (bypass set::anti-flood::connect-flood))");
-	sendnotice(client, "d: Unknown data flood (no ZLINE on too much data before registration)");
+	sendnotice(client, "d: Handshake data flood (no ZLINE on too much data before registration)");
 	sendnotice(client, "m: Bypass allow::maxperip restriction");
 	sendnotice(client, "r: Bypass antirandom module");
 	sendnotice(client, "8: Bypass antimixedutf8 module");
 	sendnotice(client, "v: Bypass ban version { } blocks");
 	sendnotice(client, "Examples:");
-	sendnotice(client, "/ELINE *@unrealircd.org kGf 0 This user is exempt");
-	sendnotice(client, "/ELINE ~S:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef kGf 0 Trusted user with this certificate fingerprint");
+	sendnotice(client, "/ELINE *@unrealircd.org kGF 0 This user is exempt");
+	sendnotice(client, "/ELINE ~S:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef kGF 0 Trusted user with this certificate fingerprint");
 	sendnotice(client, "-");
 	sendnotice(client, "To get a list of all current ELINEs, type: /STATS except");
 }
@@ -2637,6 +2639,18 @@ void _tkl_del_line(TKL *tkl)
 	free_tkl(tkl);
 }
 
+/** Add some default ban exceptions - for localhost */
+static void add_default_exempts(void)
+{
+	/* The exempted ban types are only ones that will affect other connections as well,
+	 * such as gline, and not policy decissions such as maxperip exempt or bypass qlines.
+	 * Currently the list is: gline, kline, gzline, zline, shun, blacklist,
+	 *                        connect-flood, handshake-data-flood.
+	 */
+	tkl_add_banexception(TKL_EXCEPTION, "*", "127.*", "localhost is always exempt",
+	                     "-default-", 0, TStime(), 0, "GkZzsbcd", TKL_FLAG_CONFIG);
+}
+
 /*
  * tkl_check_local_remove_shun:
  * removes shun from currently connected users affected by tmp.
@@ -4673,6 +4687,12 @@ int _match_spamfilter(Client *client, char *str_in, int target, char *destinatio
 	if (!client->user || ValidatePermissionsForPath("immune:server-ban:spamfilter",client,NULL,NULL,NULL) || IsULine(client))
 		return 0;
 
+	/* Client exempt from spamfilter checking?
+	 * Let's check that early: going through elines is likely faster than running the regex(es).
+	 */
+	if (find_tkl_exception(TKL_SPAMF, client))
+		return 0;
+
 	for (tkl = tklines[tkl_hash('F')]; tkl; tkl = tkl->next)
 	{
 		if (!(tkl->ptr.spamfilter->target & target))
diff --git a/src/modules/tkldb.c b/src/modules/tkldb.c
@@ -27,9 +27,16 @@ ModuleHeader MOD_HEADER = {
 	"unrealircd-5",
 };
 
-#define TKL_DB_MAGIC 0x10101010
-#define TKL_DB_VERSION 4999
-#define TKL_DB_SAVE_EVERY 299
+#define TKLDB_MAGIC 0x10101010
+/* Database version */
+#define TKLDB_VERSION 4999
+/* Save tkls to file every <this> seconds */
+#define TKLDB_SAVE_EVERY 300
+/* The very first save after boot, apply this delta, this
+ * so we don't coincide with other (potentially) expensive
+ * I/O events like saving channeldb.
+ */
+#define TKLDB_SAVE_EVERY_DELTA +15
 
 #ifdef DEBUGMODE
  #define BENCHMARK
@@ -96,13 +103,13 @@ int write_tkline(FILE *fd, const char *tmpfname, TKL *tkl);
 int read_tkldb(void);
 
 /* Globals variables */
-const uint32_t tkl_db_version = TKL_DB_VERSION;
+const uint32_t tkldb_version = TKLDB_VERSION;
 struct cfgstruct {
 	char *database;
 };
 static struct cfgstruct cfg;
 
-static int tkls_loaded = 0;
+static long tkldb_next_event = 0;
 
 MOD_TEST()
 {
@@ -115,11 +122,11 @@ MOD_INIT()
 {
 	MARK_AS_OFFICIAL_MODULE(modinfo);
 
-	LoadPersistentInt(modinfo, tkls_loaded);
+	LoadPersistentLong(modinfo, tkldb_next_event);
 
 	setcfg();
 
-	if (!tkls_loaded)
+	if (!tkldb_next_event)
 	{
 		/* If this is the first time that our module is loaded, then
 		 * read the TKL DB and add all *-Lines.
@@ -133,7 +140,7 @@ MOD_INIT()
 			else
 				config_warn("[tkldb] Failed to rename database from %s to %s: %s", cfg.database, fname, strerror(errno));
 		}
-		tkls_loaded = 1;
+		tkldb_next_event = TStime() + TKLDB_SAVE_EVERY + TKLDB_SAVE_EVERY_DELTA;
 	}
 	HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, tkldb_configrun);
 	return MOD_SUCCESS;
@@ -141,7 +148,7 @@ MOD_INIT()
 
 MOD_LOAD()
 {
-	EventAdd(modinfo->handle, "tkldb_write_tkldb", write_tkldb_evt, NULL, TKL_DB_SAVE_EVERY*1000, 0);
+	EventAdd(modinfo->handle, "tkldb_write_tkldb", write_tkldb_evt, NULL, 1000, 0);
 	if (ModuleGetError(modinfo->handle) != MODERR_NOERROR)
 	{
 		config_error("A critical error occurred when loading module %s: %s", MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle));
@@ -154,7 +161,7 @@ MOD_UNLOAD()
 {
 	write_tkldb();
 	freecfg();
-	SavePersistentInt(modinfo, tkls_loaded);
+	SavePersistentLong(modinfo, tkldb_next_event);
 	return MOD_SUCCESS;
 }
 
@@ -228,6 +235,9 @@ int tkldb_configrun(ConfigFile *cf, ConfigEntry *ce, int type)
 
 EVENT(write_tkldb_evt)
 {
+	if (tkldb_next_event > TStime())
+		return;
+	tkldb_next_event = TStime() + TKLDB_SAVE_EVERY;
 	write_tkldb();
 }
 
@@ -245,7 +255,7 @@ int write_tkldb(void)
 #endif
 
 	// Write to a tempfile first, then rename it if everything succeeded
-	snprintf(tmpfname, sizeof(tmpfname), "%s.tmp", cfg.database);
+	snprintf(tmpfname, sizeof(tmpfname), "%s.%x.tmp", cfg.database, getrandom32());
 	fd = fopen(tmpfname, "wb");
 	if (!fd)
 	{
@@ -253,8 +263,8 @@ int write_tkldb(void)
 		return 0;
 	}
 
-	W_SAFE(write_int32(fd, TKL_DB_MAGIC));
-	W_SAFE(write_data(fd, &tkl_db_version, sizeof(tkl_db_version)));
+	W_SAFE(write_int32(fd, TKLDB_MAGIC));
+	W_SAFE(write_data(fd, &tkldb_version, sizeof(tkldb_version)));
 
 	// Count the *-Lines
 	tklcount = 0;
@@ -432,7 +442,7 @@ int read_tkldb(void)
 
 	/* The database starts with a "magic value" - unless it's some old version or corrupt */
 	R_SAFE(read_data(fd, &magic, sizeof(magic)));
-	if (magic != TKL_DB_MAGIC)
+	if (magic != TKLDB_MAGIC)
 	{
 		config_warn("[tkldb] Database '%s' uses an old and unsupported format OR is corrupt", cfg.database);
 		config_status("If you are upgrading from UnrealIRCd 4 (or 5.0.0-alpha1) then we suggest you to "
@@ -450,10 +460,10 @@ int read_tkldb(void)
 		fclose(fd);
 		return 0;
 	}
-	if (version > tkl_db_version)
+	if (version > tkldb_version)
 	{
 		config_warn("[tkldb] Database '%s' has version %lu while we only support %lu. Did you just downgrade UnrealIRCd? Sorry this is not suported",
-			cfg.database, (unsigned long)tkl_db_version, (unsigned long)version);
+			cfg.database, (unsigned long)tkldb_version, (unsigned long)version);
 		fclose(fd);
 		return 0;
 	}
diff --git a/src/modules/websocket.c b/src/modules/websocket.c
@@ -6,7 +6,6 @@
  */
    
 #include "unrealircd.h"
-#include <limits.h>
 
 #define WEBSOCKET_VERSION "1.1.0"
 
diff --git a/src/numeric.c b/src/numeric.c
@@ -244,7 +244,7 @@ static char *replies[] = {
 #endif
 /* 213    RPL_STATSCLINE */ "%c %s * %s %d %d %s",
 /* 214    RPL_STATSOLDNLINE */ "%c %s * %s %d %d %s",
-/* 215    RPL_STATSILINE */ "I %s * %s %d %s %s %d",
+/* 215    RPL_STATSILINE */ "I %s %s %d %d %s %s %d",
 /* 216    RPL_STATSKLINE */ "%s %s %s",
 /* 217    RPL_STATSQLINE */ "%c %s %ld %ld %s :%s",
 /* 218    RPL_STATSYLINE */ "Y %s %d %d %d %d %d",
diff --git a/src/parse.c b/src/parse.c
@@ -35,6 +35,7 @@ static void remove_unknown(Client *, char *);
 static void parse2(Client *client, Client **fromptr, MessageTag *mtags, char *ch);
 static void parse_addlag(Client *client, int cmdbytes);
 static int client_lagged_up(Client *client);
+static void ban_handshake_data_flooder(Client *client);
 
 /** Put a packet in the client receive queue and process the data (if
  * the 'fake lag' rules permit doing so).
@@ -60,14 +61,13 @@ int process_packet(Client *client, char *readbuf, int length, int killsafely)
 		return 0;
 
 	/* flood from unknown connection */
-	if (IsUnknown(client) && (DBufLength(&client->local->recvQ) > UNKNOWN_FLOOD_AMOUNT*1024))
+	if (IsUnknown(client) && (DBufLength(&client->local->recvQ) > iConf.handshake_data_flood_amount))
 	{
-		sendto_snomask(SNO_FLOOD, "Flood from unknown connection %s detected",
-			client->local->sockhost);
+		sendto_snomask(SNO_FLOOD, "Handshake data flood from %s detected", client->local->sockhost);
 		if (!killsafely)
-			ban_flooder(client);
+			ban_handshake_data_flooder(client);
 		else
-			dead_socket(client, "Flood from unknown connection");
+			dead_socket(client, "Handshake data flood detected");
 		return 0;
 	}
 
@@ -105,7 +105,7 @@ void parse_client_queued(Client *client)
 		return; /* we delay processing of data until identd has replied */
 
 	if (!IsUser(client) && !IsServer(client) && (iConf.handshake_delay > 0) &&
-	    (TStime() - client->local->firsttime < iConf.handshake_delay))
+	    !IsNoHandshakeDelay(client) && (TStime() - client->local->firsttime < iConf.handshake_delay))
 	{
 		return; /* we delay processing of data until set::handshake-delay is reached */
 	}
@@ -193,11 +193,10 @@ void parse(Client *cptr, char *buffer, int length)
 	if (IsDeadSocket(cptr))
 		return;
 
-	if ((cptr->local->receiveK >= UNKNOWN_FLOOD_AMOUNT) && IsUnknown(cptr))
+	if ((cptr->local->receiveK >= iConf.handshake_data_flood_amount/1024) && IsUnknown(cptr))
 	{
-		sendto_snomask(SNO_FLOOD, "Flood from unknown connection %s detected",
-			cptr->local->sockhost);
-		ban_flooder(cptr);
+		sendto_snomask(SNO_FLOOD, "Handshake data flood from %s detected", cptr->local->sockhost);
+		ban_handshake_data_flooder(cptr);
 		return;
 	}
 
@@ -533,20 +532,20 @@ static void parse2(Client *cptr, Client **fromptr, MessageTag *mtags, char *ch)
  * Note that "lots" in terms of IRC is a few KB's, since more is rather unusual.
  * @param client The client.
  */
-void ban_flooder(Client *client)
+static void ban_handshake_data_flooder(Client *client)
 {
-	if (find_tkl_exception(TKL_UNKNOWN_DATA_FLOOD, client))
+	if (find_tkl_exception(TKL_HANDSHAKE_DATA_FLOOD, client))
 	{
 		/* If the user is exempt we will still KILL the client, since it is
 		 * clearly misbehaving. We just won't ZLINE the host, so it won't
 		 * affect any other connections from the same IP address.
 		 */
-		exit_client(client, NULL, "Flood from unknown connection");
+		exit_client(client, NULL, "Handshake data flood detected");
 	}
 	else
 	{
 		/* place_host_ban also takes care of removing any other clients with same host/ip */
-		place_host_ban(client, BAN_ACT_ZLINE, "Flood from unknown connection", UNKNOWN_FLOOD_BANTIME);
+		place_host_ban(client, iConf.handshake_data_flood_ban_action, "Handshake data flood detected", iConf.handshake_data_flood_ban_time);
 	}
 }
 
diff --git a/src/send.c b/src/send.c
@@ -1069,21 +1069,16 @@ void vsendto_prefix_one(Client *to, Client *from, MessageTag *mtags, const char 
 void sendto_connectnotice(Client *newuser, int disconnect, char *comment)
 {
 	Client *acptr;
-	char connect[512], secure[256];
+	char connect[512];
 
 	if (!disconnect)
 	{
 		RunHook(HOOKTYPE_LOCAL_CONNECT, newuser);
 
-		*secure = '\0';
-		if (IsSecure(newuser))
-			snprintf(secure, sizeof(secure), " [secure %s]", tls_get_cipher(newuser->local->ssl));
-
 		ircsnprintf(connect, sizeof(connect),
-		    "*** Client connecting: %s (%s@%s) [%s] {%s}%s", newuser->name,
+		    "*** Client connecting: %s (%s@%s) [%s] %s", newuser->name,
 		    newuser->user->username, newuser->user->realhost, newuser->ip,
-		    newuser->local->class ? newuser->local->class->name : "0",
-		    secure);
+		    get_connect_extinfo(newuser));
 	}
 	else
 	{
@@ -1101,18 +1096,14 @@ void sendto_connectnotice(Client *newuser, int disconnect, char *comment)
 void sendto_fconnectnotice(Client *newuser, int disconnect, char *comment)
 {
 	Client *acptr;
-	char connect[512], secure[256];
+	char connect[512];
 
 	if (!disconnect)
 	{
-		*secure = '\0';
-		if (IsSecureConnect(newuser))
-			strcpy(secure, " [secure]"); /* will we ever expand this? */
-
 		ircsnprintf(connect, sizeof(connect),
-		    "*** Client connecting: %s (%s@%s) [%s] {0}%s", newuser->name,
+		    "*** Client connecting: %s (%s@%s) [%s] %s", newuser->name,
 		    newuser->user->username, newuser->user->realhost, newuser->ip ? newuser->ip : "0",
-		    secure);
+		    get_connect_extinfo(newuser));
 	}
 	else
 	{
diff --git a/src/socket.c b/src/socket.c
@@ -703,10 +703,7 @@ void set_ipv6_opts(int fd)
 }
 
 /** This sets the *OS* socket buffers.
- * Note that setting these high is not always a good idea.
- * For example for regular users we keep the receive buffer tight
- * so we detect a high receive queue (Excess Flood) properly.
- * See include/fdlist.h for more information
+ * This shouldn't be needed anymore, but I've left the function here.
  */
 void set_socket_buffers(int fd, int rcvbuf, int sndbuf)
 {
@@ -726,17 +723,24 @@ void set_sock_opts(int fd, Client *client, int ipv6)
 
 	if (ipv6)
 		set_ipv6_opts(fd);
+
 #ifdef SO_REUSEADDR
 	opt = 1;
 	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(opt)) < 0)
 			report_error("setsockopt(SO_REUSEADDR) %s:%s", client);
 #endif
+
 #if defined(SO_USELOOPBACK) && !defined(_WIN32)
 	opt = 1;
 	if (setsockopt(fd, SOL_SOCKET, SO_USELOOPBACK, (void *)&opt, sizeof(opt)) < 0)
 		report_error("setsockopt(SO_USELOOPBACK) %s:%s", client);
 #endif
-	set_socket_buffers(fd, USER_SOCKET_RECEIVE_BUFFER, USER_SOCKET_SEND_BUFFER);
+
+	/* Previously we also called set_socket_buffers() to set some
+	 * specific buffer limits. This is no longer needed on modern OS's.
+	 * Setting it explicitly actually slows things down.
+	 */
+
 	/* Set to non blocking: */
 #if !defined(_WIN32)
 	if ((opt = fcntl(fd, F_GETFL, 0)) == -1)
@@ -1105,8 +1109,10 @@ void read_packet(int fd, int revents, void *data)
 		for (h = Hooks[HOOKTYPE_RAWPACKET_IN]; h; h = h->next)
 		{
 			processdata = (*(h->func.intfunc))(client, readbuf, &length);
+			if (processdata == 0)
+				break; /* if hook tells to ignore the data, then break now */
 			if (processdata < 0)
-				return;
+				return; /* if hook tells client is dead, return now */
 		}
 
 		if (processdata && !process_packet(client, readbuf, length, 0))
diff --git a/src/support.c b/src/support.c
@@ -1293,3 +1293,17 @@ int get_terminal_width(void)
 	return w.ws_col;
 #endif
 }
+
+/** Like strftime() but easier. */
+char *unreal_strftime(char *str)
+{
+	time_t t;
+	struct tm *tmp;
+	static char buf[512];
+
+	t = time(NULL);
+	tmp = localtime(&t);
+	if (!tmp || !strftime(buf, sizeof(buf), str, tmp))
+		return str;
+	return buf;
+}
diff --git a/src/user.c b/src/user.c
@@ -872,3 +872,50 @@ int user_allowed_by_security_group_name(Client *client, char *secgroupname)
 		return 0; /* security group not found: no match */
 	return user_allowed_by_security_group(client, s);
 }
+
+/** Return extended information about user for the "Client connecting" line.
+ * @returns A string such as "[secure] [reputation: 5]", never returns NULL.
+ */
+char *get_connect_extinfo(Client *client)
+{
+	static char retbuf[512];
+	char tmp[512];
+	NameValuePrioList *list = NULL, *e;
+
+	/* From modules... */
+	RunHook2(HOOKTYPE_CONNECT_EXTINFO, client, &list);
+
+	/* And some built-in: */
+
+	/* "class": this should be first */
+	if (MyUser(client) && client->local->class)
+		add_nvplist(&list, -100000, "class", client->local->class->name);
+
+	/* "secure": SSL/TLS */
+	if (MyUser(client) && IsSecure(client))
+		add_nvplist(&list, -1000, "secure", tls_get_cipher(client->local->ssl));
+	else if (!MyUser(client) && IsSecureConnect(client))
+		add_nvplist(&list, -1000, "secure", NULL);
+
+	/* services account? */
+	if (IsLoggedIn(client))
+		add_nvplist(&list, -500, "account", client->user->svid);
+
+	*retbuf = '\0';
+	for (e = list; e; e = e->next)
+	{
+		if (e->value)
+			snprintf(tmp, sizeof(tmp), "[%s: %s] ", e->name, e->value);
+		else
+			snprintf(tmp, sizeof(tmp), "[%s] ", e->name);
+		strlcat(retbuf, tmp, sizeof(retbuf));
+	}
+	/* Cut off last space (unless empty string) */
+	if (*buf)
+		buf[strlen(buf)-1] = '\0';
+
+	/* Free the list, as it was only used to build retbuf */
+	free_nvplist(list);
+
+	return retbuf;
+}
diff --git a/src/version.c.SH b/src/version.c.SH
@@ -4,7 +4,7 @@ echo "Extracting src/version.c..."
 
 #id=`grep '$Id: Changes,v' ../Changes`
 #id=`echo $id |sed 's/.* Changes\,v \(.*\) .* Exp .*/\1/'`
-id="5.0.8"
+id="5.0.9"
 echo "$id"
 
 if test -r version.c
diff --git a/src/windows/UnrealIRCd.exe.manifest b/src/windows/UnrealIRCd.exe.manifest
@@ -3,7 +3,7 @@
 <assemblyIdentity
     processorArchitecture="amd64"
     name="UnrealIRCd.UnrealIRCd.5"
-    version="5.0.8.0"
+    version="5.0.9.0"
     type="win32"
 />
 <description>Internet Relay Chat Daemon</description>
diff --git a/src/windows/gui.c b/src/windows/gui.c
@@ -1034,6 +1034,7 @@ void win_log(FORMAT_STRING(const char *format), ...)
 	va_start(ap, format);
 
 	ircvsnprintf(buf, sizeof(buf), format, ap);
+	stripcrlf(buf);
 
 	if (!IsService) 
 	{
@@ -1043,6 +1044,7 @@ void win_log(FORMAT_STRING(const char *format), ...)
 			char *tbuf = safe_alloc(strlen(errors) + strlen(buf) + 1);
 			strcpy(tbuf, errors);
 			strcat(tbuf, buf);
+			safe_free(errors);
 			errors = tbuf;
 		}
 		else 
diff --git a/src/windows/unrealinst.iss b/src/windows/unrealinst.iss
@@ -6,7 +6,7 @@
 
 [Setup]
 AppName=UnrealIRCd 5
-AppVerName=UnrealIRCd 5.0.8
+AppVerName=UnrealIRCd 5.0.9
 AppPublisher=UnrealIRCd Team
 AppPublisherURL=https://www.unrealircd.org
 AppSupportURL=https://www.unrealircd.org
diff --git a/src/windows/unrealsvc.c b/src/windows/unrealsvc.c
@@ -1,6 +1,7 @@
 /************************************************************************
- *   IRC - Internet Relay Chat, windows/unreal.c
+ *   IRC - Internet Relay Chat, windows/unrealsvc.c
  *   Copyright (C) 2002 Dominick Meglio (codemastr)
+ *   Copyright (C) 2006-2021 Bram Matthys (Syzop)
  *   
  *   This program is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -25,7 +26,7 @@ UCHANGESERVICECONFIG2 uChangeServiceConfig2;
 
 #define IRCD_SERVICE_CONTROL_REHASH 128
 void show_usage() {
-	fprintf(stderr, "unreal start|stop|rehash|restart|install|uninstall|config <option> <value>");
+	fprintf(stderr, "unrealsvc start|stop|rehash|restart|install|uninstall|config <option> <value>");
 	fprintf(stderr, "\nValid config options:\nstartup auto|manual\n");
 	fprintf(stderr, "crashrestart delay\n");
 }
diff --git a/unrealircd.in b/unrealircd.in
@@ -286,6 +286,8 @@ elif [ "$1" = "hot-patch" -o "$1" = "cold-patch" ] ; then
 	else
 		echo "Patch applied successfully. You must now restart your IRC server."
 	fi
+elif [ "$1" = "upgrade" ] ; then
+	@BINDIR@/unrealircd-upgrade-script $*
 elif [ "$1" = "genlinkblock" ] ; then
 	@BINDIR@/unrealircd -L
 else
@@ -298,15 +300,17 @@ else
 	echo "unrealircd start         Start the IRC Server"
 	echo "unrealircd stop          Stop (kill) the IRC Server"
 	echo "unrealircd rehash        Reload the configuration file"
-	echo "unrealircd reloadtls     Reload the SSL/TLS certificate and settings"
+	echo "unrealircd reloadtls     Reload the SSL/TLS certificates"
 	echo "unrealircd restart       Restart the IRC Server (stop+start)"
+	echo "unrealircd upgrade       Upgrade UnrealIRCd to the latest version"
+	echo "unrealircd upgrade-conf  Upgrade the configuration file from UnrealIRCd"
+	echo "                         3.2.x/4.x to 5.x format"
 	echo "unrealircd mkpasswd      Hash a password"
 	echo "unrealircd version       Display the UnrealIRCd version"
 	echo "unrealircd module        Install and uninstall 3rd party modules"
 	echo "unrealircd croncheck     For use in crontab: this checks if the server"
 	echo "                         is running. If not, the server is started."
+	echo "unrealircd genlinkblock  Generate link { } block for the other side."
 	echo "unrealircd gencloak      Display 3 random cloak keys"
 	echo "unrealircd spkifp        Display SPKI Fingerprint"
-	echo "unrealircd upgrade-conf  Upgrade the configuration file from UnrealIRCd"
-	echo "                         3.2.x/4.x to 5.x format"
 fi