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