MEDIUM: mqtt: support mqtt_is_valid and mqtt_field_value converters for MQTTv3.1

In MQTTv3.1, protocol name is "MQIsdp" and protocol level is 3. The mqtt
converters(mqtt_is_valid and mqtt_field_value) did not work for clients on
mqttv3.1 because the mqtt_parse_connect() marked the CONNECT message invalid
if either the protocol name is not "MQTT" or the protocol version is other than
v3.1.1 or v5.0. To fix it, we have added the mqttv3.1 protocol name and version
as part of the checks.

This patch fixes the mqtt converters to support mqttv3.1 clients as well (issue #1600).
It must be backported to 2.4.

(cherry picked from commit 12957981390ef5c1d60fd6c1004944a0ff28fb1d)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit f854d113db66cebe9501d368d03126e63f5eaed6)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/include/haproxy/mqtt-t.h b/include/haproxy/mqtt-t.h
index 9377021..710fd87 100644
--- a/include/haproxy/mqtt-t.h
+++ b/include/haproxy/mqtt-t.h
@@ -27,6 +27,7 @@
 /* MQTT protocol version
  * In MQTT 3.1.1, version is called "level"
  */
+#define MQTT_VERSION_3_1      3
 #define MQTT_VERSION_3_1_1    4
 #define MQTT_VERSION_5_0      5
 
diff --git a/reg-tests/converter/mqtt.vtc b/reg-tests/converter/mqtt.vtc
index ea2cbb4..9f7e6b1 100644
--- a/reg-tests/converter/mqtt.vtc
+++ b/reg-tests/converter/mqtt.vtc
@@ -42,6 +42,11 @@
     recv 22
     sendhex "21020000"
     expect_close
+
+    # MQTT 3.1 CONNECT packet (id: test_sub - username: test - passwd: passwd)
+    accept
+    recv 38
+    sendhex "20020000"
 } -start
 
 server s2 {
@@ -225,3 +230,9 @@
     recv 39
     expect_close
 } -run
+
+client c3_31_1 -connect ${h1_fe1_sock} {
+    # Valid MQTT 3.1 CONNECT packet (id: test_sub - username: test - passwd: passwd)
+    sendhex "102400064d514973647003c200000008746573745f7375620004746573740006706173737764"
+    recv 4
+} -run
\ No newline at end of file
diff --git a/src/mqtt.c b/src/mqtt.c
index 6624201..75759b7 100644
--- a/src/mqtt.c
+++ b/src/mqtt.c
@@ -40,14 +40,14 @@
 const struct ist mqtt_fields_string[MQTT_FN_ENTRIES] = {
 	[MQTT_FN_INVALID]                            = IST(""),
 
-	/* it's MQTT 3.1.1 and 5.0, those fields have no unique id, so we use strings */
+	/* it's MQTT 3.1, 3.1.1 and 5.0, those fields have no unique id, so we use strings */
 	[MQTT_FN_FLAGS]                              = IST("flags"),
-	[MQTT_FN_REASON_CODE]                        = IST("reason_code"),       /* MQTT 3.1.1: return_code */
+	[MQTT_FN_REASON_CODE]                        = IST("reason_code"),       /* MQTT 3.1 and 3.1.1: return_code */
 	[MQTT_FN_PROTOCOL_NAME]                      = IST("protocol_name"),
 	[MQTT_FN_PROTOCOL_VERSION]                   = IST("protocol_version"),  /* MQTT 3.1.1: protocol_level */
 	[MQTT_FN_CLIENT_IDENTIFIER]                  = IST("client_identifier"),
 	[MQTT_FN_WILL_TOPIC]                         = IST("will_topic"),
-	[MQTT_FN_WILL_PAYLOAD]                       = IST("will_payload"),      /* MQTT 3.1.1: will_message */
+	[MQTT_FN_WILL_PAYLOAD]                       = IST("will_payload"),      /* MQTT 3.1 and 3.1.1: will_message */
 	[MQTT_FN_USERNAME]                           = IST("username"),
 	[MQTT_FN_PASSWORD]                           = IST("password"),
 	[MQTT_FN_KEEPALIVE]                          = IST("keepalive"),
@@ -695,6 +695,7 @@
 }
 
 /* Parses a CONNECT packet :
+ *   https://public.dhe.ibm.com/software/dw/webservices/ws-mqtt/mqtt-v3r1.html#connect
  *   https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718028
  *   https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901033
  *
@@ -718,14 +719,15 @@
 	 */
 	/* read protocol_name */
 	parser = mqtt_read_string(parser, &mpkt->data.connect.var_hdr.protocol_name);
-	if (!isttest(parser) || !isteqi(mpkt->data.connect.var_hdr.protocol_name, ist("MQTT")))
+	if (!isttest(parser) || !(isteqi(mpkt->data.connect.var_hdr.protocol_name, ist("MQTT")) || isteqi(mpkt->data.connect.var_hdr.protocol_name, ist("MQIsdp"))))
 		goto end;
 
 	/* read protocol_version */
 	parser = mqtt_read_1byte_int(parser, &mpkt->data.connect.var_hdr.protocol_version);
 	if (!isttest(parser))
 		goto end;
-	if (mpkt->data.connect.var_hdr.protocol_version != MQTT_VERSION_3_1_1 &&
+	if (mpkt->data.connect.var_hdr.protocol_version != MQTT_VERSION_3_1 &&
+	    mpkt->data.connect.var_hdr.protocol_version != MQTT_VERSION_3_1_1 &&
 	    mpkt->data.connect.var_hdr.protocol_version != MQTT_VERSION_5_0)
 		goto end;