[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#985759: unblock: mosquitto/2.0.9-1



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Please unblock package mosquitto

[ Reason ]
Mosquitto 2.0.8 is currently in testing, Mosquitto 2.0.9 was released on
2021-03-11 and has sufficiently important fixes in it that I believe
should be in a Debian release.

The full debdiff is 1110 lines. If I reduce that to code-only changes it
drops to 387 (the remainder are documentation and extra tests), with
about 150 lines of actual affected code. It is a small bugfix release
with low risk but some reasonably important fixes.

[ Impact ]
I have listed the fixes below that I think are worth mentioning. The
other changes are of minor impact or are fixing strict compiler
warnings.

Client and library: There is a fairly minor security issue that affects
outgoing client connections only - if an empty or corrupt CA certificate
is provided to a client, then the initial connection would fail but
subsequent connections would succeed without verifying the remote server
certificate. There is a new test for this behaviour, but it is not in
the 2.0.9 release.

Build: The CMake build script was not enabling epoll(), so poll() was
being used instead which has a very detrimental impact on performance.

Server: Messages published with QoS 0 were not being delivered when
`max_queued_bytes` was configured. This has a big impact on users
wanting to use QoS 0, which is the most common QoS, but also set some
client limits. There is a new test to check this behaviour.

Server: If the `max_keepalive` option was set, this did not apply to
clients connecting with keepalive set to 0 (which means "infinite keepalive").
This gives a very straightforward means to circumvent the wishes of the
server operator, although in itself it isn't very important.

Server: The behaviour setting acceptable TLS versions did not match the
documentation.

Server: Messages to '$' prefixed MQTT topics were being rejected. This
is not security critical but very annoying for a user wanting to use
that feature.

[ Tests ]
The release introduces a new test that covers one issue. A test
exists for the CA issue but is not part of this release.

[ Risks ]
I believe this to be low risk. Most of the code changes are reasonably
simple.

shairport-sync, kamailio-mqtt-module, and baresip-core depend on
libmosquitto1. The changes to the library code are trivial.

[ Checklist ]
  [x] all changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in testing

[ Other info ]
mosquitto_2.0.8-mosquitto-2.0.9.debdiff is the full debdiff.
mosquitto_2.0.8-mosquitto-2.0.9-code.debdiff is the code only debdiff.

unblock mosquitto/2.0.9-1

-- System Information:
Debian Release: bullseye/sid
  APT prefers focal-updates
  APT policy: (500, 'focal-updates'), (500, 'focal-security'), (500, 'focal-proposed'), (500, 'focal'), (100, 'focal-backports')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 5.4.0-48-generic (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
diff -Nru mosquitto-2.0.8/ChangeLog.txt mosquitto-2.0.9/ChangeLog.txt
--- mosquitto-2.0.8/ChangeLog.txt	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/ChangeLog.txt	2021-03-11 22:37:20.000000000 +0000
@@ -1,3 +1,39 @@
+2.0.9 - 2021-03-11
+==================
+
+Security:
+- If an empty or invalid CA file was provided to the client library for
+  verifying the remote broker, then the initial connection would fail but
+  subsequent connections would succeed without verifying the remote broker
+  certificate. Closes #2130.
+- If an empty or invalid CA file was provided to the broker for verifying the
+  remote broker for an outgoing bridge connection then the initial connection
+  would fail but subsequent connections would succeed without verifying the
+  remote broker certificate. Closes #2130.
+
+Broker:
+- Fix encrypted bridge connections incorrectly connecting when `bridge_cafile`
+  is empty or invalid. Closes #2130.
+- Fix `tls_version` behaviour not matching documentation. It was setting the
+  exact TLS version to use, not the minimium TLS version to use. Closes #2110.
+- Fix messages to `$` prefixed topics being rejected. Closes #2111.
+- Fix QoS 0 messages not being delivered when max_queued_bytes was configured.
+  Closes #2123.
+- Fix bridge increasing backoff calculation.
+- Improve handling of invalid combinations of listener address and bind
+  interface configurations. Closes #2081.
+- Fix `max_keepalive` option not applying to clients connecting with keepalive
+  set to 0. Closes #2117.
+
+Client library:
+- Fix encrypted connections incorrectly connecting when the CA file passed to
+  `mosquitto_tls_set()` is empty or invalid. Closes #2130.
+- Fix connections retrying very rapidly in some situations.
+
+Build:
+- Fix cmake epoll detection.
+
+
 2.0.8 - 2021-02-25
 ==================
 
diff -Nru mosquitto-2.0.8/CMakeLists.txt mosquitto-2.0.9/CMakeLists.txt
--- mosquitto-2.0.8/CMakeLists.txt	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/CMakeLists.txt	2021-03-11 22:37:20.000000000 +0000
@@ -8,7 +8,7 @@
 cmake_policy(SET CMP0042 NEW)
 
 project(mosquitto)
-set (VERSION 2.0.8)
+set (VERSION 2.0.9)
 
 list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/")
 
diff -Nru mosquitto-2.0.8/config.mk mosquitto-2.0.9/config.mk
--- mosquitto-2.0.8/config.mk	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/config.mk	2021-03-11 22:37:20.000000000 +0000
@@ -127,7 +127,7 @@
 
 # Also bump lib/mosquitto.h, CMakeLists.txt,
 # installer/mosquitto.nsi, installer/mosquitto64.nsi
-VERSION=2.0.8
+VERSION=2.0.9
 
 # Client library SO version. Bump if incompatible API/ABI changes are made.
 SOVERSION=1
diff -Nru mosquitto-2.0.8/debian/changelog mosquitto-2.0.9/debian/changelog
--- mosquitto-2.0.8/debian/changelog	2021-02-25 18:56:57.000000000 +0000
+++ mosquitto-2.0.9/debian/changelog	2021-03-11 22:53:34.000000000 +0000
@@ -1,3 +1,9 @@
+mosquitto (2.0.9-1) unstable; urgency=medium
+
+  * New upstream release.
+
+ -- Roger A. Light <roger@atchoo.org>  Thu, 11 Mar 2021 22:53:34 +0000
+
 mosquitto (2.0.8-1) unstable; urgency=medium
 
   * New upstream release.
diff -Nru mosquitto-2.0.8/debian/control mosquitto-2.0.9/debian/control
--- mosquitto-2.0.8/debian/control	2021-02-25 18:56:53.000000000 +0000
+++ mosquitto-2.0.9/debian/control	2021-03-11 22:53:28.000000000 +0000
@@ -11,7 +11,7 @@
                libwebsockets-dev,
                libwrap0-dev,
                pkg-config,
-               uthash-dev (>=2.1.0),
+               uthash-dev,
                xsltproc,
                docbook-xsl
 Standards-Version: 4.5.0
diff -Nru mosquitto-2.0.8/include/mosquitto.h mosquitto-2.0.9/include/mosquitto.h
--- mosquitto-2.0.8/include/mosquitto.h	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/include/mosquitto.h	2021-03-11 22:37:20.000000000 +0000
@@ -66,7 +66,7 @@
 
 #define LIBMOSQUITTO_MAJOR 2
 #define LIBMOSQUITTO_MINOR 0
-#define LIBMOSQUITTO_REVISION 8
+#define LIBMOSQUITTO_REVISION 9
 /* LIBMOSQUITTO_VERSION_NUMBER looks like 1002001 for e.g. version 1.2.1. */
 #define LIBMOSQUITTO_VERSION_NUMBER (LIBMOSQUITTO_MAJOR*1000000+LIBMOSQUITTO_MINOR*1000+LIBMOSQUITTO_REVISION)
 
@@ -1605,40 +1605,6 @@
 libmosq_EXPORT int mosquitto_void_option(struct mosquitto *mosq, enum mosq_opt_t option, void *value);
 
 /*
- * Function: mosquitto_string_option
- *
- * Used to set const char* options for the client.
- *
- * Parameters:
- *	mosq -   a valid mosquitto instance.
- *	option - the option to set.
- *	value -  the option specific value.
- *
- * Options:
- *	MOSQ_OPT_TLS_ENGINE
- *	          Configure the client for TLS Engine support. Pass a TLS Engine ID
- *	          to be used when creating TLS connections.
- *	          Must be set before <mosquitto_connect>.
- *	MOSQ_OPT_TLS_KEYFORM
- *            Configure the client to treat the keyfile differently depending
- *            on its type.  Must be set before <mosquitto_connect>.
- *	          Set as either "pem" or "engine", to determine from where the
- *	          private key for a TLS connection will be obtained. Defaults to
- *	          "pem", a normal private key file.
- *	MOSQ_OPT_TLS_KPASS_SHA1
- *	          Where the TLS Engine requires the use of a password to be
- *	          accessed, this option allows a hex encoded SHA1 hash of the
- *	          private key password to be passed to the engine directly.
- *	          Must be set before <mosquitto_connect>.
- *	MOSQ_OPT_TLS_ALPN
- *	          If the broker being connected to has multiple services available
- *	          on a single TLS port, such as both MQTT and WebSockets, use this
- *	          option to configure the ALPN option for the connection.
- */
-libmosq_EXPORT int mosquitto_string_option(struct mosquitto *mosq, enum mosq_opt_t option, const char *value);
-
-
-/*
  * Function: mosquitto_reconnect_delay_set
  *
  * Control the behaviour of the client when it has unexpectedly disconnected in
diff -Nru mosquitto-2.0.8/installer/mosquitto64.nsi mosquitto-2.0.9/installer/mosquitto64.nsi
--- mosquitto-2.0.8/installer/mosquitto64.nsi	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/installer/mosquitto64.nsi	2021-03-11 22:37:20.000000000 +0000
@@ -9,7 +9,7 @@
 !define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
 
 Name "Eclipse Mosquitto"
-!define VERSION 2.0.8
+!define VERSION 2.0.9
 OutFile "mosquitto-${VERSION}-install-windows-x64.exe"
 
 !include "x64.nsh"
diff -Nru mosquitto-2.0.8/installer/mosquitto.nsi mosquitto-2.0.9/installer/mosquitto.nsi
--- mosquitto-2.0.8/installer/mosquitto.nsi	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/installer/mosquitto.nsi	2021-03-11 22:37:20.000000000 +0000
@@ -9,7 +9,7 @@
 !define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
 
 Name "Eclipse Mosquitto"
-!define VERSION 2.0.8
+!define VERSION 2.0.9
 OutFile "mosquitto-${VERSION}-install-windows-x86.exe"
 
 InstallDir "$PROGRAMFILES\mosquitto"
diff -Nru mosquitto-2.0.8/lib/loop.c mosquitto-2.0.9/lib/loop.c
--- mosquitto-2.0.8/lib/loop.c	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/lib/loop.c	2021-03-11 22:37:20.000000000 +0000
@@ -203,6 +203,13 @@
 	char pairbuf;
 	int maxfd = 0;
 
+#ifndef WIN32
+	if(read(mosq->sockpairR, &pairbuf, 1) == 0){
+	}
+#else
+	recv(mosq->sockpairR, &pairbuf, 1, 0);
+#endif
+
 	local_timeout.tv_sec = reconnect_delay;
 #ifdef HAVE_PSELECT
 	local_timeout.tv_nsec = 0;
diff -Nru mosquitto-2.0.8/lib/mosquitto.c mosquitto-2.0.9/lib/mosquitto.c
--- mosquitto-2.0.8/lib/mosquitto.c	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/lib/mosquitto.c	2021-03-11 22:37:20.000000000 +0000
@@ -196,6 +196,7 @@
 #ifdef WITH_TLS
 	mosq->ssl = NULL;
 	mosq->ssl_ctx = NULL;
+	mosq->ssl_ctx_defaults = true;
 	mosq->tls_cert_reqs = SSL_VERIFY_PEER;
 	mosq->tls_insecure = false;
 	mosq->want_write = false;
diff -Nru mosquitto-2.0.8/lib/mosquitto_internal.h mosquitto-2.0.9/lib/mosquitto_internal.h
--- mosquitto-2.0.8/lib/mosquitto_internal.h	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/lib/mosquitto_internal.h	2021-03-11 22:37:20.000000000 +0000
@@ -190,8 +190,8 @@
 #ifdef WITH_BROKER
 	struct mosquitto_client_msg *inflight;
 	struct mosquitto_client_msg *queued;
-	unsigned long msg_bytes;
-	unsigned long msg_bytes12;
+	long msg_bytes;
+	long msg_bytes12;
 	int msg_count;
 	int msg_count12;
 #else
diff -Nru mosquitto-2.0.8/man/libmosquitto.3 mosquitto-2.0.9/man/libmosquitto.3
--- mosquitto-2.0.8/man/libmosquitto.3	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/man/libmosquitto.3	2021-03-11 22:37:20.000000000 +0000
@@ -1,13 +1,13 @@
 '\" t
 .\"     Title: libmosquitto
 .\"    Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/25/2021
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\"      Date: 03/11/2021
 .\"    Manual: Library calls
 .\"    Source: Mosquitto Project
 .\"  Language: English
 .\"
-.TH "LIBMOSQUITTO" "3" "02/25/2021" "Mosquitto Project" "Library calls"
+.TH "LIBMOSQUITTO" "3" "03/11/2021" "Mosquitto Project" "Library calls"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru mosquitto-2.0.8/man/mosquitto.8 mosquitto-2.0.9/man/mosquitto.8
--- mosquitto-2.0.8/man/mosquitto.8	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/man/mosquitto.8	2021-03-11 22:37:20.000000000 +0000
@@ -1,13 +1,13 @@
 '\" t
 .\"     Title: mosquitto
 .\"    Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/25/2021
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\"      Date: 03/11/2021
 .\"    Manual: System management commands
 .\"    Source: Mosquitto Project
 .\"  Language: English
 .\"
-.TH "MOSQUITTO" "8" "02/25/2021" "Mosquitto Project" "System management commands"
+.TH "MOSQUITTO" "8" "03/11/2021" "Mosquitto Project" "System management commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru mosquitto-2.0.8/man/mosquitto.conf.5 mosquitto-2.0.9/man/mosquitto.conf.5
--- mosquitto-2.0.8/man/mosquitto.conf.5	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/man/mosquitto.conf.5	2021-03-11 22:37:20.000000000 +0000
@@ -1,13 +1,13 @@
 '\" t
 .\"     Title: mosquitto.conf
 .\"    Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/25/2021
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\"      Date: 03/11/2021
 .\"    Manual: File formats and conventions
 .\"    Source: Mosquitto Project
 .\"  Language: English
 .\"
-.TH "MOSQUITTO\&.CONF" "5" "02/25/2021" "Mosquitto Project" "File formats and conventions"
+.TH "MOSQUITTO\&.CONF" "5" "03/11/2021" "Mosquitto Project" "File formats and conventions"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru mosquitto-2.0.8/man/mosquitto_ctrl.1 mosquitto-2.0.9/man/mosquitto_ctrl.1
--- mosquitto-2.0.8/man/mosquitto_ctrl.1	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/man/mosquitto_ctrl.1	2021-03-11 22:37:20.000000000 +0000
@@ -1,13 +1,13 @@
 '\" t
 .\"     Title: mosquitto_ctrl
 .\"    Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/25/2021
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\"      Date: 03/11/2021
 .\"    Manual: Commands
 .\"    Source: Mosquitto Project
 .\"  Language: English
 .\"
-.TH "MOSQUITTO_CTRL" "1" "02/25/2021" "Mosquitto Project" "Commands"
+.TH "MOSQUITTO_CTRL" "1" "03/11/2021" "Mosquitto Project" "Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru mosquitto-2.0.8/man/mosquitto_ctrl_dynsec.1 mosquitto-2.0.9/man/mosquitto_ctrl_dynsec.1
--- mosquitto-2.0.8/man/mosquitto_ctrl_dynsec.1	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/man/mosquitto_ctrl_dynsec.1	2021-03-11 22:37:20.000000000 +0000
@@ -1,13 +1,13 @@
 '\" t
 .\"     Title: mosquitto_ctrl_dynsec
 .\"    Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/25/2021
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\"      Date: 03/11/2021
 .\"    Manual: Commands
 .\"    Source: Mosquitto Project
 .\"  Language: English
 .\"
-.TH "MOSQUITTO_CTRL_DYNSE" "1" "02/25/2021" "Mosquitto Project" "Commands"
+.TH "MOSQUITTO_CTRL_DYNSE" "1" "03/11/2021" "Mosquitto Project" "Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru mosquitto-2.0.8/man/mosquitto_passwd.1 mosquitto-2.0.9/man/mosquitto_passwd.1
--- mosquitto-2.0.8/man/mosquitto_passwd.1	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/man/mosquitto_passwd.1	2021-03-11 22:37:20.000000000 +0000
@@ -1,13 +1,13 @@
 '\" t
 .\"     Title: mosquitto_passwd
 .\"    Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/25/2021
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\"      Date: 03/11/2021
 .\"    Manual: Commands
 .\"    Source: Mosquitto Project
 .\"  Language: English
 .\"
-.TH "MOSQUITTO_PASSWD" "1" "02/25/2021" "Mosquitto Project" "Commands"
+.TH "MOSQUITTO_PASSWD" "1" "03/11/2021" "Mosquitto Project" "Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru mosquitto-2.0.8/man/mosquitto_pub.1 mosquitto-2.0.9/man/mosquitto_pub.1
--- mosquitto-2.0.8/man/mosquitto_pub.1	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/man/mosquitto_pub.1	2021-03-11 22:37:20.000000000 +0000
@@ -1,13 +1,13 @@
 '\" t
 .\"     Title: mosquitto_pub
 .\"    Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/25/2021
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\"      Date: 03/11/2021
 .\"    Manual: Commands
 .\"    Source: Mosquitto Project
 .\"  Language: English
 .\"
-.TH "MOSQUITTO_PUB" "1" "02/25/2021" "Mosquitto Project" "Commands"
+.TH "MOSQUITTO_PUB" "1" "03/11/2021" "Mosquitto Project" "Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru mosquitto-2.0.8/man/mosquitto_rr.1 mosquitto-2.0.9/man/mosquitto_rr.1
--- mosquitto-2.0.8/man/mosquitto_rr.1	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/man/mosquitto_rr.1	2021-03-11 22:37:20.000000000 +0000
@@ -1,13 +1,13 @@
 '\" t
 .\"     Title: mosquitto_rr
 .\"    Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/25/2021
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\"      Date: 03/11/2021
 .\"    Manual: Commands
 .\"    Source: Mosquitto Project
 .\"  Language: English
 .\"
-.TH "MOSQUITTO_RR" "1" "02/25/2021" "Mosquitto Project" "Commands"
+.TH "MOSQUITTO_RR" "1" "03/11/2021" "Mosquitto Project" "Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -437,7 +437,7 @@
 \fBmqttv5\fR,
 \fBmqttv311\fR, or
 \fBmqttv31\fR\&. Defaults to
-\fB311\fR\&.
+\fB5\fR\&.
 .RE
 .PP
 \fB\-\-will\-payload\fR
diff -Nru mosquitto-2.0.8/man/mosquitto_rr.1.xml mosquitto-2.0.9/man/mosquitto_rr.1.xml
--- mosquitto-2.0.8/man/mosquitto_rr.1.xml	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/man/mosquitto_rr.1.xml	2021-03-11 22:37:20.000000000 +0000
@@ -632,7 +632,7 @@
 						<option>31</option>, or the more verbose
 						<option>mqttv5</option>, <option>mqttv311</option>, or
 						<option>mqttv31</option>.
-						Defaults to <option>311</option>.</para>
+						Defaults to <option>5</option>.</para>
 				</listitem>
 			</varlistentry>
 			<varlistentry>
diff -Nru mosquitto-2.0.8/man/mosquitto_sub.1 mosquitto-2.0.9/man/mosquitto_sub.1
--- mosquitto-2.0.8/man/mosquitto_sub.1	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/man/mosquitto_sub.1	2021-03-11 22:37:20.000000000 +0000
@@ -1,13 +1,13 @@
 '\" t
 .\"     Title: mosquitto_sub
 .\"    Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/25/2021
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\"      Date: 03/11/2021
 .\"    Manual: Commands
 .\"    Source: Mosquitto Project
 .\"  Language: English
 .\"
-.TH "MOSQUITTO_SUB" "1" "02/25/2021" "Mosquitto Project" "Commands"
+.TH "MOSQUITTO_SUB" "1" "03/11/2021" "Mosquitto Project" "Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru mosquitto-2.0.8/man/mosquitto-tls.7 mosquitto-2.0.9/man/mosquitto-tls.7
--- mosquitto-2.0.8/man/mosquitto-tls.7	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/man/mosquitto-tls.7	2021-03-11 22:37:20.000000000 +0000
@@ -1,13 +1,13 @@
 '\" t
 .\"     Title: mosquitto-tls
 .\"    Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/25/2021
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\"      Date: 03/11/2021
 .\"    Manual: Conventions and miscellaneous
 .\"    Source: Mosquitto Project
 .\"  Language: English
 .\"
-.TH "MOSQUITTO\-TLS" "7" "02/25/2021" "Mosquitto Project" "Conventions and miscellaneous"
+.TH "MOSQUITTO\-TLS" "7" "03/11/2021" "Mosquitto Project" "Conventions and miscellaneous"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru mosquitto-2.0.8/man/mqtt.7 mosquitto-2.0.9/man/mqtt.7
--- mosquitto-2.0.8/man/mqtt.7	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/man/mqtt.7	2021-03-11 22:37:20.000000000 +0000
@@ -1,13 +1,13 @@
 '\" t
 .\"     Title: mqtt
 .\"    Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/25/2021
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\"      Date: 03/11/2021
 .\"    Manual: Conventions and miscellaneous
 .\"    Source: Mosquitto Project
 .\"  Language: English
 .\"
-.TH "MQTT" "7" "02/25/2021" "Mosquitto Project" "Conventions and miscellaneous"
+.TH "MQTT" "7" "03/11/2021" "Mosquitto Project" "Conventions and miscellaneous"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru mosquitto-2.0.8/snap/snapcraft.yaml mosquitto-2.0.9/snap/snapcraft.yaml
--- mosquitto-2.0.8/snap/snapcraft.yaml	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/snap/snapcraft.yaml	2021-03-11 22:37:20.000000000 +0000
@@ -1,5 +1,5 @@
 name: mosquitto
-version: 2.0.8
+version: 2.0.9
 summary: Eclipse Mosquitto MQTT broker
 description: This is a message broker that supports version 5.0, 3.1.1, and 3.1 of the MQTT
     protocol.
diff -Nru mosquitto-2.0.8/src/bridge.c mosquitto-2.0.9/src/bridge.c
--- mosquitto-2.0.8/src/bridge.c	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/src/bridge.c	2021-03-11 22:37:20.000000000 +0000
@@ -112,6 +112,7 @@
 	new_context->tls_alpn = new_context->bridge->tls_alpn;
 	new_context->tls_engine = db.config->default_listener.tls_engine;
 	new_context->tls_keyform = db.config->default_listener.tls_keyform;
+	new_context->ssl_ctx_defaults = true;
 #ifdef FINAL_WITH_TLS_PSK
 	new_context->tls_psk_identity = new_context->bridge->tls_psk_identity;
 	new_context->tls_psk = new_context->bridge->tls_psk;
@@ -313,10 +314,8 @@
 
 	rc = send__connect(context, context->keepalive, context->clean_start, NULL);
 	if(rc == MOSQ_ERR_SUCCESS){
-		bridge__backoff_reset(context);
 		return MOSQ_ERR_SUCCESS;
 	}else if(rc == MOSQ_ERR_ERRNO && errno == ENOTCONN){
-		bridge__backoff_reset(context);
 		return MOSQ_ERR_SUCCESS;
 	}else{
 		if(rc == MOSQ_ERR_TLS){
@@ -454,10 +453,8 @@
 
 	rc2 = send__connect(context, context->keepalive, context->clean_start, NULL);
 	if(rc2 == MOSQ_ERR_SUCCESS){
-		bridge__backoff_reset(context);
 		return rc;
 	}else if(rc2 == MOSQ_ERR_ERRNO && errno == ENOTCONN){
-		bridge__backoff_reset(context);
 		return MOSQ_ERR_SUCCESS;
 	}else{
 		if(rc2 == MOSQ_ERR_TLS){
@@ -562,6 +559,8 @@
 		}
 	}
 
+	bridge__backoff_reset(context);
+
 	return MOSQ_ERR_SUCCESS;
 }
 
@@ -646,11 +645,11 @@
 	packet__cleanup(&(context->in_packet));
 }
 
-static int rand_between(int base, int cap)
+static int rand_between(int low, int high)
 {
 	int r;
 	util__random_bytes(&r, sizeof(int));
-	return (r % (cap - base)) + base;
+	return (abs(r) % (high - low)) + low;
 }
 
 static void bridge__backoff_step(struct mosquitto *context)
@@ -685,6 +684,33 @@
 	}
 }
 
+
+static void bridge_check_pending(struct mosquitto *context)
+{
+	int err;
+	socklen_t len;
+
+	if(context->state == mosq_cs_connect_pending){
+		len = sizeof(int);
+		if(!getsockopt(context->sock, SOL_SOCKET, SO_ERROR, (char *)&err, &len)){
+			if(err == 0){
+				mosquitto__set_state(context, mosq_cs_new);
+#if defined(WITH_ADNS) && defined(WITH_BRIDGE)
+				if(context->bridge){
+					bridge__connect_step3(context);
+				}
+#endif
+			}else if(err == ECONNREFUSED){
+				do_disconnect(context, MOSQ_ERR_CONN_LOST);
+				return;
+			}
+		}else{
+			do_disconnect(context, MOSQ_ERR_CONN_LOST);
+			return;
+		}
+	}
+}
+
 void bridge_check(void)
 {
 	static time_t last_check = 0;
@@ -703,6 +729,7 @@
 
 		if(context->sock != INVALID_SOCKET){
 			mosquitto__check_keepalive(context);
+			bridge_check_pending(context);
 
 			/* Check for bridges that are not round robin and not currently
 			 * connected to their primary broker. */
diff -Nru mosquitto-2.0.8/src/CMakeLists.txt mosquitto-2.0.9/src/CMakeLists.txt
--- mosquitto-2.0.8/src/CMakeLists.txt	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/src/CMakeLists.txt	2021-03-11 22:37:20.000000000 +0000
@@ -77,6 +77,11 @@
 	include_directories(${mosquitto_SOURCE_DIR} ${mosquitto_SOURCE_DIR}/deps)
 endif (WITH_BUNDLED_DEPS)
 
+find_path(HAVE_SYS_EPOLL_H sys/epoll.h)
+if (HAVE_SYS_EPOLL_H)
+	add_definitions("-DWITH_EPOLL")
+endif()
+
 option(INC_BRIDGE_SUPPORT
 	"Include bridge support for connecting to other brokers?" ON)
 if (INC_BRIDGE_SUPPORT)
diff -Nru mosquitto-2.0.8/src/database.c mosquitto-2.0.9/src/database.c
--- mosquitto-2.0.8/src/database.c	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/src/database.c	2021-03-11 22:37:20.000000000 +0000
@@ -53,7 +53,7 @@
 		if(db.config->max_queued_messages == 0 && db.config->max_inflight_bytes == 0){
 			return true;
 		}
-		valid_bytes = msgs->msg_bytes - db.config->max_inflight_bytes < db.config->max_queued_bytes;
+		valid_bytes = ((msgs->msg_bytes - (ssize_t)db.config->max_inflight_bytes) < (ssize_t)db.config->max_queued_bytes);
 		valid_count = msgs->msg_count - msgs->inflight_maximum < db.config->max_queued_messages;
 
 		if(db.config->max_queued_messages == 0){
@@ -90,8 +90,8 @@
 {
 	int source_count;
 	int adjust_count;
-	size_t source_bytes;
-	size_t adjust_bytes = db.config->max_inflight_bytes;
+	long source_bytes;
+	ssize_t adjust_bytes = (ssize_t)db.config->max_inflight_bytes;
 	bool valid_bytes;
 	bool valid_count;
 
@@ -893,6 +893,26 @@
 }
 
 
+int db__message_remove_incoming(struct mosquitto* context, uint16_t mid)
+{
+	struct mosquitto_client_msg *tail, *tmp;
+
+	if(!context) return MOSQ_ERR_INVAL;
+
+	DL_FOREACH_SAFE(context->msgs_in.inflight, tail, tmp){
+		if(tail->mid == mid) {
+			if(tail->store->qos != 2){
+				return MOSQ_ERR_PROTOCOL;
+			}
+			db__message_remove(&context->msgs_in, tail);
+			return MOSQ_ERR_SUCCESS;
+		}
+	}
+
+	return MOSQ_ERR_NOT_FOUND;
+}
+
+
 int db__message_release_incoming(struct mosquitto *context, uint16_t mid)
 {
 	struct mosquitto_client_msg *tail, *tmp;
diff -Nru mosquitto-2.0.8/src/handle_connect.c mosquitto-2.0.9/src/handle_connect.c
--- mosquitto-2.0.8/src/handle_connect.c	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/src/handle_connect.c	2021-03-11 22:37:20.000000000 +0000
@@ -244,7 +244,9 @@
 				goto error;
 			}
 		}
-		if(context->keepalive > db.config->max_keepalive){
+		if(db.config->max_keepalive &&
+				(context->keepalive > db.config->max_keepalive || context->keepalive == 0)){
+
 			context->keepalive = db.config->max_keepalive;
 			if(mosquitto_property_add_int16(&connack_props, MQTT_PROP_SERVER_KEEP_ALIVE, context->keepalive)){
 				rc = MOSQ_ERR_NOMEM;
diff -Nru mosquitto-2.0.8/src/handle_publish.c mosquitto-2.0.9/src/handle_publish.c
--- mosquitto-2.0.8/src/handle_publish.c	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/src/handle_publish.c	2021-03-11 22:37:20.000000000 +0000
@@ -285,6 +285,18 @@
 	if(msg->qos > 0){
 		db__message_store_find(context, msg->source_mid, &stored);
 	}
+
+	if(stored && msg->source_mid != 0 &&
+			(stored->qos != msg->qos
+			 || stored->payloadlen != msg->payloadlen
+			 || strcmp(stored->topic, msg->topic)
+			 || memcmp(stored->payload, msg->payload, msg->payloadlen) )){
+
+		log__printf(NULL, MOSQ_LOG_WARNING, "Reused message ID %u from %s detected. Clearing from storage.", msg->source_mid, context->id);
+		db__message_remove_incoming(context, msg->source_mid);
+		stored = NULL;
+	}
+
 	if(!stored){
 		if(msg->qos == 0
 				|| db__ready_for_flight(&context->msgs_in, msg->qos)
diff -Nru mosquitto-2.0.8/src/mosquitto_broker_internal.h mosquitto-2.0.9/src/mosquitto_broker_internal.h
--- mosquitto-2.0.8/src/mosquitto_broker_internal.h	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/src/mosquitto_broker_internal.h	2021-03-11 22:37:20.000000000 +0000
@@ -642,6 +642,7 @@
 int db__message_count(int *count);
 int db__message_delete_outgoing(struct mosquitto *context, uint16_t mid, enum mosquitto_msg_state expect_state, int qos);
 int db__message_insert(struct mosquitto *context, uint16_t mid, enum mosquitto_msg_direction dir, uint8_t qos, bool retain, struct mosquitto_msg_store *stored, mosquitto_property *properties, bool update);
+int db__message_remove_incoming(struct mosquitto* context, uint16_t mid);
 int db__message_release_incoming(struct mosquitto *context, uint16_t mid);
 int db__message_update_outgoing(struct mosquitto *context, uint16_t mid, enum mosquitto_msg_state state, int qos);
 void db__message_dequeue_first(struct mosquitto *context, struct mosquitto_msg_data *msg_data);
diff -Nru mosquitto-2.0.8/src/net.c mosquitto-2.0.9/src/net.c
--- mosquitto-2.0.8/src/net.c	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/src/net.c	2021-03-11 22:37:20.000000000 +0000
@@ -335,14 +335,14 @@
 	}else if(!strcmp(listener->tls_version, "tlsv1.3")){
 		SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2);
 	}else if(!strcmp(listener->tls_version, "tlsv1.2")){
-		SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_3);
+		SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1);
 	}else if(!strcmp(listener->tls_version, "tlsv1.1")){
-		SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3);
+		SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1);
 #else
 	}else if(!strcmp(listener->tls_version, "tlsv1.2")){
 		SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1);
 	}else if(!strcmp(listener->tls_version, "tlsv1.1")){
-		SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_2);
+		SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1);
 #endif
 	}else{
 		log__printf(NULL, MOSQ_LOG_ERR, "Error: Unsupported tls_version \"%s\".", listener->tls_version);
@@ -624,23 +624,44 @@
 				&& ifa->ifa_addr->sa_family == rp->ai_addr->sa_family){
 
 			if(rp->ai_addr->sa_family == AF_INET){
-				memcpy(&((struct sockaddr_in *)rp->ai_addr)->sin_addr,
-						&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr,
-						sizeof(struct in_addr));
-
-				freeifaddrs(ifaddr);
-				return MOSQ_ERR_SUCCESS;
+				if(listener->host &&
+						memcmp(&((struct sockaddr_in *)rp->ai_addr)->sin_addr,
+							&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr,
+							sizeof(struct in_addr))){
+
+					log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface address for %s does not match specified listener address (%s).",
+							listener->bind_interface, listener->host);
+					return MOSQ_ERR_INVAL;
+				}else{
+					memcpy(&((struct sockaddr_in *)rp->ai_addr)->sin_addr,
+							&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr,
+							sizeof(struct in_addr));
+
+					freeifaddrs(ifaddr);
+					return MOSQ_ERR_SUCCESS;
+				}
 			}else if(rp->ai_addr->sa_family == AF_INET6){
-				memcpy(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr,
-						&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr,
-						 sizeof(struct in6_addr));
-				freeifaddrs(ifaddr);
-				return MOSQ_ERR_SUCCESS;
+				if(listener->host &&
+						memcmp(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr,
+							&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr,
+							sizeof(struct in6_addr))){
+
+					log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface address for %s does not match specified listener address (%s).",
+							listener->bind_interface, listener->host);
+					return MOSQ_ERR_INVAL;
+				}else{
+					memcpy(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr,
+							&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr,
+							sizeof(struct in6_addr));
+					freeifaddrs(ifaddr);
+					return MOSQ_ERR_SUCCESS;
+				}
 			}
 		}
 	}
 	freeifaddrs(ifaddr);
-	log__printf(NULL, MOSQ_LOG_ERR, "Error: Interface %s not found.", listener->bind_interface);
+	log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface %s does not support %s configuration.",
+	            listener->bind_interface, rp->ai_addr->sa_family == AF_INET ? "IPv4" : "IPv6");
 	return MOSQ_ERR_NOT_FOUND;
 }
 #endif
@@ -654,6 +675,9 @@
 	char service[10];
 	int rc;
 	int ss_opt = 1;
+#ifndef WIN32
+	bool interface_bound = false;
+#endif
 
 	if(!listener) return MOSQ_ERR_INVAL;
 
@@ -718,12 +742,14 @@
 
 #ifndef WIN32
 		if(listener->bind_interface){
+			/* It might be possible that an interface does not support all relevant sa_families.
+			 * We should successfully find at least one. */
 			if(net__bind_interface(listener, rp)){
 				COMPAT_CLOSE(sock);
-				freeaddrinfo(ainfo);
-				mosquitto__free(listener->socks);
-				return 1;
+				listener->sock_count--;
+				continue;
 			}
+			interface_bound = true;
 		}
 #endif
 
@@ -745,6 +771,13 @@
 	}
 	freeaddrinfo(ainfo);
 
+#ifndef WIN32
+	if(listener->bind_interface && !interface_bound){
+		mosquitto__free(listener->socks);
+		return 1;
+	}
+#endif
+
 	return 0;
 }
 
diff -Nru mosquitto-2.0.8/src/retain.c mosquitto-2.0.9/src/retain.c
--- mosquitto-2.0.8/src/retain.c	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/src/retain.c	2021-03-11 22:37:20.000000000 +0000
@@ -83,7 +83,10 @@
 	assert(split_topics);
 
 	HASH_FIND(hh, db.retains, split_topics[0], strlen(split_topics[0]), retainhier);
-	if(retainhier == NULL) return MOSQ_ERR_NOT_FOUND;
+	if(retainhier == NULL){
+		retainhier = retain__add_hier_entry(NULL, &db.retains, split_topics[0], (uint16_t)strlen(split_topics[0]));
+		if(!retainhier) return MOSQ_ERR_NOMEM;
+	}
 
 	for(i=0; split_topics[i] != NULL; i++){
 		slen = strlen(split_topics[i]);
diff -Nru mosquitto-2.0.8/test/broker/02-subpub-qos0-queued-bytes.py mosquitto-2.0.9/test/broker/02-subpub-qos0-queued-bytes.py
--- mosquitto-2.0.8/test/broker/02-subpub-qos0-queued-bytes.py	1970-01-01 01:00:00.000000000 +0100
+++ mosquitto-2.0.9/test/broker/02-subpub-qos0-queued-bytes.py	2021-03-11 22:37:20.000000000 +0000
@@ -0,0 +1,61 @@
+#!/usr/bin/env python3
+
+from mosq_test_helper import *
+
+def write_config(filename, port):
+    with open(filename, 'w') as f:
+        f.write("listener %d\n" % (port))
+        f.write("allow_anonymous true\n")
+        f.write("max_inflight_messages 20\n")
+        f.write("max_inflight_bytes 1000000\n")
+        f.write("max_queued_messages 20\n")
+        f.write("max_queued_bytes 1000000\n")
+
+def do_test(proto_ver):
+    rc = 1
+    keepalive = 60
+    connect_packet = mosq_test.gen_connect("subpub-qos0-bytes", keepalive=keepalive, proto_ver=proto_ver)
+    connack_packet = mosq_test.gen_connack(rc=0, proto_ver=proto_ver)
+
+    connect_packet_helper = mosq_test.gen_connect("qos0-bytes-helper", keepalive=keepalive, proto_ver=proto_ver)
+
+    mid = 1
+    subscribe_packet = mosq_test.gen_subscribe(mid, "subpub/qos0/queued/bytes", 1, proto_ver=proto_ver)
+    suback_packet = mosq_test.gen_suback(mid, 1, proto_ver=proto_ver)
+
+    publish_packet0 = mosq_test.gen_publish("subpub/qos0/queued/bytes", qos=0, payload="message", proto_ver=proto_ver)
+
+
+    port = mosq_test.get_port()
+    conf_file = os.path.basename(__file__).replace('.py', '.conf')
+    write_config(conf_file, port)
+    broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port)
+
+    try:
+        sock = mosq_test.do_client_connect(connect_packet, connack_packet, timeout=4, port=port, connack_error="connack 1")
+
+        mosq_test.do_send_receive(sock, subscribe_packet, suback_packet, "suback")
+
+        helper = mosq_test.do_client_connect(connect_packet_helper, connack_packet, timeout=4, port=port, connack_error="connack helper")
+
+        helper.send(publish_packet0)
+        mosq_test.expect_packet(sock, "publish0", publish_packet0)
+        rc = 0
+
+        sock.close()
+    except mosq_test.TestError:
+        pass
+    finally:
+        os.remove(conf_file)
+        broker.terminate()
+        broker.wait()
+        (stdo, stde) = broker.communicate()
+        if rc:
+            print(stde.decode('utf-8'))
+            print("proto_ver=%d" % (proto_ver))
+            exit(rc)
+
+
+do_test(proto_ver=4)
+do_test(proto_ver=5)
+exit(0)
diff -Nru mosquitto-2.0.8/test/broker/03-publish-b2c-timeout-qos1.py mosquitto-2.0.9/test/broker/03-publish-b2c-timeout-qos1.py
--- mosquitto-2.0.8/test/broker/03-publish-b2c-timeout-qos1.py	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/test/broker/03-publish-b2c-timeout-qos1.py	1970-01-01 01:00:00.000000000 +0100
@@ -1,71 +0,0 @@
-#!/usr/bin/env python3
-
-# Test whether a SUBSCRIBE to a topic with QoS 2 results in the correct SUBACK packet.
-
-from mosq_test_helper import *
-
-
-def helper(port):
-    connect_packet = mosq_test.gen_connect("test-helper", keepalive=60)
-    connack_packet = mosq_test.gen_connack(rc=0)
-
-    mid = 128
-    publish_packet = mosq_test.gen_publish("qos1/timeout/test", qos=1, mid=mid, payload="timeout-message")
-    puback_packet = mosq_test.gen_puback(mid)
-
-    sock = mosq_test.do_client_connect(connect_packet, connack_packet, connack_error="helper connack")
-    mosq_test.do_send_receive(sock, publish_packet, puback_packet, "helper puback")
-    sock.close()
-
-
-def do_test(proto_ver):
-    rc = 1
-    mid = 3265
-    keepalive = 60
-    connect_packet = mosq_test.gen_connect("pub-qos1-timeout-test", keepalive=keepalive, proto_ver=proto_ver)
-    connack_packet = mosq_test.gen_connack(rc=0, proto_ver=proto_ver)
-
-    subscribe_packet = mosq_test.gen_subscribe(mid, "qos1/timeout/test", 1, proto_ver=proto_ver)
-    suback_packet = mosq_test.gen_suback(mid, 1, proto_ver=proto_ver)
-
-    mid = 1
-    publish_packet = mosq_test.gen_publish("qos1/timeout/test", qos=1, mid=mid, payload="timeout-message", proto_ver=proto_ver)
-    publish_dup_packet = mosq_test.gen_publish("qos1/timeout/test", qos=1, mid=mid, payload="timeout-message", dup=True, proto_ver=proto_ver)
-    puback_packet = mosq_test.gen_puback(mid, proto_ver=proto_ver)
-
-    port = mosq_test.get_port()
-    broker = mosq_test.start_broker(filename=os.path.basename(__file__), port=port)
-
-    try:
-        sock = mosq_test.do_client_connect(connect_packet, connack_packet)
-        mosq_test.do_send_receive(sock, subscribe_packet, suback_packet, "suback")
-
-        helper(port)
-        # Should have now received a publish command
-
-        mosq_test.expect_packet(sock, "publish", publish_packet)
-        # Wait for longer than 5 seconds to get republish with dup set
-        # This is covered by the 8 second timeout
-
-        mosq_test.expect_packet(sock, "dup publish", publish_dup_packet)
-        sock.send(puback_packet)
-        rc = 0
-
-        sock.close()
-    except mosq_test.TestError:
-        pass
-    finally:
-        broker.terminate()
-        broker.wait()
-        (stdo, stde) = broker.communicate()
-        if rc:
-            print(stde.decode('utf-8'))
-            print("proto_ver=%d" % (proto_ver))
-            exit(rc)
-
-
-do_test(proto_ver=4)
-do_test(proto_ver=5)
-
-exit(0)
-
diff -Nru mosquitto-2.0.8/test/broker/03-publish-b2c-timeout-qos2.py mosquitto-2.0.9/test/broker/03-publish-b2c-timeout-qos2.py
--- mosquitto-2.0.8/test/broker/03-publish-b2c-timeout-qos2.py	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/test/broker/03-publish-b2c-timeout-qos2.py	1970-01-01 01:00:00.000000000 +0100
@@ -1,81 +0,0 @@
-#!/usr/bin/env python3
-
-# Test whether a SUBSCRIBE to a topic with QoS 2 results in the correct SUBACK packet.
-
-from mosq_test_helper import *
-
-
-def helper(port):
-    connect_packet = mosq_test.gen_connect("test-helper", keepalive=60)
-    connack_packet = mosq_test.gen_connack(rc=0)
-
-    mid = 312
-    publish_packet = mosq_test.gen_publish("qos2/timeout/test", qos=2, mid=mid, payload="timeout-message")
-    pubrec_packet = mosq_test.gen_pubrec(mid)
-    pubrel_packet = mosq_test.gen_pubrel(mid)
-    pubcomp_packet = mosq_test.gen_pubcomp(mid)
-
-    sock = mosq_test.do_client_connect(connect_packet, connack_packet, connack_error="helper connack")
-    mosq_test.do_send_receive(sock, publish_packet, pubrec_packet, "helper pubrec")
-    mosq_test.do_send_receive(sock, pubrel_packet, pubcomp_packet, "helper pubcomp")
-    sock.close()
-
-
-def do_test(proto_ver):
-    rc = 1
-    mid = 3265
-    keepalive = 60
-    connect_packet = mosq_test.gen_connect("pub-qo2-timeout-test", keepalive=keepalive, proto_ver=proto_ver)
-    connack_packet = mosq_test.gen_connack(rc=0, proto_ver=proto_ver)
-
-    subscribe_packet = mosq_test.gen_subscribe(mid, "qos2/timeout/test", 2, proto_ver=proto_ver)
-    suback_packet = mosq_test.gen_suback(mid, 2, proto_ver=proto_ver)
-
-    mid = 1
-    publish_packet = mosq_test.gen_publish("qos2/timeout/test", qos=2, mid=mid, payload="timeout-message", proto_ver=proto_ver)
-    publish_dup_packet = mosq_test.gen_publish("qos2/timeout/test", qos=2, mid=mid, payload="timeout-message", dup=True, proto_ver=proto_ver)
-    pubrec_packet = mosq_test.gen_pubrec(mid, proto_ver=proto_ver)
-    pubrel_packet = mosq_test.gen_pubrel(mid, proto_ver=proto_ver)
-    pubcomp_packet = mosq_test.gen_pubcomp(mid, proto_ver=proto_ver)
-
-    port = mosq_test.get_port()
-    broker = mosq_test.start_broker(filename=os.path.basename(__file__), port=port)
-
-    try:
-        sock = mosq_test.do_client_connect(connect_packet, connack_packet)
-        mosq_test.do_send_receive(sock, subscribe_packet, suback_packet, "suback")
-
-        helper(port)
-        # Should have now received a publish command
-
-        mosq_test.expect_packet(sock, "publish", publish_packet)
-        # Wait for longer than 5 seconds to get republish with dup set
-        # This is covered by the 8 second timeout
-
-        mosq_test.expect_packet(sock, "dup publish", publish_dup_packet)
-        mosq_test.do_send_receive(sock, pubrec_packet, pubrel_packet, "pubrel")
-
-        # Wait for longer than 5 seconds to get republish with dup set
-        # This is covered by the 8 second timeout
-
-        mosq_test.expect_packet(sock, "dup pubrel", pubrel_packet)
-        sock.send(pubcomp_packet)
-        rc = 0
-
-        sock.close()
-    except mosq_test.TestError:
-        pass
-    finally:
-        broker.terminate()
-        broker.wait()
-        (stdo, stde) = broker.communicate()
-        if rc:
-            print(stde.decode('utf-8'))
-            print("proto_ver=%d" % (proto_ver))
-            exit(rc)
-
-
-do_test(proto_ver=4)
-do_test(proto_ver=5)
-exit(0)
-
diff -Nru mosquitto-2.0.8/test/broker/03-publish-c2b-timeout-qos2.py mosquitto-2.0.9/test/broker/03-publish-c2b-timeout-qos2.py
--- mosquitto-2.0.8/test/broker/03-publish-c2b-timeout-qos2.py	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/test/broker/03-publish-c2b-timeout-qos2.py	1970-01-01 01:00:00.000000000 +0100
@@ -1,52 +0,0 @@
-#!/usr/bin/env python3
-
-# Test whether a PUBLISH to a topic with QoS 2 results in the correct packet
-# flow. This test introduces delays into the flow in order to force the broker
-# to send duplicate PUBREC and PUBCOMP messages.
-
-from mosq_test_helper import *
-
-
-def do_test(port):
-    rc = 1
-    keepalive = 600
-    connect_packet = mosq_test.gen_connect("pub-qos2-timeout-test", keepalive=keepalive, proto_ver=proto_ver)
-    connack_packet = mosq_test.gen_connack(rc=0, proto_ver=proto_ver)
-
-    mid = 1926
-    publish_packet = mosq_test.gen_publish("pub/qos2/test", qos=2, mid=mid, payload="timeout-message", proto_ver=proto_ver)
-    pubrec_packet = mosq_test.gen_pubrec(mid, proto_ver=proto_ver)
-    pubrel_packet = mosq_test.gen_pubrel(mid, proto_ver=proto_ver)
-    pubcomp_packet = mosq_test.gen_pubcomp(mid, proto_ver=proto_ver)
-
-    port = mosq_test.get_port()
-    broker = mosq_test.start_broker(filename=os.path.basename(__file__), port=port)
-
-    try:
-        sock = mosq_test.do_client_connect(connect_packet, connack_packet)
-        mosq_test.do_send_receive(sock, publish_packet, pubrec_packet, "pubrec")
-
-        # Timeout is 8 seconds which means the broker should repeat the PUBREC.
-
-        mosq_test.expect_packet(sock, "pubrec", pubrec_packet)
-        mosq_test.do_send_receive(sock, pubrel_packet, pubcomp_packet, "pubcomp")
-
-        rc = 0
-
-        sock.close()
-    except mosq_test.TestError:
-        pass
-    finally:
-        broker.terminate()
-        broker.wait()
-        (stdo, stde) = broker.communicate()
-        if rc:
-            print(stde.decode('utf-8'))
-            print("proto_ver=%d" % (proto_ver))
-            exit(rc)
-
-
-do_test(proto_ver=4)
-do_test(proto_ver=5)
-exit(0)
-
diff -Nru mosquitto-2.0.8/test/broker/Makefile mosquitto-2.0.9/test/broker/Makefile
--- mosquitto-2.0.8/test/broker/Makefile	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/test/broker/Makefile	2021-03-11 22:37:20.000000000 +0000
@@ -45,6 +45,7 @@
 	./02-subhier-crash.py
 	./02-subpub-qos0-long-topic.py
 	./02-subpub-qos0-oversize-payload.py
+	./02-subpub-qos0-queued-bytes.py
 	./02-subpub-qos0-retain-as-publish.py
 	./02-subpub-qos0-send-retain.py
 	./02-subpub-qos0-subscription-id.py
diff -Nru mosquitto-2.0.8/test/broker/test.py mosquitto-2.0.9/test/broker/test.py
--- mosquitto-2.0.8/test/broker/test.py	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/test/broker/test.py	2021-03-11 22:37:20.000000000 +0000
@@ -28,6 +28,7 @@
     (1, './02-subhier-crash.py'),
     (1, './02-subpub-qos0-long-topic.py'),
     (1, './02-subpub-qos0-oversize-payload.py'),
+    (1, './02-subpub-qos0-queued-bytes.py'),
     (1, './02-subpub-qos0-retain-as-publish.py'),
     (1, './02-subpub-qos0-send-retain.py'),
     (1, './02-subpub-qos0-subscription-id.py'),
diff -Nru mosquitto-2.0.8/lib/loop.c mosquitto-2.0.9/lib/loop.c
--- mosquitto-2.0.8/lib/loop.c	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/lib/loop.c	2021-03-11 22:37:20.000000000 +0000
@@ -203,6 +203,13 @@
 	char pairbuf;
 	int maxfd = 0;
 
+#ifndef WIN32
+	if(read(mosq->sockpairR, &pairbuf, 1) == 0){
+	}
+#else
+	recv(mosq->sockpairR, &pairbuf, 1, 0);
+#endif
+
 	local_timeout.tv_sec = reconnect_delay;
 #ifdef HAVE_PSELECT
 	local_timeout.tv_nsec = 0;
diff -Nru mosquitto-2.0.8/lib/mosquitto.c mosquitto-2.0.9/lib/mosquitto.c
--- mosquitto-2.0.8/lib/mosquitto.c	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/lib/mosquitto.c	2021-03-11 22:37:20.000000000 +0000
@@ -196,6 +196,7 @@
 #ifdef WITH_TLS
 	mosq->ssl = NULL;
 	mosq->ssl_ctx = NULL;
+	mosq->ssl_ctx_defaults = true;
 	mosq->tls_cert_reqs = SSL_VERIFY_PEER;
 	mosq->tls_insecure = false;
 	mosq->want_write = false;
diff -Nru mosquitto-2.0.8/lib/mosquitto_internal.h mosquitto-2.0.9/lib/mosquitto_internal.h
--- mosquitto-2.0.8/lib/mosquitto_internal.h	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/lib/mosquitto_internal.h	2021-03-11 22:37:20.000000000 +0000
@@ -190,8 +190,8 @@
 #ifdef WITH_BROKER
 	struct mosquitto_client_msg *inflight;
 	struct mosquitto_client_msg *queued;
-	unsigned long msg_bytes;
-	unsigned long msg_bytes12;
+	long msg_bytes;
+	long msg_bytes12;
 	int msg_count;
 	int msg_count12;
 #else
diff -Nru mosquitto-2.0.8/src/bridge.c mosquitto-2.0.9/src/bridge.c
--- mosquitto-2.0.8/src/bridge.c	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/src/bridge.c	2021-03-11 22:37:20.000000000 +0000
@@ -112,6 +112,7 @@
 	new_context->tls_alpn = new_context->bridge->tls_alpn;
 	new_context->tls_engine = db.config->default_listener.tls_engine;
 	new_context->tls_keyform = db.config->default_listener.tls_keyform;
+	new_context->ssl_ctx_defaults = true;
 #ifdef FINAL_WITH_TLS_PSK
 	new_context->tls_psk_identity = new_context->bridge->tls_psk_identity;
 	new_context->tls_psk = new_context->bridge->tls_psk;
@@ -313,10 +314,8 @@
 
 	rc = send__connect(context, context->keepalive, context->clean_start, NULL);
 	if(rc == MOSQ_ERR_SUCCESS){
-		bridge__backoff_reset(context);
 		return MOSQ_ERR_SUCCESS;
 	}else if(rc == MOSQ_ERR_ERRNO && errno == ENOTCONN){
-		bridge__backoff_reset(context);
 		return MOSQ_ERR_SUCCESS;
 	}else{
 		if(rc == MOSQ_ERR_TLS){
@@ -454,10 +453,8 @@
 
 	rc2 = send__connect(context, context->keepalive, context->clean_start, NULL);
 	if(rc2 == MOSQ_ERR_SUCCESS){
-		bridge__backoff_reset(context);
 		return rc;
 	}else if(rc2 == MOSQ_ERR_ERRNO && errno == ENOTCONN){
-		bridge__backoff_reset(context);
 		return MOSQ_ERR_SUCCESS;
 	}else{
 		if(rc2 == MOSQ_ERR_TLS){
@@ -562,6 +559,8 @@
 		}
 	}
 
+	bridge__backoff_reset(context);
+
 	return MOSQ_ERR_SUCCESS;
 }
 
@@ -646,11 +645,11 @@
 	packet__cleanup(&(context->in_packet));
 }
 
-static int rand_between(int base, int cap)
+static int rand_between(int low, int high)
 {
 	int r;
 	util__random_bytes(&r, sizeof(int));
-	return (r % (cap - base)) + base;
+	return (abs(r) % (high - low)) + low;
 }
 
 static void bridge__backoff_step(struct mosquitto *context)
@@ -685,6 +684,33 @@
 	}
 }
 
+
+static void bridge_check_pending(struct mosquitto *context)
+{
+	int err;
+	socklen_t len;
+
+	if(context->state == mosq_cs_connect_pending){
+		len = sizeof(int);
+		if(!getsockopt(context->sock, SOL_SOCKET, SO_ERROR, (char *)&err, &len)){
+			if(err == 0){
+				mosquitto__set_state(context, mosq_cs_new);
+#if defined(WITH_ADNS) && defined(WITH_BRIDGE)
+				if(context->bridge){
+					bridge__connect_step3(context);
+				}
+#endif
+			}else if(err == ECONNREFUSED){
+				do_disconnect(context, MOSQ_ERR_CONN_LOST);
+				return;
+			}
+		}else{
+			do_disconnect(context, MOSQ_ERR_CONN_LOST);
+			return;
+		}
+	}
+}
+
 void bridge_check(void)
 {
 	static time_t last_check = 0;
@@ -703,6 +729,7 @@
 
 		if(context->sock != INVALID_SOCKET){
 			mosquitto__check_keepalive(context);
+			bridge_check_pending(context);
 
 			/* Check for bridges that are not round robin and not currently
 			 * connected to their primary broker. */
diff -Nru mosquitto-2.0.8/src/CMakeLists.txt mosquitto-2.0.9/src/CMakeLists.txt
--- mosquitto-2.0.8/src/CMakeLists.txt	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/src/CMakeLists.txt	2021-03-11 22:37:20.000000000 +0000
@@ -77,6 +77,11 @@
 	include_directories(${mosquitto_SOURCE_DIR} ${mosquitto_SOURCE_DIR}/deps)
 endif (WITH_BUNDLED_DEPS)
 
+find_path(HAVE_SYS_EPOLL_H sys/epoll.h)
+if (HAVE_SYS_EPOLL_H)
+	add_definitions("-DWITH_EPOLL")
+endif()
+
 option(INC_BRIDGE_SUPPORT
 	"Include bridge support for connecting to other brokers?" ON)
 if (INC_BRIDGE_SUPPORT)
diff -Nru mosquitto-2.0.8/src/database.c mosquitto-2.0.9/src/database.c
--- mosquitto-2.0.8/src/database.c	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/src/database.c	2021-03-11 22:37:20.000000000 +0000
@@ -53,7 +53,7 @@
 		if(db.config->max_queued_messages == 0 && db.config->max_inflight_bytes == 0){
 			return true;
 		}
-		valid_bytes = msgs->msg_bytes - db.config->max_inflight_bytes < db.config->max_queued_bytes;
+		valid_bytes = ((msgs->msg_bytes - (ssize_t)db.config->max_inflight_bytes) < (ssize_t)db.config->max_queued_bytes);
 		valid_count = msgs->msg_count - msgs->inflight_maximum < db.config->max_queued_messages;
 
 		if(db.config->max_queued_messages == 0){
@@ -90,8 +90,8 @@
 {
 	int source_count;
 	int adjust_count;
-	size_t source_bytes;
-	size_t adjust_bytes = db.config->max_inflight_bytes;
+	long source_bytes;
+	ssize_t adjust_bytes = (ssize_t)db.config->max_inflight_bytes;
 	bool valid_bytes;
 	bool valid_count;
 
@@ -893,6 +893,26 @@
 }
 
 
+int db__message_remove_incoming(struct mosquitto* context, uint16_t mid)
+{
+	struct mosquitto_client_msg *tail, *tmp;
+
+	if(!context) return MOSQ_ERR_INVAL;
+
+	DL_FOREACH_SAFE(context->msgs_in.inflight, tail, tmp){
+		if(tail->mid == mid) {
+			if(tail->store->qos != 2){
+				return MOSQ_ERR_PROTOCOL;
+			}
+			db__message_remove(&context->msgs_in, tail);
+			return MOSQ_ERR_SUCCESS;
+		}
+	}
+
+	return MOSQ_ERR_NOT_FOUND;
+}
+
+
 int db__message_release_incoming(struct mosquitto *context, uint16_t mid)
 {
 	struct mosquitto_client_msg *tail, *tmp;
diff -Nru mosquitto-2.0.8/src/handle_connect.c mosquitto-2.0.9/src/handle_connect.c
--- mosquitto-2.0.8/src/handle_connect.c	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/src/handle_connect.c	2021-03-11 22:37:20.000000000 +0000
@@ -244,7 +244,9 @@
 				goto error;
 			}
 		}
-		if(context->keepalive > db.config->max_keepalive){
+		if(db.config->max_keepalive &&
+				(context->keepalive > db.config->max_keepalive || context->keepalive == 0)){
+
 			context->keepalive = db.config->max_keepalive;
 			if(mosquitto_property_add_int16(&connack_props, MQTT_PROP_SERVER_KEEP_ALIVE, context->keepalive)){
 				rc = MOSQ_ERR_NOMEM;
diff -Nru mosquitto-2.0.8/src/handle_publish.c mosquitto-2.0.9/src/handle_publish.c
--- mosquitto-2.0.8/src/handle_publish.c	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/src/handle_publish.c	2021-03-11 22:37:20.000000000 +0000
@@ -285,6 +285,18 @@
 	if(msg->qos > 0){
 		db__message_store_find(context, msg->source_mid, &stored);
 	}
+
+	if(stored && msg->source_mid != 0 &&
+			(stored->qos != msg->qos
+			 || stored->payloadlen != msg->payloadlen
+			 || strcmp(stored->topic, msg->topic)
+			 || memcmp(stored->payload, msg->payload, msg->payloadlen) )){
+
+		log__printf(NULL, MOSQ_LOG_WARNING, "Reused message ID %u from %s detected. Clearing from storage.", msg->source_mid, context->id);
+		db__message_remove_incoming(context, msg->source_mid);
+		stored = NULL;
+	}
+
 	if(!stored){
 		if(msg->qos == 0
 				|| db__ready_for_flight(&context->msgs_in, msg->qos)
diff -Nru mosquitto-2.0.8/src/mosquitto_broker_internal.h mosquitto-2.0.9/src/mosquitto_broker_internal.h
--- mosquitto-2.0.8/src/mosquitto_broker_internal.h	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/src/mosquitto_broker_internal.h	2021-03-11 22:37:20.000000000 +0000
@@ -642,6 +642,7 @@
 int db__message_count(int *count);
 int db__message_delete_outgoing(struct mosquitto *context, uint16_t mid, enum mosquitto_msg_state expect_state, int qos);
 int db__message_insert(struct mosquitto *context, uint16_t mid, enum mosquitto_msg_direction dir, uint8_t qos, bool retain, struct mosquitto_msg_store *stored, mosquitto_property *properties, bool update);
+int db__message_remove_incoming(struct mosquitto* context, uint16_t mid);
 int db__message_release_incoming(struct mosquitto *context, uint16_t mid);
 int db__message_update_outgoing(struct mosquitto *context, uint16_t mid, enum mosquitto_msg_state state, int qos);
 void db__message_dequeue_first(struct mosquitto *context, struct mosquitto_msg_data *msg_data);
diff -Nru mosquitto-2.0.8/src/net.c mosquitto-2.0.9/src/net.c
--- mosquitto-2.0.8/src/net.c	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/src/net.c	2021-03-11 22:37:20.000000000 +0000
@@ -335,14 +335,14 @@
 	}else if(!strcmp(listener->tls_version, "tlsv1.3")){
 		SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2);
 	}else if(!strcmp(listener->tls_version, "tlsv1.2")){
-		SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_3);
+		SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1);
 	}else if(!strcmp(listener->tls_version, "tlsv1.1")){
-		SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3);
+		SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1);
 #else
 	}else if(!strcmp(listener->tls_version, "tlsv1.2")){
 		SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1);
 	}else if(!strcmp(listener->tls_version, "tlsv1.1")){
-		SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_2);
+		SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1);
 #endif
 	}else{
 		log__printf(NULL, MOSQ_LOG_ERR, "Error: Unsupported tls_version \"%s\".", listener->tls_version);
@@ -624,23 +624,44 @@
 				&& ifa->ifa_addr->sa_family == rp->ai_addr->sa_family){
 
 			if(rp->ai_addr->sa_family == AF_INET){
-				memcpy(&((struct sockaddr_in *)rp->ai_addr)->sin_addr,
-						&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr,
-						sizeof(struct in_addr));
-
-				freeifaddrs(ifaddr);
-				return MOSQ_ERR_SUCCESS;
+				if(listener->host &&
+						memcmp(&((struct sockaddr_in *)rp->ai_addr)->sin_addr,
+							&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr,
+							sizeof(struct in_addr))){
+
+					log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface address for %s does not match specified listener address (%s).",
+							listener->bind_interface, listener->host);
+					return MOSQ_ERR_INVAL;
+				}else{
+					memcpy(&((struct sockaddr_in *)rp->ai_addr)->sin_addr,
+							&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr,
+							sizeof(struct in_addr));
+
+					freeifaddrs(ifaddr);
+					return MOSQ_ERR_SUCCESS;
+				}
 			}else if(rp->ai_addr->sa_family == AF_INET6){
-				memcpy(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr,
-						&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr,
-						 sizeof(struct in6_addr));
-				freeifaddrs(ifaddr);
-				return MOSQ_ERR_SUCCESS;
+				if(listener->host &&
+						memcmp(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr,
+							&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr,
+							sizeof(struct in6_addr))){
+
+					log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface address for %s does not match specified listener address (%s).",
+							listener->bind_interface, listener->host);
+					return MOSQ_ERR_INVAL;
+				}else{
+					memcpy(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr,
+							&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr,
+							sizeof(struct in6_addr));
+					freeifaddrs(ifaddr);
+					return MOSQ_ERR_SUCCESS;
+				}
 			}
 		}
 	}
 	freeifaddrs(ifaddr);
-	log__printf(NULL, MOSQ_LOG_ERR, "Error: Interface %s not found.", listener->bind_interface);
+	log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface %s does not support %s configuration.",
+	            listener->bind_interface, rp->ai_addr->sa_family == AF_INET ? "IPv4" : "IPv6");
 	return MOSQ_ERR_NOT_FOUND;
 }
 #endif
@@ -654,6 +675,9 @@
 	char service[10];
 	int rc;
 	int ss_opt = 1;
+#ifndef WIN32
+	bool interface_bound = false;
+#endif
 
 	if(!listener) return MOSQ_ERR_INVAL;
 
@@ -718,12 +742,14 @@
 
 #ifndef WIN32
 		if(listener->bind_interface){
+			/* It might be possible that an interface does not support all relevant sa_families.
+			 * We should successfully find at least one. */
 			if(net__bind_interface(listener, rp)){
 				COMPAT_CLOSE(sock);
-				freeaddrinfo(ainfo);
-				mosquitto__free(listener->socks);
-				return 1;
+				listener->sock_count--;
+				continue;
 			}
+			interface_bound = true;
 		}
 #endif
 
@@ -745,6 +771,13 @@
 	}
 	freeaddrinfo(ainfo);
 
+#ifndef WIN32
+	if(listener->bind_interface && !interface_bound){
+		mosquitto__free(listener->socks);
+		return 1;
+	}
+#endif
+
 	return 0;
 }
 
diff -Nru mosquitto-2.0.8/src/retain.c mosquitto-2.0.9/src/retain.c
--- mosquitto-2.0.8/src/retain.c	2021-02-25 17:28:19.000000000 +0000
+++ mosquitto-2.0.9/src/retain.c	2021-03-11 22:37:20.000000000 +0000
@@ -83,7 +83,10 @@
 	assert(split_topics);
 
 	HASH_FIND(hh, db.retains, split_topics[0], strlen(split_topics[0]), retainhier);
-	if(retainhier == NULL) return MOSQ_ERR_NOT_FOUND;
+	if(retainhier == NULL){
+		retainhier = retain__add_hier_entry(NULL, &db.retains, split_topics[0], (uint16_t)strlen(split_topics[0]));
+		if(!retainhier) return MOSQ_ERR_NOMEM;
+	}
 
 	for(i=0; split_topics[i] != NULL; i++){
 		slen = strlen(split_topics[i]);

Reply to: