1 /* 2 * include/haproxy/mqtt.h 3 * This file contains structure declarations for MQTT protocol. 4 * 5 * Copyright 2020 Baptiste Assmann <bedis9@gmail.com> 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation, version 2.1 10 * exclusively. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22 #ifndef _HAPROXY_MQTT_T_H 23 #define _HAPROXY_MQTT_T_H 24 25 #include <import/ist.h> 26 27 /* MQTT protocol version 28 * In MQTT 3.1.1, version is called "level" 29 */ 30 #define MQTT_VERSION_3_1_1 4 31 #define MQTT_VERSION_5_0 5 32 33 /* 34 * return code when parsing / validating MQTT messages 35 */ 36 #define MQTT_INVALID_MESSAGE -1 37 #define MQTT_NEED_MORE_DATA 0 38 #define MQTT_VALID_MESSAGE 1 39 40 41 /* 42 * MQTT Control Packet Type: MQTT_CPT_* 43 * 44 * Part of the fixed headers, encoded on the first packet byte : 45 * 46 * +-------+-----------+-----------+-----------+---------+----------+----------+---------+------------+ 47 * | bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 48 * +-------+-----------+-----------+-----------+---------+----------+----------+---------+------------+ 49 * | field | MQTT Control Packet Type | Flags specific to each Control Packet type | 50 * +-------+---------------------------------------------+--------------------------------------------+ 51 * 52 * Don't forget to "left offset by 4 bits (<< 4)" the values below when matching against the fixed 53 * header collected in a MQTT packet. 54 * 55 * value 0x0 is reserved and forbidden 56 */ 57 enum { 58 MQTT_CPT_INVALID = 0, 59 60 MQTT_CPT_CONNECT, 61 MQTT_CPT_CONNACK, 62 MQTT_CPT_PUBLISH, 63 MQTT_CPT_PUBACK, 64 MQTT_CPT_PUBREC, 65 MQTT_CPT_PUBREL, 66 MQTT_CPT_PUBCOMP, 67 MQTT_CPT_SUBSCRIBE, 68 MQTT_CPT_SUBACK, 69 MQTT_CPT_UNSUBSCRIBE, 70 MQTT_CPT_UNSUBACK, 71 MQTT_CPT_PINGREQ, 72 MQTT_CPT_PINGRESP, 73 MQTT_CPT_DISCONNECT, 74 MQTT_CPT_AUTH, 75 MQTT_CPT_ENTRIES /* used to mark the end/size of our MQTT_CPT_* list */ 76 }; 77 78 /* MQTT CONNECT packet flags */ 79 #define MQTT_CONNECT_FL_RESERVED 0x01 80 #define MQTT_CONNECT_FL_CLEAN_SESSION 0x02 81 #define MQTT_CONNECT_FL_WILL 0x04 82 #define MQTT_CONNECT_FL_WILL_QOS 0x18 /* covers 2 bits 00011000 */ 83 #define MQTT_CONNECT_FL_WILL_RETAIN 0x20 84 #define MQTT_CONNECT_FL_PASSWORD 0x40 85 #define MQTT_CONNECT_FL_USERNAME 0x80 86 87 /* MQTT packet properties indentifiers 88 * https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901029 89 */ 90 #define MQTT_PROP_PAYLOAD_FORMAT_INDICATOR 0x01 91 #define MQTT_PROP_MESSAGE_EXPIRY_INTERVAL 0x02 92 #define MQTT_PROP_CONTENT_TYPE 0x03 93 #define MQTT_PROP_RESPONSE_TOPIC 0x08 94 #define MQTT_PROP_CORRELATION_DATA 0x09 95 #define MQTT_PROP_SESSION_EXPIRY_INTERVAL 0x11 96 #define MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER 0x12 97 #define MQTT_PROP_SERVER_KEEPALIVE 0x13 98 #define MQTT_PROP_AUTHENTICATION_METHOD 0x15 99 #define MQTT_PROP_AUTHENTICATION_DATA 0x16 100 #define MQTT_PROP_REQUEST_PROBLEM_INFORMATION 0x17 101 #define MQTT_PROP_WILL_DELAY_INTERVAL 0x18 102 #define MQTT_PROP_REQUEST_RESPONSE_INFORMATION 0x19 103 #define MQTT_PROP_RESPONSE_INFORMATION 0x1A 104 #define MQTT_PROP_SERVER_REFERENCE 0x1C 105 #define MQTT_PROP_RECEIVE_MAXIMUM 0x21 106 #define MQTT_PROP_TOPIC_ALIAS_MAXIMUM 0x22 107 #define MQTT_PROP_MAXIMUM_QOS 0x24 108 #define MQTT_PROP_RETAIN_AVAILABLE 0x25 109 #define MQTT_PROP_USER_PROPERTIES 0x26 110 #define MQTT_PROP_MAXIMUM_PACKET_SIZE 0x27 111 #define MQTT_PROP_WILDCARD_SUBSCRIPTION_AVAILABLE 0x28 112 #define MQTT_PROP_SUBSCRIPTION_IDENTIFIERS_AVAILABLE 0x29 113 #define MQTT_PROP_SHARED_SUBSRIPTION_AVAILABLE 0x2A 114 #define MQTT_PROP_REASON_STRING 0x1F 115 #define MQTT_PROP_LAST 0xFF 116 117 /* MQTT minimal packet size */ 118 #define MQTT_MIN_PKT_SIZE 2 119 #define MQTT_REMAINING_LENGHT_MAX_SIZE 4 120 121 /* list of supported capturable Field Names and configuration file string */ 122 enum { 123 MQTT_FN_INVALID = 0, 124 125 MQTT_FN_FLAGS, 126 MQTT_FN_REASON_CODE, 127 MQTT_FN_PROTOCOL_NAME, 128 MQTT_FN_PROTOCOL_VERSION, 129 MQTT_FN_CLIENT_IDENTIFIER, 130 MQTT_FN_WILL_TOPIC, 131 MQTT_FN_WILL_PAYLOAD, 132 MQTT_FN_USERNAME, 133 MQTT_FN_PASSWORD, 134 MQTT_FN_KEEPALIVE, 135 136 /* MQTT 5.0 properties 137 * https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901029 138 */ 139 MQTT_FN_PAYLOAD_FORMAT_INDICATOR, 140 MQTT_FN_MESSAGE_EXPIRY_INTERVAL, 141 MQTT_FN_CONTENT_TYPE, 142 MQTT_FN_RESPONSE_TOPIC, 143 MQTT_FN_CORRELATION_DATA, 144 MQTT_FN_SUBSCRIPTION_IDENTIFIER, 145 MQTT_FN_SESSION_EXPIRY_INTERVAL, 146 MQTT_FN_ASSIGNED_CLIENT_IDENTIFIER, 147 MQTT_FN_SERVER_KEEPALIVE, 148 MQTT_FN_AUTHENTICATION_METHOD, 149 MQTT_FN_AUTHENTICATION_DATA, 150 MQTT_FN_REQUEST_PROBLEM_INFORMATION, 151 MQTT_FN_DELAY_INTERVAL, 152 MQTT_FN_REQUEST_RESPONSE_INFORMATION, 153 MQTT_FN_RESPONSE_INFORMATION, 154 MQTT_FN_SERVER_REFERENCE, 155 MQTT_FN_REASON_STRING, 156 MQTT_FN_RECEIVE_MAXIMUM, 157 MQTT_FN_TOPIC_ALIAS_MAXIMUM, 158 MQTT_FN_TOPIC_ALIAS, 159 MQTT_FN_MAXIMUM_QOS, 160 MQTT_FN_RETAIN_AVAILABLE, 161 MQTT_FN_USER_PROPERTY, 162 MQTT_FN_MAXIMUM_PACKET_SIZE, 163 MQTT_FN_WILDCARD_SUBSCRIPTION_AVAILABLE, 164 MQTT_FN_SUBSCRIPTION_IDENTIFIERS_AVAILABLE, 165 MQTT_FN_SHARED_SUBSCRIPTION_AVAILABLE, 166 167 MQTT_FN_ENTRIES /* this one must always be the latest one */ 168 }; 169 170 /* MQTT field string bit, for easy match using bitmasks 171 * ATTENTION: "user-properties" are not supported for now 172 */ 173 enum { 174 MQTT_FN_BIT_FLAGS = (1ULL << MQTT_FN_FLAGS), 175 MQTT_FN_BIT_REASON_CODE = (1ULL << MQTT_FN_REASON_CODE), 176 MQTT_FN_BIT_PROTOCOL_NAME = (1ULL << MQTT_FN_PROTOCOL_NAME), 177 MQTT_FN_BIT_PROTOCOL_VERSION = (1ULL << MQTT_FN_PROTOCOL_VERSION), 178 MQTT_FN_BIT_CLIENT_IDENTIFIER = (1ULL << MQTT_FN_CLIENT_IDENTIFIER), 179 MQTT_FN_BIT_WILL_TOPIC = (1ULL << MQTT_FN_WILL_TOPIC), 180 MQTT_FN_BIT_WILL_PAYLOAD = (1ULL << MQTT_FN_WILL_PAYLOAD), 181 MQTT_FN_BIT_USERNAME = (1ULL << MQTT_FN_USERNAME), 182 MQTT_FN_BIT_PASSWORD = (1ULL << MQTT_FN_PASSWORD), 183 MQTT_FN_BIT_KEEPALIVE = (1ULL << MQTT_FN_KEEPALIVE), 184 MQTT_FN_BIT_PAYLOAD_FORMAT_INDICATOR = (1ULL << MQTT_FN_PAYLOAD_FORMAT_INDICATOR), 185 MQTT_FN_BIT_MESSAGE_EXPIRY_INTERVAL = (1ULL << MQTT_FN_MESSAGE_EXPIRY_INTERVAL), 186 MQTT_FN_BIT_CONTENT_TYPE = (1ULL << MQTT_FN_CONTENT_TYPE), 187 MQTT_FN_BIT_RESPONSE_TOPIC = (1ULL << MQTT_FN_RESPONSE_TOPIC), 188 MQTT_FN_BIT_CORRELATION_DATA = (1ULL << MQTT_FN_CORRELATION_DATA), 189 MQTT_FN_BIT_SUBSCRIPTION_IDENTIFIER = (1ULL << MQTT_FN_SUBSCRIPTION_IDENTIFIER), 190 MQTT_FN_BIT_SESSION_EXPIRY_INTERVAL = (1ULL << MQTT_FN_SESSION_EXPIRY_INTERVAL), 191 MQTT_FN_BIT_ASSIGNED_CLIENT_IDENTIFIER = (1ULL << MQTT_FN_ASSIGNED_CLIENT_IDENTIFIER), 192 MQTT_FN_BIT_SERVER_KEEPALIVE = (1ULL << MQTT_FN_SERVER_KEEPALIVE), 193 MQTT_FN_BIT_AUTHENTICATION_METHOD = (1ULL << MQTT_FN_AUTHENTICATION_METHOD), 194 MQTT_FN_BIT_AUTHENTICATION_DATA = (1ULL << MQTT_FN_AUTHENTICATION_DATA), 195 MQTT_FN_BIT_REQUEST_PROBLEM_INFORMATION = (1ULL << MQTT_FN_REQUEST_PROBLEM_INFORMATION), 196 MQTT_FN_BIT_DELAY_INTERVAL = (1ULL << MQTT_FN_DELAY_INTERVAL), 197 MQTT_FN_BIT_REQUEST_RESPONSE_INFORMATION = (1ULL << MQTT_FN_REQUEST_RESPONSE_INFORMATION), 198 MQTT_FN_BIT_RESPONSE_INFORMATION = (1ULL << MQTT_FN_RESPONSE_INFORMATION), 199 MQTT_FN_BIT_SERVER_REFERENCE = (1ULL << MQTT_FN_SERVER_REFERENCE), 200 MQTT_FN_BIT_REASON_STRING = (1ULL << MQTT_FN_REASON_STRING), 201 MQTT_FN_BIT_RECEIVE_MAXIMUM = (1ULL << MQTT_FN_RECEIVE_MAXIMUM), 202 MQTT_FN_BIT_TOPIC_ALIAS_MAXIMUM = (1ULL << MQTT_FN_TOPIC_ALIAS_MAXIMUM), 203 MQTT_FN_BIT_TOPIC_ALIAS = (1ULL << MQTT_FN_TOPIC_ALIAS), 204 MQTT_FN_BIT_MAXIMUM_QOS = (1ULL << MQTT_FN_MAXIMUM_QOS), 205 MQTT_FN_BIT_RETAIN_AVAILABLE = (1ULL << MQTT_FN_RETAIN_AVAILABLE), 206 MQTT_FN_BIT_USER_PROPERTY = (1ULL << MQTT_FN_USER_PROPERTY), 207 MQTT_FN_BIT_MAXIMUM_PACKET_SIZE = (1ULL << MQTT_FN_MAXIMUM_PACKET_SIZE), 208 MQTT_FN_BIT_WILDCARD_SUBSCRIPTION_AVAILABLE = (1ULL << MQTT_FN_WILDCARD_SUBSCRIPTION_AVAILABLE), 209 MQTT_FN_BIT_SUBSCRIPTION_IDENTIFIERS_AVAILABLE= (1ULL << MQTT_FN_SUBSCRIPTION_IDENTIFIERS_AVAILABLE), 210 MQTT_FN_BIT_SHARED_SUBSCRIPTION_AVAILABLE = (1ULL << MQTT_FN_SHARED_SUBSCRIPTION_AVAILABLE), 211 }; 212 213 /* structure to host fields for a MQTT CONNECT packet */ 214 #define MQTT_PROP_USER_PROPERTY_ENTRIES 5 215 struct connect { 216 struct { 217 struct ist protocol_name; 218 uint8_t protocol_version; 219 uint8_t flags; 220 uint16_t keepalive; 221 222 struct { 223 uint32_t session_expiry_interval; 224 uint16_t receive_maximum; 225 uint32_t maximum_packet_size; 226 uint16_t topic_alias_maximum; 227 uint8_t request_response_information; 228 uint8_t request_problem_information; 229 struct { 230 struct ist name; 231 struct ist value; 232 } user_props[MQTT_PROP_USER_PROPERTY_ENTRIES]; 233 struct ist authentication_method; 234 struct ist authentication_data; 235 } props; 236 } var_hdr; 237 struct { 238 struct ist client_identifier; 239 struct { 240 uint32_t delay_interval; 241 uint8_t payload_format_indicator; 242 uint32_t message_expiry_interval; 243 struct ist content_type; 244 struct ist response_topic; 245 struct ist correlation_data; 246 struct { 247 struct ist name; 248 struct ist value; 249 } user_props[MQTT_PROP_USER_PROPERTY_ENTRIES]; 250 } will_props; 251 struct ist will_topic; 252 struct ist will_payload; 253 struct ist username; 254 struct ist password; 255 } payload; 256 }; 257 258 /* structure to host fields for a MQTT CONNACK packet */ 259 struct connack { 260 struct { 261 uint8_t protocol_version; 262 uint8_t flags; 263 uint8_t reason_code; 264 struct { 265 uint32_t session_expiry_interval; 266 uint16_t receive_maximum; 267 uint8_t maximum_qos; 268 uint8_t retain_available; 269 uint32_t maximum_packet_size; 270 struct ist assigned_client_identifier; 271 uint16_t topic_alias_maximum; 272 struct ist reason_string; 273 struct { 274 struct ist name; 275 struct ist value; 276 } user_props[MQTT_PROP_USER_PROPERTY_ENTRIES]; 277 uint8_t wildcard_subscription_available; 278 uint8_t subscription_identifiers_available; 279 uint8_t shared_subsription_available; 280 uint16_t server_keepalive; 281 struct ist response_information; 282 struct ist server_reference; 283 struct ist authentication_method; 284 struct ist authentication_data; 285 } props; 286 } var_hdr; 287 }; 288 289 /* structure to host a MQTT packet */ 290 struct mqtt_pkt { 291 struct { 292 uint8_t type; /* MQTT_CPT_* */ 293 uint8_t flags; /* MQTT_CPT_FL* */ 294 uint32_t remaining_length; 295 } fixed_hdr; 296 union { 297 struct connect connect; 298 struct connack connack; 299 } data; 300 }; 301 302 #endif /* _HAPROXY_MQTT_T_H */ 303 304 /* 305 * Local variables: 306 * c-indent-level: 8 307 * c-basic-offset: 8 308 * End: 309 */ 310