summaryrefslogtreecommitdiffstats
path: root/include/haproxy/mqtt-t.h
blob: 51f55ea51e9402ea307117b3b21f1c193ce2cb10 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
/*
 * include/haproxy/mqtt.h
 * This file contains structure declarations for MQTT protocol.
 *
 * Copyright 2020 Baptiste Assmann <bedis9@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation, version 2.1
 * exclusively.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#ifndef _HAPROXY_MQTT_T_H
#define _HAPROXY_MQTT_T_H

#include <import/ist.h>

/* 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

/*
 * return code when parsing / validating MQTT messages
 */
#define MQTT_INVALID_MESSAGE   -1
#define MQTT_NEED_MORE_DATA     0
#define MQTT_VALID_MESSAGE      1


/*
 * MQTT Control Packet Type: MQTT_CPT_*
 *
 * Part of the fixed headers, encoded on the first packet byte :
 *
 * +-------+-----------+-----------+-----------+---------+----------+----------+---------+------------+
 * | bit   |    7      |     6     |    5      |    4    |     3    |     2    |     1   |     0      |
 * +-------+-----------+-----------+-----------+---------+----------+----------+---------+------------+
 * | field |          MQTT Control Packet Type           | Flags specific to each Control Packet type |
 * +-------+---------------------------------------------+--------------------------------------------+
 *
 * Don't forget to "left offset by 4 bits (<< 4)" the values below when matching against the fixed
 * header collected in a MQTT packet.
 *
 * value 0x0 is reserved and forbidden
 */
enum {
	MQTT_CPT_INVALID = 0,

	MQTT_CPT_CONNECT,
	MQTT_CPT_CONNACK,
	MQTT_CPT_PUBLISH,
	MQTT_CPT_PUBACK,
	MQTT_CPT_PUBREC,
	MQTT_CPT_PUBREL,
	MQTT_CPT_PUBCOMP,
	MQTT_CPT_SUBSCRIBE,
	MQTT_CPT_SUBACK,
	MQTT_CPT_UNSUBSCRIBE,
	MQTT_CPT_UNSUBACK,
	MQTT_CPT_PINGREQ,
	MQTT_CPT_PINGRESP,
	MQTT_CPT_DISCONNECT,
	MQTT_CPT_AUTH,
	MQTT_CPT_ENTRIES  /* used to mark the end/size of our MQTT_CPT_* list */
};

/* MQTT CONNECT packet flags */
#define MQTT_CONNECT_FL_RESERVED        0x01
#define MQTT_CONNECT_FL_CLEAN_SESSION   0x02
#define MQTT_CONNECT_FL_WILL            0x04
#define MQTT_CONNECT_FL_WILL_QOS        0x18  /* covers 2 bits 00011000 */
#define MQTT_CONNECT_FL_WILL_RETAIN     0x20
#define MQTT_CONNECT_FL_PASSWORD        0x40
#define MQTT_CONNECT_FL_USERNAME        0x80

/* MQTT packet properties identifiers
 * https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901029
 */
#define MQTT_PROP_PAYLOAD_FORMAT_INDICATOR           0x01
#define MQTT_PROP_MESSAGE_EXPIRY_INTERVAL            0x02
#define MQTT_PROP_CONTENT_TYPE                       0x03
#define MQTT_PROP_RESPONSE_TOPIC                     0x08
#define MQTT_PROP_CORRELATION_DATA                   0x09
#define MQTT_PROP_SESSION_EXPIRY_INTERVAL            0x11
#define MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER         0x12
#define MQTT_PROP_SERVER_KEEPALIVE                   0x13
#define MQTT_PROP_AUTHENTICATION_METHOD              0x15
#define MQTT_PROP_AUTHENTICATION_DATA                0x16
#define MQTT_PROP_REQUEST_PROBLEM_INFORMATION        0x17
#define MQTT_PROP_WILL_DELAY_INTERVAL                0x18
#define MQTT_PROP_REQUEST_RESPONSE_INFORMATION       0x19
#define MQTT_PROP_RESPONSE_INFORMATION               0x1A
#define MQTT_PROP_SERVER_REFERENCE                   0x1C
#define MQTT_PROP_RECEIVE_MAXIMUM                    0x21
#define MQTT_PROP_TOPIC_ALIAS_MAXIMUM                0x22
#define MQTT_PROP_MAXIMUM_QOS                        0x24
#define MQTT_PROP_RETAIN_AVAILABLE                   0x25
#define MQTT_PROP_USER_PROPERTIES                    0x26
#define MQTT_PROP_MAXIMUM_PACKET_SIZE                0x27
#define MQTT_PROP_WILDCARD_SUBSCRIPTION_AVAILABLE    0x28
#define MQTT_PROP_SUBSCRIPTION_IDENTIFIERS_AVAILABLE 0x29
#define MQTT_PROP_SHARED_SUBSRIPTION_AVAILABLE       0x2A
#define MQTT_PROP_REASON_STRING                      0x1F
#define MQTT_PROP_LAST                               0xFF

/* MQTT minimal packet size */
#define MQTT_MIN_PKT_SIZE              2
#define MQTT_REMAINING_LENGHT_MAX_SIZE 4

/* list of supported capturable Field Names and configuration file string */
enum {
	MQTT_FN_INVALID = 0,

	MQTT_FN_FLAGS,
	MQTT_FN_REASON_CODE,
	MQTT_FN_PROTOCOL_NAME,
	MQTT_FN_PROTOCOL_VERSION,
	MQTT_FN_CLIENT_IDENTIFIER,
	MQTT_FN_WILL_TOPIC,
	MQTT_FN_WILL_PAYLOAD,
	MQTT_FN_USERNAME,
	MQTT_FN_PASSWORD,
	MQTT_FN_KEEPALIVE,

	/* MQTT 5.0 properties
	 * https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901029
	 */
	MQTT_FN_PAYLOAD_FORMAT_INDICATOR,
	MQTT_FN_MESSAGE_EXPIRY_INTERVAL,
	MQTT_FN_CONTENT_TYPE,
	MQTT_FN_RESPONSE_TOPIC,
	MQTT_FN_CORRELATION_DATA,
	MQTT_FN_SUBSCRIPTION_IDENTIFIER,
	MQTT_FN_SESSION_EXPIRY_INTERVAL,
	MQTT_FN_ASSIGNED_CLIENT_IDENTIFIER,
	MQTT_FN_SERVER_KEEPALIVE,
	MQTT_FN_AUTHENTICATION_METHOD,
	MQTT_FN_AUTHENTICATION_DATA,
	MQTT_FN_REQUEST_PROBLEM_INFORMATION,
	MQTT_FN_DELAY_INTERVAL,
	MQTT_FN_REQUEST_RESPONSE_INFORMATION,
	MQTT_FN_RESPONSE_INFORMATION,
	MQTT_FN_SERVER_REFERENCE,
	MQTT_FN_REASON_STRING,
	MQTT_FN_RECEIVE_MAXIMUM,
	MQTT_FN_TOPIC_ALIAS_MAXIMUM,
	MQTT_FN_TOPIC_ALIAS,
	MQTT_FN_MAXIMUM_QOS,
	MQTT_FN_RETAIN_AVAILABLE,
	MQTT_FN_USER_PROPERTY,
	MQTT_FN_MAXIMUM_PACKET_SIZE,
	MQTT_FN_WILDCARD_SUBSCRIPTION_AVAILABLE,
	MQTT_FN_SUBSCRIPTION_IDENTIFIERS_AVAILABLE,
	MQTT_FN_SHARED_SUBSCRIPTION_AVAILABLE,

	MQTT_FN_ENTRIES           /* this one must always be the latest one */
};

/* MQTT field string bit, for easy match using bitmasks
 * ATTENTION: "user-properties" are not supported for now
 */
enum {
	MQTT_FN_BIT_FLAGS                             = (1ULL << MQTT_FN_FLAGS),
	MQTT_FN_BIT_REASON_CODE                       = (1ULL << MQTT_FN_REASON_CODE),
	MQTT_FN_BIT_PROTOCOL_NAME                     = (1ULL << MQTT_FN_PROTOCOL_NAME),
	MQTT_FN_BIT_PROTOCOL_VERSION                  = (1ULL << MQTT_FN_PROTOCOL_VERSION),
	MQTT_FN_BIT_CLIENT_IDENTIFIER                 = (1ULL << MQTT_FN_CLIENT_IDENTIFIER),
	MQTT_FN_BIT_WILL_TOPIC                        = (1ULL << MQTT_FN_WILL_TOPIC),
	MQTT_FN_BIT_WILL_PAYLOAD                      = (1ULL << MQTT_FN_WILL_PAYLOAD),
	MQTT_FN_BIT_USERNAME                          = (1ULL << MQTT_FN_USERNAME),
	MQTT_FN_BIT_PASSWORD                          = (1ULL << MQTT_FN_PASSWORD),
	MQTT_FN_BIT_KEEPALIVE                         = (1ULL << MQTT_FN_KEEPALIVE),
	MQTT_FN_BIT_PAYLOAD_FORMAT_INDICATOR          = (1ULL << MQTT_FN_PAYLOAD_FORMAT_INDICATOR),
	MQTT_FN_BIT_MESSAGE_EXPIRY_INTERVAL           = (1ULL << MQTT_FN_MESSAGE_EXPIRY_INTERVAL),
	MQTT_FN_BIT_CONTENT_TYPE                      = (1ULL << MQTT_FN_CONTENT_TYPE),
	MQTT_FN_BIT_RESPONSE_TOPIC                    = (1ULL << MQTT_FN_RESPONSE_TOPIC),
	MQTT_FN_BIT_CORRELATION_DATA                  = (1ULL << MQTT_FN_CORRELATION_DATA),
	MQTT_FN_BIT_SUBSCRIPTION_IDENTIFIER           = (1ULL << MQTT_FN_SUBSCRIPTION_IDENTIFIER),
	MQTT_FN_BIT_SESSION_EXPIRY_INTERVAL           = (1ULL << MQTT_FN_SESSION_EXPIRY_INTERVAL),
	MQTT_FN_BIT_ASSIGNED_CLIENT_IDENTIFIER        = (1ULL << MQTT_FN_ASSIGNED_CLIENT_IDENTIFIER),
	MQTT_FN_BIT_SERVER_KEEPALIVE                  = (1ULL << MQTT_FN_SERVER_KEEPALIVE),
	MQTT_FN_BIT_AUTHENTICATION_METHOD             = (1ULL << MQTT_FN_AUTHENTICATION_METHOD),
	MQTT_FN_BIT_AUTHENTICATION_DATA               = (1ULL << MQTT_FN_AUTHENTICATION_DATA),
	MQTT_FN_BIT_REQUEST_PROBLEM_INFORMATION       = (1ULL << MQTT_FN_REQUEST_PROBLEM_INFORMATION),
	MQTT_FN_BIT_DELAY_INTERVAL                    = (1ULL << MQTT_FN_DELAY_INTERVAL),
	MQTT_FN_BIT_REQUEST_RESPONSE_INFORMATION      = (1ULL << MQTT_FN_REQUEST_RESPONSE_INFORMATION),
	MQTT_FN_BIT_RESPONSE_INFORMATION              = (1ULL << MQTT_FN_RESPONSE_INFORMATION),
	MQTT_FN_BIT_SERVER_REFERENCE                  = (1ULL << MQTT_FN_SERVER_REFERENCE),
	MQTT_FN_BIT_REASON_STRING                     = (1ULL << MQTT_FN_REASON_STRING),
	MQTT_FN_BIT_RECEIVE_MAXIMUM                   = (1ULL << MQTT_FN_RECEIVE_MAXIMUM),
	MQTT_FN_BIT_TOPIC_ALIAS_MAXIMUM               = (1ULL << MQTT_FN_TOPIC_ALIAS_MAXIMUM),
	MQTT_FN_BIT_TOPIC_ALIAS                       = (1ULL << MQTT_FN_TOPIC_ALIAS),
	MQTT_FN_BIT_MAXIMUM_QOS                       = (1ULL << MQTT_FN_MAXIMUM_QOS),
	MQTT_FN_BIT_RETAIN_AVAILABLE                  = (1ULL << MQTT_FN_RETAIN_AVAILABLE),
	MQTT_FN_BIT_USER_PROPERTY                     = (1ULL << MQTT_FN_USER_PROPERTY),
	MQTT_FN_BIT_MAXIMUM_PACKET_SIZE               = (1ULL << MQTT_FN_MAXIMUM_PACKET_SIZE),
	MQTT_FN_BIT_WILDCARD_SUBSCRIPTION_AVAILABLE   = (1ULL << MQTT_FN_WILDCARD_SUBSCRIPTION_AVAILABLE),
	MQTT_FN_BIT_SUBSCRIPTION_IDENTIFIERS_AVAILABLE= (1ULL << MQTT_FN_SUBSCRIPTION_IDENTIFIERS_AVAILABLE),
	MQTT_FN_BIT_SHARED_SUBSCRIPTION_AVAILABLE     = (1ULL << MQTT_FN_SHARED_SUBSCRIPTION_AVAILABLE),
};

/* structure to host fields for a MQTT CONNECT packet */
#define MQTT_PROP_USER_PROPERTY_ENTRIES 5
struct connect {
	struct {
		struct ist protocol_name;
		uint8_t protocol_version;
		uint8_t flags;
		uint16_t keepalive;

		struct {
			uint32_t session_expiry_interval;
			uint16_t receive_maximum;
			uint32_t maximum_packet_size;
			uint16_t topic_alias_maximum;
			uint8_t  request_response_information;
			uint8_t  request_problem_information;
			struct {
				struct ist name;
				struct ist value;
			} user_props[MQTT_PROP_USER_PROPERTY_ENTRIES];
			struct ist authentication_method;
			struct ist authentication_data;
		} props;
	} var_hdr;
	struct {
		struct ist client_identifier;
		struct {
			uint32_t delay_interval;
			uint8_t  payload_format_indicator;
			uint32_t message_expiry_interval;
			struct ist content_type;
			struct ist response_topic;
			struct ist correlation_data;
			struct {
				struct ist name;
				struct ist value;
			} user_props[MQTT_PROP_USER_PROPERTY_ENTRIES];
		} will_props;
		struct ist will_topic;
		struct ist will_payload;
		struct ist username;
		struct ist password;
	} payload;
};

/* structure to host fields for a MQTT CONNACK packet */
struct connack {
	struct {
		uint8_t protocol_version;
		uint8_t flags;
		uint8_t reason_code;
		struct {
			uint32_t session_expiry_interval;
			uint16_t receive_maximum;
			uint8_t  maximum_qos;
			uint8_t  retain_available;
			uint32_t maximum_packet_size;
			struct ist assigned_client_identifier;
			uint16_t topic_alias_maximum;
			struct ist reason_string;
			struct {
				struct ist name;
				struct ist value;
			} user_props[MQTT_PROP_USER_PROPERTY_ENTRIES];
			uint8_t  wildcard_subscription_available;
			uint8_t  subscription_identifiers_available;
			uint8_t  shared_subsription_available;
			uint16_t server_keepalive;
			struct ist response_information;
			struct ist server_reference;
			struct ist authentication_method;
			struct ist authentication_data;
		} props;
	} var_hdr;
};

/* structure to host a MQTT packet */
struct mqtt_pkt {
	struct {
		uint8_t type;              /* MQTT_CPT_* */
		uint8_t flags;             /* MQTT_CPT_FL* */
		uint32_t remaining_length;
	} fixed_hdr;
	union {
		struct connect connect;
		struct connack connack;
	} data;
};

#endif /* _HAPROXY_MQTT_T_H */

/*
 * Local variables:
 *  c-indent-level: 8
 *  c-basic-offset: 8
 * End:
 */