1 /* packet-mysql.c
2  * Routines for mysql packet dissection
3  *
4  * Huagang XIE <huagang@intruvert.com>
5  *
6  * MySQL 4.1+ protocol by Axel Schwenke <axel@mysql.com>
7  * MariaDB protocol by Georg Richter <georg@mariadb.com>
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * Copied from packet-tftp.c
14  *
15  * SPDX-License-Identifier: GPL-2.0-or-later
16  *
17  *
18  * the protocol specifications
19  * For MySQL at
20  *  https://dev.mysql.com/doc/internals/en/client-server-protocol.html
21  * For MariaDB at
22  *  https://mariadb.com/kb/en/clientserver-protocol/
23  * and MySQL source code
24  */
25 
26 /* create extra output for conversation tracking */
27 /* #define CTDEBUG 1 */
28 
29 #include "config.h"
30 
31 #include <epan/packet.h>
32 #include <epan/prefs.h>
33 #include <epan/expert.h>
34 #include <epan/strutil.h>
35 #include <epan/proto_data.h>
36 #include "packet-tcp.h"
37 #include "packet-tls-utils.h"
38 
39 void proto_register_mysql(void);
40 void proto_reg_handoff_mysql(void);
41 
42 /* port for protocol registration */
43 #define TCP_PORT_MySQL   3306
44 
45 /* MariaDB Server >= 10.0 sends a 5.5.5- prefix for the version, since
46 	 replication doesn't support a two digit version number. Version 5.5.5
47    was never released in MySQL and MariaDB */
48 #define MARIADB_RPL_VERSION_HACK "5.5.5-"
49 
50 /* client/server capabilities
51  * Source: http://dev.mysql.com/doc/internals/en/capability-flags.html
52  * Source: mysql_com.h
53  */
54 #define MYSQL_CAPS_LP 0x0001 /* CLIENT_LONG_PASSWORD */
55 #define MYSQL_CAPS_FR 0x0002 /* CLIENT_FOUND_ROWS */
56 #define MYSQL_CAPS_LF 0x0004 /* CLIENT_LONG_FLAG */
57 #define MYSQL_CAPS_CD 0x0008 /* CLIENT_CONNECT_WITH_DB */
58 #define MYSQL_CAPS_NS 0x0010 /* CLIENT_NO_SCHEMA */
59 #define MYSQL_CAPS_CP 0x0020 /* CLIENT_COMPRESS */
60 #define MYSQL_CAPS_OB 0x0040 /* CLIENT_ODBC */
61 #define MYSQL_CAPS_LI 0x0080 /* CLIENT_LOCAL_FILES */
62 #define MYSQL_CAPS_IS 0x0100 /* CLIENT_IGNORE_SPACE */
63 #define MYSQL_CAPS_CU 0x0200 /* CLIENT_PROTOCOL_41 */
64 #define MYSQL_CAPS_IA 0x0400 /* CLIENT_INTERACTIVE */
65 #define MYSQL_CAPS_SL 0x0800 /* CLIENT_SSL */
66 #define MYSQL_CAPS_II 0x1000 /* CLIENT_IGNORE_SPACE */
67 #define MYSQL_CAPS_TA 0x2000 /* CLIENT_TRANSACTIONS */
68 #define MYSQL_CAPS_RS 0x4000 /* CLIENT_RESERVED */
69 #define MYSQL_CAPS_SC 0x8000 /* CLIENT_SECURE_CONNECTION */
70 
71 
72 /* field flags */
73 #define MYSQL_FLD_NOT_NULL_FLAG       0x0001
74 #define MYSQL_FLD_PRI_KEY_FLAG        0x0002
75 #define MYSQL_FLD_UNIQUE_KEY_FLAG     0x0004
76 #define MYSQL_FLD_MULTIPLE_KEY_FLAG   0x0008
77 #define MYSQL_FLD_BLOB_FLAG           0x0010
78 #define MYSQL_FLD_UNSIGNED_FLAG       0x0020
79 #define MYSQL_FLD_ZEROFILL_FLAG       0x0040
80 #define MYSQL_FLD_BINARY_FLAG         0x0080
81 #define MYSQL_FLD_ENUM_FLAG           0x0100
82 #define MYSQL_FLD_AUTO_INCREMENT_FLAG 0x0200
83 #define MYSQL_FLD_TIMESTAMP_FLAG      0x0400
84 #define MYSQL_FLD_SET_FLAG            0x0800
85 
86 /* extended capabilities: 4.1+ client only
87  *
88  * These are libmysqlclient flags and NOT present
89  * in the protocol:
90  * CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30)
91  * CLIENT_REMEMBER_OPTIONS (1UL << 31)
92  */
93 #define MYSQL_CAPS_MS 0x0001 /* CLIENT_MULTI_STATMENTS */
94 #define MYSQL_CAPS_MR 0x0002 /* CLIENT_MULTI_RESULTS */
95 #define MYSQL_CAPS_PM 0x0004 /* CLIENT_PS_MULTI_RESULTS */
96 #define MYSQL_CAPS_PA 0x0008 /* CLIENT_PLUGIN_AUTH */
97 #define MYSQL_CAPS_CA 0x0010 /* CLIENT_CONNECT_ATTRS */
98 #define MYSQL_CAPS_AL 0x0020 /* CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA */
99 #define MYSQL_CAPS_EP 0x0040 /* CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS */
100 #define MYSQL_CAPS_ST 0x0080 /* CLIENT_SESSION_TRACK */
101 #define MYSQL_CAPS_DE 0x0100 /* CLIENT_DEPRECATE_EOF */
102 #define MYSQL_CAPS_UNUSED 0xFE00
103 
104 /* status bitfield */
105 #define MYSQL_STAT_IT 0x0001
106 #define MYSQL_STAT_AC 0x0002
107 #define MYSQL_STAT_MU 0x0004
108 #define MYSQL_STAT_MR 0x0008
109 #define MYSQL_STAT_BI 0x0010
110 #define MYSQL_STAT_NI 0x0020
111 #define MYSQL_STAT_CR 0x0040
112 #define MYSQL_STAT_LR 0x0080
113 #define MYSQL_STAT_DR 0x0100
114 #define MYSQL_STAT_BS 0x0200
115 #define MYSQL_STAT_MC 0x0400
116 #define MYSQL_STAT_QUERY_WAS_SLOW 0x0800
117 #define MYSQL_STAT_PS_OUT_PARAMS 0x1000
118 #define MYSQL_STAT_TRANS_READONLY 0x2000
119 #define MYSQL_STAT_SESSION_STATE_CHANGED 0x4000
120 
121 /* bitfield for MYSQL_REFRESH */
122 #define MYSQL_RFSH_GRANT   1   /* Refresh grant tables */
123 #define MYSQL_RFSH_LOG     2   /* Start on new log file */
124 #define MYSQL_RFSH_TABLES  4   /* close all tables */
125 #define MYSQL_RFSH_HOSTS   8   /* Flush host cache */
126 #define MYSQL_RFSH_STATUS  16  /* Flush status variables */
127 #define MYSQL_RFSH_THREADS 32  /* Flush thread cache */
128 #define MYSQL_RFSH_SLAVE   64  /* Reset master info and restart slave thread */
129 #define MYSQL_RFSH_MASTER  128 /* Remove all bin logs in the index and truncate the index */
130 
131 /* MySQL command codes (enum_server_command in mysql-server.git:include/my_command.h) */
132 #define MYSQL_SLEEP               0  /* not from client */
133 #define MYSQL_QUIT                1
134 #define MYSQL_INIT_DB             2
135 #define MYSQL_QUERY               3
136 #define MYSQL_FIELD_LIST          4
137 #define MYSQL_CREATE_DB           5
138 #define MYSQL_DROP_DB             6
139 #define MYSQL_REFRESH             7
140 #define MYSQL_SHUTDOWN            8
141 #define MYSQL_STATISTICS          9
142 #define MYSQL_PROCESS_INFO        10
143 #define MYSQL_CONNECT             11 /* not from client */
144 #define MYSQL_PROCESS_KILL        12
145 #define MYSQL_DEBUG               13
146 #define MYSQL_PING                14
147 #define MYSQL_TIME                15 /* not from client */
148 #define MYSQL_DELAY_INSERT        16 /* not from client */
149 #define MYSQL_CHANGE_USER         17
150 #define MYSQL_BINLOG_DUMP         18 /* replication */
151 #define MYSQL_TABLE_DUMP          19 /* replication */
152 #define MYSQL_CONNECT_OUT         20 /* replication */
153 #define MYSQL_REGISTER_SLAVE      21 /* replication */
154 #define MYSQL_STMT_PREPARE        22
155 #define MYSQL_STMT_EXECUTE        23
156 #define MYSQL_STMT_SEND_LONG_DATA 24
157 #define MYSQL_STMT_CLOSE          25
158 #define MYSQL_STMT_RESET          26
159 #define MYSQL_SET_OPTION          27
160 #define MYSQL_STMT_FETCH          28
161 #define MYSQL_DAEMON              29
162 #define MYSQL_BINLOG_DUMP_GTID    30 /* replication */
163 #define MYSQL_RESET_CONNECTION    31
164 
165 /* MariaDB specific commands */
166 #define MARIADB_STMT_BULK_EXECUTE 250
167 
168 /* MariaDB bulk execute flags */
169 #define MARIADB_BULK_AUTOID      64
170 #define MARIADB_BULK_SEND_TYPES 128
171 
172 /* MariaDB extended capabilities */
173 #define MARIADB_CAPS_PR 0x0001 /* MARIADB_CLIENT_PROGRESS */
174 #define MARIADB_CAPS_CM 0x0002 /* MARIADB_CLIENT_COM_MULTI */
175 #define MARIADB_CAPS_BO 0x0004 /* MARIADB_CLIENT_STMT_BULK_OPERATIONS */
176 #define MARIADB_CAPS_EM 0x0008 /* MARIADB_CLIENT_EXTENDED_METADATA */
177 
178 /* MariaDB bulk indicators */
179 #define MARIADB_INDICATOR_NONE       0
180 #define MARIADB_INDICATOR_NULL       1
181 #define MARIADB_INDICATOR_DEFAULT    2
182 #define MARIADB_INDICATOR_IGNORE     3
183 #define MARIADB_INDICATIR_IGNORE_ROW 4
184 
185 
186 /* MySQL cursor types */
187 
188 #define MYSQL_CURSOR_TYPE_NO_CURSOR  0
189 #define MYSQL_CURSOR_TYPE_READ_ONLY  1
190 #define MYSQL_CURSOR_TYPE_FOR_UPDATE 2
191 #define MYSQL_CURSOR_TYPE_SCROLLABLE 4
192 
193 /* MySQL parameter flags -- used internally by the dissector */
194 
195 #define MYSQL_PARAM_FLAG_STREAMED 0x01
196 
197 /* Compression states, internal to the dissector */
198 #define MYSQL_COMPRESS_NONE   0
199 #define MYSQL_COMPRESS_INIT   1
200 #define MYSQL_COMPRESS_ACTIVE 2
201 
202 /* Generic Response Codes */
203 #define MYSQL_RESPONSE_OK   0x00
204 #define MYSQL_RESPONSE_ERR  0xFF
205 #define MYSQL_RESPONSE_EOF  0xFE
206 
207 /* decoding table: command */
208 static const value_string mysql_command_vals[] = {
209 	{MYSQL_SLEEP,   "SLEEP"},
210 	{MYSQL_QUIT,   "Quit"},
211 	{MYSQL_INIT_DB,  "Use Database"},
212 	{MYSQL_QUERY,   "Query"},
213 	{MYSQL_FIELD_LIST, "Show Fields"},
214 	{MYSQL_CREATE_DB,  "Create Database"},
215 	{MYSQL_DROP_DB , "Drop Database"},
216 	{MYSQL_REFRESH , "Refresh"},
217 	{MYSQL_SHUTDOWN , "Shutdown"},
218 	{MYSQL_STATISTICS , "Statistics"},
219 	{MYSQL_PROCESS_INFO , "Process List"},
220 	{MYSQL_CONNECT , "Connect"},
221 	{MYSQL_PROCESS_KILL , "Kill Server Thread"},
222 	{MYSQL_DEBUG , "Dump Debuginfo"},
223 	{MYSQL_PING , "Ping"},
224 	{MYSQL_TIME , "Time"},
225 	{MYSQL_DELAY_INSERT , "Insert Delayed"},
226 	{MYSQL_CHANGE_USER , "Change User"},
227 	{MYSQL_BINLOG_DUMP , "Send Binlog"},
228 	{MYSQL_TABLE_DUMP, "Send Table"},
229 	{MYSQL_CONNECT_OUT, "Slave Connect"},
230 	{MYSQL_REGISTER_SLAVE, "Register Slave"},
231 	{MYSQL_STMT_PREPARE, "Prepare Statement"},
232 	{MYSQL_STMT_EXECUTE, "Execute Statement"},
233 	{MYSQL_STMT_SEND_LONG_DATA, "Send BLOB"},
234 	{MYSQL_STMT_CLOSE, "Close Statement"},
235 	{MYSQL_STMT_RESET, "Reset Statement"},
236 	{MYSQL_SET_OPTION, "Set Option"},
237 	{MYSQL_STMT_FETCH, "Fetch Data"},
238 	{MYSQL_DAEMON, "Daemon"},
239 	{MYSQL_BINLOG_DUMP_GTID, "Send Binlog GTID"},
240 	{MYSQL_RESET_CONNECTION, "Reset Connection"},
241 	{MARIADB_STMT_BULK_EXECUTE, "Execute Bulk Statement"},
242 	{0, NULL}
243 };
244 static value_string_ext mysql_command_vals_ext = VALUE_STRING_EXT_INIT(mysql_command_vals);
245 
246 /* decoding table: exec_flags */
247 static const value_string mysql_exec_flags_vals[] = {
248 	{MYSQL_CURSOR_TYPE_NO_CURSOR, "Defaults"},
249 	{MYSQL_CURSOR_TYPE_READ_ONLY, "Read-only cursor"},
250 	{MYSQL_CURSOR_TYPE_FOR_UPDATE, "Cursor for update"},
251 	{MYSQL_CURSOR_TYPE_SCROLLABLE, "Scrollable cursor"},
252 	{0, NULL}
253 };
254 
255 /* decoding table: new_parameter_bound_flag */
256 static const value_string mysql_new_parameter_bound_flag_vals[] = {
257 	{0, "Subsequent call"},
258 	{1, "First call or rebound"},
259 	{0, NULL}
260 };
261 /*
262 static const value_string mariadb_bulk_flags_vals[] = {
263 	{MARIADB_BULK_AUTOID, "Return auto generated IDs"},
264 	{MARIADB_BULK_SEND_TYPES, "Send types to server"},
265 	{0, NULL}
266 };
267 */
268 static const value_string mariadb_bulk_indicator_vals[] = {
269 	{MARIADB_INDICATOR_NONE, "Not set"},
270 	{MARIADB_INDICATOR_NULL, "Null Value"},
271 	{MARIADB_INDICATOR_DEFAULT, "Default Value"},
272 	{MARIADB_INDICATOR_IGNORE, "Don't Update Value"},
273 	{MARIADB_INDICATIR_IGNORE_ROW, "Ignore Row"},
274 	{0, NULL}
275 };
276 
277 /* decoding table: exec_time_sign */
278 static const value_string mysql_exec_time_sign_vals[] = {
279 	{0, "Positive"},
280 	{1, "Negative"},
281 	{0, NULL}
282 };
283 
284 #if 0
285 /* charset: pre-4.1 used the term 'charset', later changed to 'collation' */
286 static const value_string mysql_charset_vals[] = {
287 	{1,  "big5"},
288 	{2,  "czech"},
289 	{3,  "dec8"},
290 	{4,  "dos" },
291 	{5,  "german1"},
292 	{6,  "hp8"},
293 	{7,  "koi8_ru"},
294 	{8,  "latin1"},
295 	{9,  "latin2"},
296 	{9,  "swe7 "},
297 	{10, "usa7"},
298 	{11, "ujis"},
299 	{12, "sjis"},
300 	{13, "cp1251"},
301 	{14, "danish"},
302 	{15, "hebrew"},
303 	{16, "win1251"},
304 	{17, "tis620"},
305 	{18, "euc_kr"},
306 	{19, "estonia"},
307 	{20, "hungarian"},
308 	{21, "koi8_ukr"},
309 	{22, "win1251ukr"},
310 	{23, "gb2312"},
311 	{24, "greek"},
312 	{25, "win1250"},
313 	{26, "croat"},
314 	{27, "gbk"},
315 	{28, "cp1257"},
316 	{29, "latin5"},
317 	{0, NULL}
318 };
319 #endif
320 
321 
322 /* collation codes may change over time, recreate with the following SQL
323 
324 SELECT CONCAT('  {', ID, ',"', CHARACTER_SET_NAME, ' COLLATE ', COLLATION_NAME, '"},')
325 FROM INFORMATION_SCHEMA.COLLATIONS
326 ORDER BY ID
327 INTO OUTFILE '/tmp/mysql-collations';
328 
329 Last Update from MySQL 8.0.20
330 
331 */
332 static const value_string mysql_collation_vals[] = {
333 	{3,   "dec8 COLLATE dec8_swedish_ci"},
334 	{4,   "cp850 COLLATE cp850_general_ci"},
335 	{5,   "latin1 COLLATE latin1_german1_ci"},
336 	{6,   "hp8 COLLATE hp8_english_ci"},
337 	{7,   "koi8r COLLATE koi8r_general_ci"},
338 	{8,   "latin1 COLLATE latin1_swedish_ci"},
339 	{9,   "latin2 COLLATE latin2_general_ci"},
340 	{10,  "swe7 COLLATE swe7_swedish_ci"},
341 	{11,  "ascii COLLATE ascii_general_ci"},
342 	{14,  "cp1251 COLLATE cp1251_bulgarian_ci"},
343 	{15,  "latin1 COLLATE latin1_danish_ci"},
344 	{16,  "hebrew COLLATE hebrew_general_ci"},
345 	{20,  "latin7 COLLATE latin7_estonian_cs"},
346 	{21,  "latin2 COLLATE latin2_hungarian_ci"},
347 	{22,  "koi8u COLLATE koi8u_general_ci"},
348 	{23,  "cp1251 COLLATE cp1251_ukrainian_ci"},
349 	{25,  "greek COLLATE greek_general_ci"},
350 	{26,  "cp1250 COLLATE cp1250_general_ci"},
351 	{27,  "latin2 COLLATE latin2_croatian_ci"},
352 	{29,  "cp1257 COLLATE cp1257_lithuanian_ci"},
353 	{30,  "latin5 COLLATE latin5_turkish_ci"},
354 	{31,  "latin1 COLLATE latin1_german2_ci"},
355 	{32,  "armscii8 COLLATE armscii8_general_ci"},
356 	{33,  "utf8 COLLATE utf8_general_ci"},
357 	{36,  "cp866 COLLATE cp866_general_ci"},
358 	{37,  "keybcs2 COLLATE keybcs2_general_ci"},
359 	{38,  "macce COLLATE macce_general_ci"},
360 	{39,  "macroman COLLATE macroman_general_ci"},
361 	{40,  "cp852 COLLATE cp852_general_ci"},
362 	{41,  "latin7 COLLATE latin7_general_ci"},
363 	{42,  "latin7 COLLATE latin7_general_cs"},
364 	{43,  "macce COLLATE macce_bin"},
365 	{44,  "cp1250 COLLATE cp1250_croatian_ci"},
366 	{45,  "utf8mb4 COLLATE utf8mb4_general_ci"},
367 	{46,  "utf8mb4 COLLATE utf8mb4_bin"},
368 	{47,  "latin1 COLLATE latin1_bin"},
369 	{48,  "latin1 COLLATE latin1_general_ci"},
370 	{49,  "latin1 COLLATE latin1_general_cs"},
371 	{50,  "cp1251 COLLATE cp1251_bin"},
372 	{51,  "cp1251 COLLATE cp1251_general_ci"},
373 	{52,  "cp1251 COLLATE cp1251_general_cs"},
374 	{53,  "macroman COLLATE macroman_bin"},
375 	{57,  "cp1256 COLLATE cp1256_general_ci"},
376 	{58,  "cp1257 COLLATE cp1257_bin"},
377 	{59,  "cp1257 COLLATE cp1257_general_ci"},
378 	{63,  "binary COLLATE binary"},
379 	{64,  "armscii8 COLLATE armscii8_bin"},
380 	{65,  "ascii COLLATE ascii_bin"},
381 	{66,  "cp1250 COLLATE cp1250_bin"},
382 	{67,  "cp1256 COLLATE cp1256_bin"},
383 	{68,  "cp866 COLLATE cp866_bin"},
384 	{69,  "dec8 COLLATE dec8_bin"},
385 	{70,  "greek COLLATE greek_bin"},
386 	{71,  "hebrew COLLATE hebrew_bin"},
387 	{72,  "hp8 COLLATE hp8_bin"},
388 	{73,  "keybcs2 COLLATE keybcs2_bin"},
389 	{74,  "koi8r COLLATE koi8r_bin"},
390 	{75,  "koi8u COLLATE koi8u_bin"},
391 	{77,  "latin2 COLLATE latin2_bin"},
392 	{78,  "latin5 COLLATE latin5_bin"},
393 	{79,  "latin7 COLLATE latin7_bin"},
394 	{80,  "cp850 COLLATE cp850_bin"},
395 	{81,  "cp852 COLLATE cp852_bin"},
396 	{82,  "swe7 COLLATE swe7_bin"},
397 	{83,  "utf8 COLLATE utf8_bin"},
398 	{92,  "geostd8 COLLATE geostd8_general_ci"},
399 	{93,  "geostd8 COLLATE geostd8_bin"},
400 	{94,  "latin1 COLLATE latin1_spanish_ci"},
401 	{99,  "cp1250 COLLATE cp1250_polish_ci"},
402 	{192, "utf8 COLLATE utf8_unicode_ci"},
403 	{193, "utf8 COLLATE utf8_icelandic_ci"},
404 	{194, "utf8 COLLATE utf8_latvian_ci"},
405 	{195, "utf8 COLLATE utf8_romanian_ci"},
406 	{196, "utf8 COLLATE utf8_slovenian_ci"},
407 	{197, "utf8 COLLATE utf8_polish_ci"},
408 	{198, "utf8 COLLATE utf8_estonian_ci"},
409 	{199, "utf8 COLLATE utf8_spanish_ci"},
410 	{200, "utf8 COLLATE utf8_swedish_ci"},
411 	{201, "utf8 COLLATE utf8_turkish_ci"},
412 	{202, "utf8 COLLATE utf8_czech_ci"},
413 	{203, "utf8 COLLATE utf8_danish_ci"},
414 	{204, "utf8 COLLATE utf8_lithuanian_ci"},
415 	{205, "utf8 COLLATE utf8_slovak_ci"},
416 	{206, "utf8 COLLATE utf8_spanish2_ci"},
417 	{207, "utf8 COLLATE utf8_roman_ci"},
418 	{208, "utf8 COLLATE utf8_persian_ci"},
419 	{209, "utf8 COLLATE utf8_esperanto_ci"},
420 	{210, "utf8 COLLATE utf8_hungarian_ci"},
421 	{211, "utf8 COLLATE utf8_sinhala_ci"},
422 	{212, "utf8 COLLATE utf8_german2_ci"},
423 	{213, "utf8 COLLATE utf8_croatian_ci"},
424 	{214, "utf8 COLLATE utf8_unicode_520_ci"},
425 	{215, "utf8 COLLATE utf8_vietnamese_ci"},
426 	{223, "utf8 COLLATE utf8_general_mysql500_ci"},
427 	{224, "utf8mb4 COLLATE utf8mb4_unicode_ci"},
428 	{225, "utf8mb4 COLLATE utf8mb4_icelandic_ci"},
429 	{226, "utf8mb4 COLLATE utf8mb4_latvian_ci"},
430 	{227, "utf8mb4 COLLATE utf8mb4_romanian_ci"},
431 	{228, "utf8mb4 COLLATE utf8mb4_slovenian_ci"},
432 	{229, "utf8mb4 COLLATE utf8mb4_polish_ci"},
433 	{230, "utf8mb4 COLLATE utf8mb4_estonian_ci"},
434 	{231, "utf8mb4 COLLATE utf8mb4_spanish_ci"},
435 	{232, "utf8mb4 COLLATE utf8mb4_swedish_ci"},
436 	{233, "utf8mb4 COLLATE utf8mb4_turkish_ci"},
437 	{234, "utf8mb4 COLLATE utf8mb4_czech_ci"},
438 	{235, "utf8mb4 COLLATE utf8mb4_danish_ci"},
439 	{236, "utf8mb4 COLLATE utf8mb4_lithuanian_ci"},
440 	{237, "utf8mb4 COLLATE utf8mb4_slovak_ci"},
441 	{238, "utf8mb4 COLLATE utf8mb4_spanish2_ci"},
442 	{239, "utf8mb4 COLLATE utf8mb4_roman_ci"},
443 	{240, "utf8mb4 COLLATE utf8mb4_persian_ci"},
444 	{241, "utf8mb4 COLLATE utf8mb4_esperanto_ci"},
445 	{242, "utf8mb4 COLLATE utf8mb4_hungarian_ci"},
446 	{243, "utf8mb4 COLLATE utf8mb4_sinhala_ci"},
447 	{244, "utf8mb4 COLLATE utf8mb4_german2_ci"},
448 	{245, "utf8mb4 COLLATE utf8mb4_croatian_ci"},
449 	{246, "utf8mb4 COLLATE utf8mb4_unicode_520_ci"},
450 	{247, "utf8mb4 COLLATE utf8mb4_vietnamese_ci"},
451 	{248,"gb18030 COLLATE gb18030_chinese_ci"},
452 	{249,"gb18030 COLLATE gb18030_bin"},
453 	{250,"gb18030 COLLATE gb18030_unicode_520_ci"},
454 	{255,"utf8mb4 COLLATE utf8mb4_0900_ai_ci"},
455 	{256,"utf8mb4 COLLATE utf8mb4_de_pb_0900_ai_ci"},
456 	{257,"utf8mb4 COLLATE utf8mb4_is_0900_ai_ci"},
457 	{258,"utf8mb4 COLLATE utf8mb4_lv_0900_ai_ci"},
458 	{259,"utf8mb4 COLLATE utf8mb4_ro_0900_ai_ci"},
459 	{260,"utf8mb4 COLLATE utf8mb4_sl_0900_ai_ci"},
460 	{261,"utf8mb4 COLLATE utf8mb4_pl_0900_ai_ci"},
461 	{262,"utf8mb4 COLLATE utf8mb4_et_0900_ai_ci"},
462 	{263,"utf8mb4 COLLATE utf8mb4_es_0900_ai_ci"},
463 	{264,"utf8mb4 COLLATE utf8mb4_sv_0900_ai_ci"},
464 	{265,"utf8mb4 COLLATE utf8mb4_tr_0900_ai_ci"},
465 	{266,"utf8mb4 COLLATE utf8mb4_cs_0900_ai_ci"},
466 	{267,"utf8mb4 COLLATE utf8mb4_da_0900_ai_ci"},
467 	{268,"utf8mb4 COLLATE utf8mb4_lt_0900_ai_ci"},
468 	{269,"utf8mb4 COLLATE utf8mb4_sk_0900_ai_ci"},
469 	{270,"utf8mb4 COLLATE utf8mb4_es_trad_0900_ai_ci"},
470 	{271,"utf8mb4 COLLATE utf8mb4_la_0900_ai_ci"},
471 	{273,"utf8mb4 COLLATE utf8mb4_eo_0900_ai_ci"},
472 	{274,"utf8mb4 COLLATE utf8mb4_hu_0900_ai_ci"},
473 	{275,"utf8mb4 COLLATE utf8mb4_hr_0900_ai_ci"},
474 	{277,"utf8mb4 COLLATE utf8mb4_vi_0900_ai_ci"},
475 	{278,"utf8mb4 COLLATE utf8mb4_0900_as_cs"},
476 	{279,"utf8mb4 COLLATE utf8mb4_de_pb_0900_as_cs"},
477 	{280,"utf8mb4 COLLATE utf8mb4_is_0900_as_cs"},
478 	{281,"utf8mb4 COLLATE utf8mb4_lv_0900_as_cs"},
479 	{282,"utf8mb4 COLLATE utf8mb4_ro_0900_as_cs"},
480 	{283,"utf8mb4 COLLATE utf8mb4_sl_0900_as_cs"},
481 	{284,"utf8mb4 COLLATE utf8mb4_pl_0900_as_cs"},
482 	{285,"utf8mb4 COLLATE utf8mb4_et_0900_as_cs"},
483 	{286,"utf8mb4 COLLATE utf8mb4_es_0900_as_cs"},
484 	{287,"utf8mb4 COLLATE utf8mb4_sv_0900_as_cs"},
485 	{288,"utf8mb4 COLLATE utf8mb4_tr_0900_as_cs"},
486 	{289,"utf8mb4 COLLATE utf8mb4_cs_0900_as_cs"},
487 	{290,"utf8mb4 COLLATE utf8mb4_da_0900_as_cs"},
488 	{291,"utf8mb4 COLLATE utf8mb4_lt_0900_as_cs"},
489 	{292,"utf8mb4 COLLATE utf8mb4_sk_0900_as_cs"},
490 	{293,"utf8mb4 COLLATE utf8mb4_es_trad_0900_as_cs"},
491 	{294,"utf8mb4 COLLATE utf8mb4_la_0900_as_cs"},
492 	{296,"utf8mb4 COLLATE utf8mb4_eo_0900_as_cs"},
493 	{297,"utf8mb4 COLLATE utf8mb4_hu_0900_as_cs"},
494 	{298,"utf8mb4 COLLATE utf8mb4_hr_0900_as_cs"},
495 	{300,"utf8mb4 COLLATE utf8mb4_vi_0900_as_cs"},
496 	{303,"utf8mb4 COLLATE utf8mb4_ja_0900_as_cs"},
497 	{304,"utf8mb4 COLLATE utf8mb4_ja_0900_as_cs_ks"},
498 	{305,"utf8mb4 COLLATE utf8mb4_0900_as_ci"},
499 	{306,"utf8mb4 COLLATE utf8mb4_ru_0900_ai_ci"},
500 	{307,"utf8mb4 COLLATE utf8mb4_ru_0900_as_cs"},
501 	{308,"utf8mb4 COLLATE utf8mb4_zh_0900_as_cs"},
502 	{309,"utf8mb4 COLLATE utf8mb4_0900_bin"},
503 	{0, NULL}
504 };
505 
506 
507 static value_string_ext mysql_collation_vals_ext = VALUE_STRING_EXT_INIT(mysql_collation_vals);
508 
509 /* MariaDB specific character sets and collations
510 
511    Last Update: MariaDB 10.5.4 */
512 
513 static const value_string mariadb_collation_vals[] = {
514 	{1,"big5 COLLATE big5_chinese_ci"},
515 	{2,"latin2 COLLATE latin2_czech_cs"},
516 	{3,"dec8 COLLATE dec8_swedish_ci"},
517 	{4,"cp850 COLLATE cp850_general_ci"},
518 	{5,"latin1 COLLATE latin1_german1_ci"},
519 	{6,"hp8 COLLATE hp8_english_ci"},
520 	{7,"koi8r COLLATE koi8r_general_ci"},
521 	{8,"latin1 COLLATE latin1_swedish_ci"},
522 	{9,"latin2 COLLATE latin2_general_ci"},
523 	{10,"swe7 COLLATE swe7_swedish_ci"},
524 	{11,"ascii COLLATE ascii_general_ci"},
525 	{12,"ujis COLLATE ujis_japanese_ci"},
526 	{13,"sjis COLLATE sjis_japanese_ci"},
527 	{14,"cp1251 COLLATE cp1251_bulgarian_ci"},
528 	{15,"latin1 COLLATE latin1_danish_ci"},
529 	{16,"hebrew COLLATE hebrew_general_ci"},
530 	{18,"tis620 COLLATE tis620_thai_ci"},
531 	{19,"euckr COLLATE euckr_korean_ci"},
532 	{20,"latin7 COLLATE latin7_estonian_cs"},
533 	{21,"latin2 COLLATE latin2_hungarian_ci"},
534 	{22,"koi8u COLLATE koi8u_general_ci"},
535 	{23,"cp1251 COLLATE cp1251_ukrainian_ci"},
536 	{24,"gb2312 COLLATE gb2312_chinese_ci"},
537 	{25,"greek COLLATE greek_general_ci"},
538 	{26,"cp1250 COLLATE cp1250_general_ci"},
539 	{27,"latin2 COLLATE latin2_croatian_ci"},
540 	{28,"gbk COLLATE gbk_chinese_ci"},
541 	{29,"cp1257 COLLATE cp1257_lithuanian_ci"},
542 	{30,"latin5 COLLATE latin5_turkish_ci"},
543 	{31,"latin1 COLLATE latin1_german2_ci"},
544 	{32,"armscii8 COLLATE armscii8_general_ci"},
545 	{33,"utf8 COLLATE utf8_general_ci"},
546 	{34,"cp1250 COLLATE cp1250_czech_cs"},
547 	{35,"ucs2 COLLATE ucs2_general_ci"},
548 	{36,"cp866 COLLATE cp866_general_ci"},
549 	{37,"keybcs2 COLLATE keybcs2_general_ci"},
550 	{38,"macce COLLATE macce_general_ci"},
551 	{39,"macroman COLLATE macroman_general_ci"},
552 	{40,"cp852 COLLATE cp852_general_ci"},
553 	{41,"latin7 COLLATE latin7_general_ci"},
554 	{42,"latin7 COLLATE latin7_general_cs"},
555 	{43,"macce COLLATE macce_bin"},
556 	{44,"cp1250 COLLATE cp1250_croatian_ci"},
557 	{45,"utf8mb4 COLLATE utf8mb4_general_ci"},
558 	{46,"utf8mb4 COLLATE utf8mb4_bin"},
559 	{47,"latin1 COLLATE latin1_bin"},
560 	{48,"latin1 COLLATE latin1_general_ci"},
561 	{49,"latin1 COLLATE latin1_general_cs"},
562 	{50,"cp1251 COLLATE cp1251_bin"},
563 	{51,"cp1251 COLLATE cp1251_general_ci"},
564 	{52,"cp1251 COLLATE cp1251_general_cs"},
565 	{53,"macroman COLLATE macroman_bin"},
566 	{54,"utf16 COLLATE utf16_general_ci"},
567 	{55,"utf16 COLLATE utf16_bin"},
568 	{56,"utf16le COLLATE utf16le_general_ci"},
569 	{57,"cp1256 COLLATE cp1256_general_ci"},
570 	{58,"cp1257 COLLATE cp1257_bin"},
571 	{59,"cp1257 COLLATE cp1257_general_ci"},
572 	{60,"utf32 COLLATE utf32_general_ci"},
573 	{61,"utf32 COLLATE utf32_bin"},
574 	{62,"utf16le COLLATE utf16le_bin"},
575 	{63,"binary COLLATE binary"},
576 	{64,"armscii8 COLLATE armscii8_bin"},
577 	{65,"ascii COLLATE ascii_bin"},
578 	{66,"cp1250 COLLATE cp1250_bin"},
579 	{67,"cp1256 COLLATE cp1256_bin"},
580 	{68,"cp866 COLLATE cp866_bin"},
581 	{69,"dec8 COLLATE dec8_bin"},
582 	{70,"greek COLLATE greek_bin"},
583 	{71,"hebrew COLLATE hebrew_bin"},
584 	{72,"hp8 COLLATE hp8_bin"},
585 	{73,"keybcs2 COLLATE keybcs2_bin"},
586 	{74,"koi8r COLLATE koi8r_bin"},
587 	{75,"koi8u COLLATE koi8u_bin"},
588 	{77,"latin2 COLLATE latin2_bin"},
589 	{78,"latin5 COLLATE latin5_bin"},
590 	{79,"latin7 COLLATE latin7_bin"},
591 	{80,"cp850 COLLATE cp850_bin"},
592 	{81,"cp852 COLLATE cp852_bin"},
593 	{82,"swe7 COLLATE swe7_bin"},
594 	{83,"utf8 COLLATE utf8_bin"},
595 	{84,"big5 COLLATE big5_bin"},
596 	{85,"euckr COLLATE euckr_bin"},
597 	{86,"gb2312 COLLATE gb2312_bin"},
598 	{87,"gbk COLLATE gbk_bin"},
599 	{88,"sjis COLLATE sjis_bin"},
600 	{89,"tis620 COLLATE tis620_bin"},
601 	{90,"ucs2 COLLATE ucs2_bin"},
602 	{91,"ujis COLLATE ujis_bin"},
603 	{92,"geostd8 COLLATE geostd8_general_ci"},
604 	{93,"geostd8 COLLATE geostd8_bin"},
605 	{94,"latin1 COLLATE latin1_spanish_ci"},
606 	{95,"cp932 COLLATE cp932_japanese_ci"},
607 	{96,"cp932 COLLATE cp932_bin"},
608 	{97,"eucjpms COLLATE eucjpms_japanese_ci"},
609 	{98,"eucjpms COLLATE eucjpms_bin"},
610 	{99,"cp1250 COLLATE cp1250_polish_ci"},
611 	{101,"utf16 COLLATE utf16_unicode_ci"},
612 	{102,"utf16 COLLATE utf16_icelandic_ci"},
613 	{103,"utf16 COLLATE utf16_latvian_ci"},
614 	{104,"utf16 COLLATE utf16_romanian_ci"},
615 	{105,"utf16 COLLATE utf16_slovenian_ci"},
616 	{106,"utf16 COLLATE utf16_polish_ci"},
617 	{107,"utf16 COLLATE utf16_estonian_ci"},
618 	{108,"utf16 COLLATE utf16_spanish_ci"},
619 	{109,"utf16 COLLATE utf16_swedish_ci"},
620 	{110,"utf16 COLLATE utf16_turkish_ci"},
621 	{111,"utf16 COLLATE utf16_czech_ci"},
622 	{112,"utf16 COLLATE utf16_danish_ci"},
623 	{113,"utf16 COLLATE utf16_lithuanian_ci"},
624 	{114,"utf16 COLLATE utf16_slovak_ci"},
625 	{115,"utf16 COLLATE utf16_spanish2_ci"},
626 	{116,"utf16 COLLATE utf16_roman_ci"},
627 	{117,"utf16 COLLATE utf16_persian_ci"},
628 	{118,"utf16 COLLATE utf16_esperanto_ci"},
629 	{119,"utf16 COLLATE utf16_hungarian_ci"},
630 	{120,"utf16 COLLATE utf16_sinhala_ci"},
631 	{121,"utf16 COLLATE utf16_german2_ci"},
632 	{122,"utf16 COLLATE utf16_croatian_mysql561_ci"},
633 	{123,"utf16 COLLATE utf16_unicode_520_ci"},
634 	{124,"utf16 COLLATE utf16_vietnamese_ci"},
635 	{128,"ucs2 COLLATE ucs2_unicode_ci"},
636 	{129,"ucs2 COLLATE ucs2_icelandic_ci"},
637 	{130,"ucs2 COLLATE ucs2_latvian_ci"},
638 	{131,"ucs2 COLLATE ucs2_romanian_ci"},
639 	{132,"ucs2 COLLATE ucs2_slovenian_ci"},
640 	{133,"ucs2 COLLATE ucs2_polish_ci"},
641 	{134,"ucs2 COLLATE ucs2_estonian_ci"},
642 	{135,"ucs2 COLLATE ucs2_spanish_ci"},
643 	{136,"ucs2 COLLATE ucs2_swedish_ci"},
644 	{137,"ucs2 COLLATE ucs2_turkish_ci"},
645 	{138,"ucs2 COLLATE ucs2_czech_ci"},
646 	{139,"ucs2 COLLATE ucs2_danish_ci"},
647 	{140,"ucs2 COLLATE ucs2_lithuanian_ci"},
648 	{141,"ucs2 COLLATE ucs2_slovak_ci"},
649 	{142,"ucs2 COLLATE ucs2_spanish2_ci"},
650 	{143,"ucs2 COLLATE ucs2_roman_ci"},
651 	{144,"ucs2 COLLATE ucs2_persian_ci"},
652 	{145,"ucs2 COLLATE ucs2_esperanto_ci"},
653 	{146,"ucs2 COLLATE ucs2_hungarian_ci"},
654 	{147,"ucs2 COLLATE ucs2_sinhala_ci"},
655 	{148,"ucs2 COLLATE ucs2_german2_ci"},
656 	{149,"ucs2 COLLATE ucs2_croatian_mysql561_ci"},
657 	{150,"ucs2 COLLATE ucs2_unicode_520_ci"},
658 	{151,"ucs2 COLLATE ucs2_vietnamese_ci"},
659 	{159,"ucs2 COLLATE ucs2_general_mysql500_ci"},
660 	{160,"utf32 COLLATE utf32_unicode_ci"},
661 	{161,"utf32 COLLATE utf32_icelandic_ci"},
662 	{162,"utf32 COLLATE utf32_latvian_ci"},
663 	{163,"utf32 COLLATE utf32_romanian_ci"},
664 	{164,"utf32 COLLATE utf32_slovenian_ci"},
665 	{165,"utf32 COLLATE utf32_polish_ci"},
666 	{166,"utf32 COLLATE utf32_estonian_ci"},
667 	{167,"utf32 COLLATE utf32_spanish_ci"},
668 	{168,"utf32 COLLATE utf32_swedish_ci"},
669 	{169,"utf32 COLLATE utf32_turkish_ci"},
670 	{170,"utf32 COLLATE utf32_czech_ci"},
671 	{171,"utf32 COLLATE utf32_danish_ci"},
672 	{172,"utf32 COLLATE utf32_lithuanian_ci"},
673 	{173,"utf32 COLLATE utf32_slovak_ci"},
674 	{174,"utf32 COLLATE utf32_spanish2_ci"},
675 	{175,"utf32 COLLATE utf32_roman_ci"},
676 	{176,"utf32 COLLATE utf32_persian_ci"},
677 	{177,"utf32 COLLATE utf32_esperanto_ci"},
678 	{178,"utf32 COLLATE utf32_hungarian_ci"},
679 	{179,"utf32 COLLATE utf32_sinhala_ci"},
680 	{180,"utf32 COLLATE utf32_german2_ci"},
681 	{181,"utf32 COLLATE utf32_croatian_mysql561_ci"},
682 	{182,"utf32 COLLATE utf32_unicode_520_ci"},
683 	{183,"utf32 COLLATE utf32_vietnamese_ci"},
684 	{192,"utf8 COLLATE utf8_unicode_ci"},
685 	{193,"utf8 COLLATE utf8_icelandic_ci"},
686 	{194,"utf8 COLLATE utf8_latvian_ci"},
687 	{195,"utf8 COLLATE utf8_romanian_ci"},
688 	{196,"utf8 COLLATE utf8_slovenian_ci"},
689 	{197,"utf8 COLLATE utf8_polish_ci"},
690 	{198,"utf8 COLLATE utf8_estonian_ci"},
691 	{199,"utf8 COLLATE utf8_spanish_ci"},
692 	{200,"utf8 COLLATE utf8_swedish_ci"},
693 	{201,"utf8 COLLATE utf8_turkish_ci"},
694 	{202,"utf8 COLLATE utf8_czech_ci"},
695 	{203,"utf8 COLLATE utf8_danish_ci"},
696 	{204,"utf8 COLLATE utf8_lithuanian_ci"},
697 	{205,"utf8 COLLATE utf8_slovak_ci"},
698 	{206,"utf8 COLLATE utf8_spanish2_ci"},
699 	{207,"utf8 COLLATE utf8_roman_ci"},
700 	{208,"utf8 COLLATE utf8_persian_ci"},
701 	{209,"utf8 COLLATE utf8_esperanto_ci"},
702 	{210,"utf8 COLLATE utf8_hungarian_ci"},
703 	{211,"utf8 COLLATE utf8_sinhala_ci"},
704 	{212,"utf8 COLLATE utf8_german2_ci"},
705 	{213,"utf8 COLLATE utf8_croatian_mysql561_ci"},
706 	{214,"utf8 COLLATE utf8_unicode_520_ci"},
707 	{215,"utf8 COLLATE utf8_vietnamese_ci"},
708 	{223,"utf8 COLLATE utf8_general_mysql500_ci"},
709 	{224,"utf8mb4 COLLATE utf8mb4_unicode_ci"},
710 	{225,"utf8mb4 COLLATE utf8mb4_icelandic_ci"},
711 	{226,"utf8mb4 COLLATE utf8mb4_latvian_ci"},
712 	{227,"utf8mb4 COLLATE utf8mb4_romanian_ci"},
713 	{228,"utf8mb4 COLLATE utf8mb4_slovenian_ci"},
714 	{229,"utf8mb4 COLLATE utf8mb4_polish_ci"},
715 	{230,"utf8mb4 COLLATE utf8mb4_estonian_ci"},
716 	{231,"utf8mb4 COLLATE utf8mb4_spanish_ci"},
717 	{232,"utf8mb4 COLLATE utf8mb4_swedish_ci"},
718 	{233,"utf8mb4 COLLATE utf8mb4_turkish_ci"},
719 	{234,"utf8mb4 COLLATE utf8mb4_czech_ci"},
720 	{235,"utf8mb4 COLLATE utf8mb4_danish_ci"},
721 	{236,"utf8mb4 COLLATE utf8mb4_lithuanian_ci"},
722 	{237,"utf8mb4 COLLATE utf8mb4_slovak_ci"},
723 	{238,"utf8mb4 COLLATE utf8mb4_spanish2_ci"},
724 	{239,"utf8mb4 COLLATE utf8mb4_roman_ci"},
725 	{240,"utf8mb4 COLLATE utf8mb4_persian_ci"},
726 	{241,"utf8mb4 COLLATE utf8mb4_esperanto_ci"},
727 	{242,"utf8mb4 COLLATE utf8mb4_hungarian_ci"},
728 	{243,"utf8mb4 COLLATE utf8mb4_sinhala_ci"},
729 	{244,"utf8mb4 COLLATE utf8mb4_german2_ci"},
730 	{245,"utf8mb4 COLLATE utf8mb4_croatian_mysql561_ci"},
731 	{246,"utf8mb4 COLLATE utf8mb4_unicode_520_ci"},
732 	{247,"utf8mb4 COLLATE utf8mb4_vietnamese_ci"},
733 	{576,"utf8 COLLATE utf8_croatian_ci"},
734 	{577,"utf8 COLLATE utf8_myanmar_ci"},
735 	{578,"utf8 COLLATE utf8_thai_520_w2"},
736 	{608,"utf8mb4 COLLATE utf8mb4_croatian_ci"},
737 	{609,"utf8mb4 COLLATE utf8mb4_myanmar_ci"},
738 	{610,"utf8mb4 COLLATE utf8mb4_thai_520_w2"},
739 	{640,"ucs2 COLLATE ucs2_croatian_ci"},
740 	{641,"ucs2 COLLATE ucs2_myanmar_ci"},
741 	{642,"ucs2 COLLATE ucs2_thai_520_w2"},
742 	{672,"utf16 COLLATE utf16_croatian_ci"},
743 	{673,"utf16 COLLATE utf16_myanmar_ci"},
744 	{674,"utf16 COLLATE utf16_thai_520_w2"},
745 	{736,"utf32 COLLATE utf32_croatian_ci"},
746 	{737,"utf32 COLLATE utf32_myanmar_ci"},
747 	{738,"utf32 COLLATE utf32_thai_520_w2"},
748 	{1025,"big5 COLLATE big5_chinese_nopad_ci"},
749 	{1027,"dec8 COLLATE dec8_swedish_nopad_ci"},
750 	{1028,"cp850 COLLATE cp850_general_nopad_ci"},
751 	{1030,"hp8 COLLATE hp8_english_nopad_ci"},
752 	{1031,"koi8r COLLATE koi8r_general_nopad_ci"},
753 	{1032,"latin1 COLLATE latin1_swedish_nopad_ci"},
754 	{1033,"latin2 COLLATE latin2_general_nopad_ci"},
755 	{1034,"swe7 COLLATE swe7_swedish_nopad_ci"},
756 	{1035,"ascii COLLATE ascii_general_nopad_ci"},
757 	{1036,"ujis COLLATE ujis_japanese_nopad_ci"},
758 	{1037,"sjis COLLATE sjis_japanese_nopad_ci"},
759 	{1040,"hebrew COLLATE hebrew_general_nopad_ci"},
760 	{1042,"tis620 COLLATE tis620_thai_nopad_ci"},
761 	{1043,"euckr COLLATE euckr_korean_nopad_ci"},
762 	{1046,"koi8u COLLATE koi8u_general_nopad_ci"},
763 	{1048,"gb2312 COLLATE gb2312_chinese_nopad_ci"},
764 	{1049,"greek COLLATE greek_general_nopad_ci"},
765 	{1050,"cp1250 COLLATE cp1250_general_nopad_ci"},
766 	{1052,"gbk COLLATE gbk_chinese_nopad_ci"},
767 	{1054,"latin5 COLLATE latin5_turkish_nopad_ci"},
768 	{1056,"armscii8 COLLATE armscii8_general_nopad_ci"},
769 	{1057,"utf8 COLLATE utf8_general_nopad_ci"},
770 	{1059,"ucs2 COLLATE ucs2_general_nopad_ci"},
771 	{1060,"cp866 COLLATE cp866_general_nopad_ci"},
772 	{1061,"keybcs2 COLLATE keybcs2_general_nopad_ci"},
773 	{1062,"macce COLLATE macce_general_nopad_ci"},
774 	{1063,"macroman COLLATE macroman_general_nopad_ci"},
775 	{1064,"cp852 COLLATE cp852_general_nopad_ci"},
776 	{1065,"latin7 COLLATE latin7_general_nopad_ci"},
777 	{1067,"macce COLLATE macce_nopad_bin"},
778 	{1069,"utf8mb4 COLLATE utf8mb4_general_nopad_ci"},
779 	{1070,"utf8mb4 COLLATE utf8mb4_nopad_bin"},
780 	{1071,"latin1 COLLATE latin1_nopad_bin"},
781 	{1074,"cp1251 COLLATE cp1251_nopad_bin"},
782 	{1075,"cp1251 COLLATE cp1251_general_nopad_ci"},
783 	{1077,"macroman COLLATE macroman_nopad_bin"},
784 	{1078,"utf16 COLLATE utf16_general_nopad_ci"},
785 	{1079,"utf16 COLLATE utf16_nopad_bin"},
786 	{1080,"utf16le COLLATE utf16le_general_nopad_ci"},
787 	{1081,"cp1256 COLLATE cp1256_general_nopad_ci"},
788 	{1082,"cp1257 COLLATE cp1257_nopad_bin"},
789 	{1083,"cp1257 COLLATE cp1257_general_nopad_ci"},
790 	{1084,"utf32 COLLATE utf32_general_nopad_ci"},
791 	{1085,"utf32 COLLATE utf32_nopad_bin"},
792 	{1086,"utf16le COLLATE utf16le_nopad_bin"},
793 	{1088,"armscii8 COLLATE armscii8_nopad_bin"},
794 	{1089,"ascii COLLATE ascii_nopad_bin"},
795 	{1090,"cp1250 COLLATE cp1250_nopad_bin"},
796 	{1091,"cp1256 COLLATE cp1256_nopad_bin"},
797 	{1092,"cp866 COLLATE cp866_nopad_bin"},
798 	{1093,"dec8 COLLATE dec8_nopad_bin"},
799 	{1094,"greek COLLATE greek_nopad_bin"},
800 	{1095,"hebrew COLLATE hebrew_nopad_bin"},
801 	{1096,"hp8 COLLATE hp8_nopad_bin"},
802 	{1097,"keybcs2 COLLATE keybcs2_nopad_bin"},
803 	{1098,"koi8r COLLATE koi8r_nopad_bin"},
804 	{1099,"koi8u COLLATE koi8u_nopad_bin"},
805 	{1101,"latin2 COLLATE latin2_nopad_bin"},
806 	{1102,"latin5 COLLATE latin5_nopad_bin"},
807 	{1103,"latin7 COLLATE latin7_nopad_bin"},
808 	{1104,"cp850 COLLATE cp850_nopad_bin"},
809 	{1105,"cp852 COLLATE cp852_nopad_bin"},
810 	{1106,"swe7 COLLATE swe7_nopad_bin"},
811 	{1107,"utf8 COLLATE utf8_nopad_bin"},
812 	{1108,"big5 COLLATE big5_nopad_bin"},
813 	{1109,"euckr COLLATE euckr_nopad_bin"},
814 	{1110,"gb2312 COLLATE gb2312_nopad_bin"},
815 	{1111,"gbk COLLATE gbk_nopad_bin"},
816 	{1112,"sjis COLLATE sjis_nopad_bin"},
817 	{1113,"tis620 COLLATE tis620_nopad_bin"},
818 	{1114,"ucs2 COLLATE ucs2_nopad_bin"},
819 	{1115,"ujis COLLATE ujis_nopad_bin"},
820 	{1116,"geostd8 COLLATE geostd8_general_nopad_ci"},
821 	{1117,"geostd8 COLLATE geostd8_nopad_bin"},
822 	{1119,"cp932 COLLATE cp932_japanese_nopad_ci"},
823 	{1120,"cp932 COLLATE cp932_nopad_bin"},
824 	{1121,"eucjpms COLLATE eucjpms_japanese_nopad_ci"},
825 	{1122,"eucjpms COLLATE eucjpms_nopad_bin"},
826 	{1125,"utf16 COLLATE utf16_unicode_nopad_ci"},
827 	{1147,"utf16 COLLATE utf16_unicode_520_nopad_ci"},
828 	{1152,"ucs2 COLLATE ucs2_unicode_nopad_ci"},
829 	{1174,"ucs2 COLLATE ucs2_unicode_520_nopad_ci"},
830 	{1184,"utf32 COLLATE utf32_unicode_nopad_ci"},
831 	{1206,"utf32 COLLATE utf32_unicode_520_nopad_ci"},
832 	{1216,"utf8 COLLATE utf8_unicode_nopad_ci"},
833 	{1238,"utf8 COLLATE utf8_unicode_520_nopad_ci"},
834 	{1248,"utf8mb4 COLLATE utf8mb4_unicode_nopad_ci"},
835 	{1270,"utf8mb4 COLLATE utf8mb4_unicode_520_nopad_ci"},
836 	{0, NULL}
837 };
838 
839 
840 static value_string_ext mariadb_collation_vals_ext = VALUE_STRING_EXT_INIT(mariadb_collation_vals);
841 
842 
843 /* allowed MYSQL_SHUTDOWN levels */
844 static const value_string mysql_shutdown_vals[] = {
845 	{0,   "default"},
846 	{1,   "wait for connections to finish"},
847 	{2,   "wait for transactions to finish"},
848 	{8,   "wait for updates to finish"},
849 	{16,  "wait flush all buffers"},
850 	{17,  "wait flush critical buffers"},
851 	{254, "kill running queries"},
852 	{255, "kill connections"},
853 	{0, NULL}
854 };
855 
856 
857 /* allowed MYSQL_SET_OPTION values */
858 static const value_string mysql_option_vals[] = {
859 	{0, "multi statements on"},
860 	{1, "multi statements off"},
861 	{0, NULL}
862 };
863 
864 static const value_string mysql_session_track_type_vals[] = {
865 	{0, "SESSION_SYSVARS_TRACKER"},
866 	{1, "CURRENT_SCHEMA_TRACKER"},
867 	{2, "SESSION_STATE_CHANGE_TRACKER"},
868 	{3, "SESSION_TRACK_GTIDS"},
869 	{4, "SESSION_TRACK_TRANSACTION_CHARACTERISTICS"},
870 	{5, "SESSION_TRACK_TRANSACTION_STATE"},
871 	{0, NULL}
872 };
873 
874 static const value_string mysql_response_code_vals[] = {
875     { MYSQL_RESPONSE_OK,    "OK Packet" },
876     { MYSQL_RESPONSE_ERR,   "ERR Packet" },
877     { MYSQL_RESPONSE_EOF,   "EOF Packet" },
878     { 0, NULL }
879 };
880 
881 /* protocol id */
882 static int proto_mysql = -1;
883 
884 /* dissector configuration */
885 static gboolean mysql_desegment = TRUE;
886 static gboolean mysql_showquery = FALSE;
887 
888 /* expand-the-tree flags */
889 static gint ett_mysql = -1;
890 static gint ett_server_greeting = -1;
891 static gint ett_login_request = -1;
892 static gint ett_caps = -1;
893 static gint ett_extcaps = -1;
894 static gint ett_stat = -1;
895 static gint ett_request = -1;
896 static gint ett_refresh = -1;
897 static gint ett_field_flags = -1;
898 static gint ett_exec_param = -1;
899 static gint ett_bulk_param = -1;
900 static gint ett_session_track = -1;
901 static gint ett_session_track_data = -1;
902 static gint ett_connattrs = -1;
903 static gint ett_connattrs_attr = -1;
904 static gint ett_mysql_field = -1;
905 
906 /* protocol fields */
907 static int hf_mysql_caps_server = -1;
908 static int hf_mysql_caps_client = -1;
909 static int hf_mysql_cap_long_password = -1;
910 static int hf_mysql_cap_found_rows = -1;
911 static int hf_mysql_cap_long_flag = -1;
912 static int hf_mysql_cap_connect_with_db = -1;
913 static int hf_mysql_cap_no_schema = -1;
914 static int hf_mysql_cap_compress = -1;
915 static int hf_mysql_cap_odbc = -1;
916 static int hf_mysql_cap_local_files = -1;
917 static int hf_mysql_cap_ignore_space = -1;
918 static int hf_mysql_cap_change_user = -1;
919 static int hf_mysql_cap_interactive = -1;
920 static int hf_mysql_cap_ssl = -1;
921 static int hf_mysql_cap_ignore_sigpipe = -1;
922 static int hf_mysql_cap_transactions = -1;
923 static int hf_mysql_cap_reserved = -1;
924 static int hf_mysql_cap_secure_connect = -1;
925 static int hf_mysql_extcaps_server = -1;
926 static int hf_mysql_extcaps_client = -1;
927 static int hf_mysql_cap_multi_statements = -1;
928 static int hf_mysql_cap_multi_results = -1;
929 static int hf_mysql_cap_ps_multi_results = -1;
930 static int hf_mysql_cap_plugin_auth = -1;
931 static int hf_mysql_cap_connect_attrs = -1;
932 static int hf_mysql_cap_plugin_auth_lenenc_client_data = -1;
933 static int hf_mysql_cap_client_can_handle_expired_passwords = -1;
934 static int hf_mysql_cap_session_track = -1;
935 static int hf_mysql_cap_deprecate_eof = -1;
936 static int hf_mysql_cap_unused = -1;
937 static int hf_mysql_server_language = -1;
938 static int hf_mysql_server_status = -1;
939 static int hf_mysql_stat_it = -1;
940 static int hf_mysql_stat_ac = -1;
941 static int hf_mysql_stat_mr = -1;
942 static int hf_mysql_stat_mu = -1;
943 static int hf_mysql_stat_bi = -1;
944 static int hf_mysql_stat_ni = -1;
945 static int hf_mysql_stat_cr = -1;
946 static int hf_mysql_stat_lr = -1;
947 static int hf_mysql_stat_dr = -1;
948 static int hf_mysql_stat_bs = -1;
949 static int hf_mysql_stat_mc = -1;
950 static int hf_mysql_stat_session_state_changed = -1;
951 static int hf_mysql_stat_query_was_slow = -1;
952 static int hf_mysql_stat_ps_out_params = -1;
953 static int hf_mysql_stat_trans_readonly = -1;
954 static int hf_mysql_refresh = -1;
955 static int hf_mysql_rfsh_grants = -1;
956 static int hf_mysql_rfsh_log = -1;
957 static int hf_mysql_rfsh_tables = -1;
958 static int hf_mysql_rfsh_hosts = -1;
959 static int hf_mysql_rfsh_status = -1;
960 static int hf_mysql_rfsh_threads = -1;
961 static int hf_mysql_rfsh_slave = -1;
962 static int hf_mysql_rfsh_master = -1;
963 static int hf_mysql_packet_length = -1;
964 static int hf_mysql_packet_number = -1;
965 static int hf_mysql_request = -1;
966 static int hf_mysql_command = -1;
967 static int hf_mysql_response_code = -1;
968 static int hf_mysql_error_code = -1;
969 static int hf_mysql_error_string = -1;
970 static int hf_mysql_sqlstate = -1;
971 static int hf_mysql_message = -1;
972 static int hf_mysql_payload = -1;
973 static int hf_mysql_server_greeting = -1;
974 static int hf_mysql_session_track = -1;
975 static int hf_mysql_session_track_type = -1;
976 static int hf_mysql_session_track_length = -1;
977 static int hf_mysql_session_track_data = -1;
978 static int hf_mysql_session_track_data_length = -1;
979 static int hf_mysql_session_track_sysvar_length = -1;
980 static int hf_mysql_session_track_sysvar_name = -1;
981 static int hf_mysql_session_track_sysvar_value = -1;
982 static int hf_mysql_session_track_schema = -1;
983 static int hf_mysql_session_track_schema_length = -1;
984 static int hf_mysql_session_state_change = -1;
985 static int hf_mysql_session_track_gtids = -1;
986 static int hf_mysql_session_track_gtids_encoding = -1;
987 static int hf_mysql_session_track_gtids_length = -1;
988 static int hf_mysql_session_track_transaction_characteristics = -1;
989 static int hf_mysql_session_track_transaction_characteristics_length = -1;
990 static int hf_mysql_session_track_transaction_state = -1;
991 static int hf_mysql_session_track_transaction_state_length = -1;
992 static int hf_mysql_protocol = -1;
993 static int hf_mysql_version  = -1;
994 static int hf_mysql_login_request = -1;
995 static int hf_mysql_max_packet = -1;
996 static int hf_mysql_user = -1;
997 static int hf_mysql_table_name = -1;
998 static int hf_mysql_schema = -1;
999 static int hf_mysql_client_auth_plugin = -1;
1000 static int hf_mysql_connattrs = -1;
1001 static int hf_mysql_connattrs_length = -1;
1002 static int hf_mysql_connattrs_attr = -1;
1003 static int hf_mysql_connattrs_name_length = -1;
1004 static int hf_mysql_connattrs_name = -1;
1005 static int hf_mysql_connattrs_value_length = -1;
1006 static int hf_mysql_connattrs_value = -1;
1007 static int hf_mysql_thread_id  = -1;
1008 static int hf_mysql_salt = -1;
1009 static int hf_mysql_salt2 = -1;
1010 static int hf_mysql_auth_plugin_length = -1;
1011 static int hf_mysql_auth_plugin = -1;
1012 static int hf_mysql_charset = -1;
1013 static int hf_mysql_passwd = -1;
1014 static int hf_mysql_unused = -1;
1015 static int hf_mysql_affected_rows = -1;
1016 static int hf_mysql_insert_id = -1;
1017 static int hf_mysql_num_warn = -1;
1018 static int hf_mysql_thd_id = -1;
1019 static int hf_mysql_stmt_id = -1;
1020 static int hf_mysql_query = -1;
1021 static int hf_mysql_shutdown = -1;
1022 static int hf_mysql_option = -1;
1023 static int hf_mysql_num_rows = -1;
1024 static int hf_mysql_param = -1;
1025 static int hf_mysql_num_params = -1;
1026 static int hf_mysql_exec_flags4 = -1;
1027 static int hf_mysql_exec_flags5 = -1;
1028 static int hf_mysql_exec_iter = -1;
1029 static int hf_mysql_binlog_position = -1;
1030 static int hf_mysql_binlog_flags = -1;
1031 static int hf_mysql_binlog_server_id = -1;
1032 static int hf_mysql_binlog_file_name = -1;
1033 static int hf_mysql_eof = -1;
1034 static int hf_mysql_num_fields = -1;
1035 static int hf_mysql_extra = -1;
1036 static int hf_mysql_fld_catalog  = -1;
1037 static int hf_mysql_fld_db = -1;
1038 static int hf_mysql_fld_table = -1;
1039 static int hf_mysql_fld_org_table = -1;
1040 static int hf_mysql_fld_name = -1;
1041 static int hf_mysql_fld_org_name = -1;
1042 static int hf_mysql_fld_charsetnr = -1;
1043 static int hf_mysql_fld_length = -1;
1044 static int hf_mysql_fld_type = -1;
1045 static int hf_mysql_fld_flags = -1;
1046 static int hf_mysql_fld_not_null = -1;
1047 static int hf_mysql_fld_primary_key = -1;
1048 static int hf_mysql_fld_unique_key = -1;
1049 static int hf_mysql_fld_multiple_key = -1;
1050 static int hf_mysql_fld_blob = -1;
1051 static int hf_mysql_fld_unsigned = -1;
1052 static int hf_mysql_fld_zero_fill = -1;
1053 static int hf_mysql_fld_binary = -1;
1054 static int hf_mysql_fld_enum = -1;
1055 static int hf_mysql_fld_auto_increment = -1;
1056 static int hf_mysql_fld_timestamp = -1;
1057 static int hf_mysql_fld_set = -1;
1058 static int hf_mysql_fld_decimals = -1;
1059 static int hf_mysql_fld_default = -1;
1060 static int hf_mysql_row_text = -1;
1061 static int hf_mysql_new_parameter_bound_flag = -1;
1062 static int hf_mysql_exec_param = -1;
1063 static int hf_mysql_exec_unsigned = -1;
1064 static int hf_mysql_exec_field_longlong = -1;
1065 static int hf_mysql_exec_field_string = -1;
1066 static int hf_mysql_exec_field_double = -1;
1067 static int hf_mysql_exec_field_datetime_length = -1;
1068 static int hf_mysql_exec_field_year = -1;
1069 static int hf_mysql_exec_field_month = -1;
1070 static int hf_mysql_exec_field_day = -1;
1071 static int hf_mysql_exec_field_hour = -1;
1072 static int hf_mysql_exec_field_minute = -1;
1073 static int hf_mysql_exec_field_second = -1;
1074 static int hf_mysql_exec_field_second_b = -1;
1075 static int hf_mysql_exec_field_long = -1;
1076 static int hf_mysql_exec_field_tiny = -1;
1077 static int hf_mysql_exec_field_short = -1;
1078 static int hf_mysql_exec_field_float = -1;
1079 static int hf_mysql_exec_field_time_length = -1;
1080 static int hf_mysql_exec_field_time_sign = -1;
1081 static int hf_mysql_exec_field_time_days = -1;
1082 static int hf_mysql_auth_switch_request_status = -1;
1083 static int hf_mysql_auth_switch_request_name = -1;
1084 static int hf_mysql_auth_switch_request_data = -1;
1085 static int hf_mysql_auth_switch_response_data = -1;
1086 static int hf_mysql_compressed_packet_length = -1;
1087 static int hf_mysql_compressed_packet_length_uncompressed = -1;
1088 static int hf_mysql_compressed_packet_number = -1;
1089 static int hf_mysql_prefix = -1;
1090 static int hf_mysql_length = -1;
1091 //static int hf_mariadb_fld_charsetnr = -1;
1092 static int hf_mariadb_server_language = -1;
1093 static int hf_mariadb_charset = -1;
1094 static int hf_mariadb_cap_progress = -1;
1095 static int hf_mariadb_cap_commulti = -1;
1096 static int hf_mariadb_cap_bulk = -1;
1097 static int hf_mariadb_cap_extmetadata = -1;
1098 static int hf_mariadb_extcaps_server = -1;
1099 static int hf_mariadb_extcaps_client = -1;
1100 static int hf_mariadb_bulk_flag_autoid = -1;
1101 static int hf_mariadb_bulk_flag_sendtypes = -1;
1102 static int hf_mariadb_bulk_caps_flags = -1;
1103 static int hf_mariadb_bulk_paramtypes = -1;
1104 static int hf_mariadb_bulk_indicator = -1;
1105 static dissector_handle_t mysql_handle;
1106 static dissector_handle_t tls_handle;
1107 
1108 static expert_field ei_mysql_eof = EI_INIT;
1109 static expert_field ei_mysql_dissector_incomplete = EI_INIT;
1110 static expert_field ei_mysql_streamed_param = EI_INIT;
1111 static expert_field ei_mysql_prepare_response_needed = EI_INIT;
1112 static expert_field ei_mysql_unknown_response = EI_INIT;
1113 static expert_field ei_mysql_command = EI_INIT;
1114 
1115 /* type constants */
1116 static const value_string type_constants[] = {
1117 	{0x00, "FIELD_TYPE_DECIMAL"    },
1118 	{0x01, "FIELD_TYPE_TINY"       },
1119 	{0x02, "FIELD_TYPE_SHORT"      },
1120 	{0x03, "FIELD_TYPE_LONG"       },
1121 	{0x04, "FIELD_TYPE_FLOAT"      },
1122 	{0x05, "FIELD_TYPE_DOUBLE"     },
1123 	{0x06, "FIELD_TYPE_NULL"       },
1124 	{0x07, "FIELD_TYPE_TIMESTAMP"  },
1125 	{0x08, "FIELD_TYPE_LONGLONG"   },
1126 	{0x09, "FIELD_TYPE_INT24"      },
1127 	{0x0a, "FIELD_TYPE_DATE"       },
1128 	{0x0b, "FIELD_TYPE_TIME"       },
1129 	{0x0c, "FIELD_TYPE_DATETIME"   },
1130 	{0x0d, "FIELD_TYPE_YEAR"       },
1131 	{0x0e, "FIELD_TYPE_NEWDATE"    },
1132 	{0x0f, "FIELD_TYPE_VARCHAR"    },
1133 	{0x10, "FIELD_TYPE_BIT"        },
1134 	{0xf6, "FIELD_TYPE_NEWDECIMAL" },
1135 	{0xf7, "FIELD_TYPE_ENUM"       },
1136 	{0xf8, "FIELD_TYPE_SET"        },
1137 	{0xf9, "FIELD_TYPE_TINY_BLOB"  },
1138 	{0xfa, "FIELD_TYPE_MEDIUM_BLOB"},
1139 	{0xfb, "FIELD_TYPE_LONG_BLOB"  },
1140 	{0xfc, "FIELD_TYPE_BLOB"       },
1141 	{0xfd, "FIELD_TYPE_VAR_STRING" },
1142 	{0xfe, "FIELD_TYPE_STRING"     },
1143 	{0xff, "FIELD_TYPE_GEOMETRY"   },
1144 	{0, NULL}
1145 };
1146 
1147 typedef enum mysql_state {
1148 	UNDEFINED,
1149 	LOGIN,
1150 	REQUEST,
1151 	RESPONSE_OK,
1152 	RESPONSE_MESSAGE,
1153 	RESPONSE_TABULAR,
1154 	RESPONSE_SHOW_FIELDS,
1155 	FIELD_PACKET,
1156 	ROW_PACKET,
1157 	RESPONSE_PREPARE,
1158 	PREPARED_PARAMETERS,
1159 	PREPARED_FIELDS,
1160 	AUTH_SWITCH_REQUEST,
1161 	AUTH_SWITCH_RESPONSE
1162 } mysql_state_t;
1163 
1164 #ifdef CTDEBUG
1165 static const value_string state_vals[] = {
1166 	{UNDEFINED,            "undefined"},
1167 	{LOGIN,                "login"},
1168 	{REQUEST,              "request"},
1169 	{RESPONSE_OK,          "response OK"},
1170 	{RESPONSE_MESSAGE,     "response message"},
1171 	{RESPONSE_TABULAR,     "tabular response"},
1172 	{RESPONSE_SHOW_FIELDS, "response to SHOW FIELDS"},
1173 	{FIELD_PACKET,         "field packet"},
1174 	{ROW_PACKET,           "row packet"},
1175 	{RESPONSE_PREPARE,     "response to PREPARE"},
1176 	{PREPARED_PARAMETERS,  "parameters in response to PREPARE"},
1177 	{PREPARED_FIELDS,      "fields in response to PREPARE"},
1178 	{AUTH_SWITCH_REQUEST,  "authentication switch request"},
1179 	{AUTH_SWITCH_RESPONSE, "authentication switch response"},
1180 	{0, NULL}
1181 };
1182 #endif
1183 
1184 typedef struct mysql_conn_data {
1185 	guint16 srv_caps;
1186 	guint16 srv_caps_ext;
1187 	guint16 clnt_caps;
1188 	guint16 clnt_caps_ext;
1189 	mysql_state_t state;
1190 	guint16 stmt_num_params;
1191 	guint16 stmt_num_fields;
1192 	wmem_tree_t* stmts;
1193 #ifdef CTDEBUG
1194 	guint32 generation;
1195 #endif
1196 	guint8 major_version;
1197 	guint32 frame_start_ssl;
1198 	guint32 frame_start_compressed;
1199 	guint8 compressed_state;
1200 	gboolean is_mariadb_server; /* set to 1, if connected to a MariaDB server */
1201 	gboolean is_mariadb_client; /* set to 1, if connected from a MariaDB client */
1202 	guint32 mariadb_server_ext_caps;
1203 	guint32 mariadb_client_ext_caps;
1204 	guint64 remaining_field_packet_count;
1205 } mysql_conn_data_t;
1206 
1207 struct mysql_frame_data {
1208 	mysql_state_t state;
1209 };
1210 
1211 typedef struct my_stmt_data {
1212 	guint16 nparam;
1213 	guint8* param_flags;
1214 	guint8* param_types;
1215 	guint16 bulk_flags;
1216 } my_stmt_data_t;
1217 
1218 typedef struct mysql_exec_dissector {
1219 	guint8 type;
1220 	guint8 unsigned_flag;
1221 	void (*dissector)(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
1222 } mysql_exec_dissector_t;
1223 
1224 /* function prototypes */
1225 static int mysql_dissect_error_packet(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
1226 static int mysql_dissect_ok_packet(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, mysql_conn_data_t *conn_data);
1227 static int mysql_dissect_server_status(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *server_status);
1228 static int mysql_dissect_caps(tvbuff_t *tvb, int offset, proto_tree *tree, int mysql_caps, guint16 *caps);
1229 static int mysql_dissect_extcaps(tvbuff_t *tvb, int offset, proto_tree *tree, int mysql_extcaps, guint16 *caps);
1230 static int mysql_dissect_result_header(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, mysql_conn_data_t *conn_data);
1231 static int mysql_dissect_field_packet(tvbuff_t *tvb, int offset, proto_tree *tree, mysql_conn_data_t *conn_data);
1232 static int mysql_dissect_row_packet(tvbuff_t *tvb, int offset, proto_tree *tree);
1233 static int mysql_dissect_response_prepare(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, mysql_conn_data_t *conn_data);
1234 static int mysql_dissect_auth_switch_request(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, mysql_conn_data_t *conn_data);
1235 static int mysql_dissect_auth_switch_response(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, mysql_conn_data_t *conn_data);
1236 static void mysql_dissect_exec_string(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
1237 static void mysql_dissect_exec_datetime(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
1238 static void mysql_dissect_exec_tiny(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
1239 static void mysql_dissect_exec_short(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
1240 static void mysql_dissect_exec_long(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
1241 static void mysql_dissect_exec_float(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
1242 static void mysql_dissect_exec_double(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
1243 static void mysql_dissect_exec_longlong(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
1244 static void mysql_dissect_exec_null(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
1245 static char mysql_dissect_exec_param(proto_item *req_tree, tvbuff_t *tvb, int *offset,
1246 		int *param_offset, guint8 param_flags, packet_info *pinfo);
1247 static void mysql_dissect_exec_primitive(tvbuff_t *tvb, int *param_offset,
1248 proto_item *field_tree, const int hfindex, const int offset);
1249 static void mysql_dissect_exec_time(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
1250 static int mariadb_dissect_caps_or_flags(tvbuff_t *tvb, int offset, enum ftenum type, proto_tree *tree,
1251 		int mariadb_caps, int * const *fields, void *value);
1252 
1253 static gint my_tvb_strsize(tvbuff_t *tvb, int offset);
1254 static int tvb_get_fle(tvbuff_t *tvb, proto_tree* tree, int offset, guint64 *res, guint8 *is_null);
1255 
1256 static const mysql_exec_dissector_t mysql_exec_dissectors[] = {
1257 	{ 0x01, 0, mysql_dissect_exec_tiny },
1258 	{ 0x02, 0, mysql_dissect_exec_short },
1259 	{ 0x03, 0, mysql_dissect_exec_long },
1260 	{ 0x04, 0, mysql_dissect_exec_float },
1261 	{ 0x05, 0, mysql_dissect_exec_double },
1262 	{ 0x06, 0, mysql_dissect_exec_null },
1263 	{ 0x07, 0, mysql_dissect_exec_datetime },
1264 	{ 0x08, 0, mysql_dissect_exec_longlong },
1265 	{ 0x0a, 0, mysql_dissect_exec_datetime },
1266 	{ 0x0b, 0, mysql_dissect_exec_time },
1267 	{ 0x0c, 0, mysql_dissect_exec_datetime },
1268 	{ 0xf6, 0, mysql_dissect_exec_string },
1269 	{ 0xfc, 0, mysql_dissect_exec_string },
1270 	{ 0xfd, 0, mysql_dissect_exec_string },
1271 	{ 0xfe, 0, mysql_dissect_exec_string },
1272 	{ 0x00, 0, NULL },
1273 };
1274 
1275 static int * const mysql_rfsh_flags[] = {
1276 	&hf_mysql_rfsh_grants,
1277 	&hf_mysql_rfsh_log,
1278 	&hf_mysql_rfsh_tables,
1279 	&hf_mysql_rfsh_hosts,
1280 	&hf_mysql_rfsh_status,
1281 	&hf_mysql_rfsh_threads,
1282 	&hf_mysql_rfsh_slave,
1283 	&hf_mysql_rfsh_master,
1284 	NULL
1285 };
1286 
1287 static int * const mysql_stat_flags[] = {
1288 	&hf_mysql_stat_it,
1289 	&hf_mysql_stat_ac,
1290 	&hf_mysql_stat_mu,
1291 	&hf_mysql_stat_mr,
1292 	&hf_mysql_stat_bi,
1293 	&hf_mysql_stat_ni,
1294 	&hf_mysql_stat_cr,
1295 	&hf_mysql_stat_lr,
1296 	&hf_mysql_stat_dr,
1297 	&hf_mysql_stat_bs,
1298 	&hf_mysql_stat_mc,
1299 	&hf_mysql_stat_query_was_slow,
1300 	&hf_mysql_stat_ps_out_params,
1301 	&hf_mysql_stat_trans_readonly,
1302 	&hf_mysql_stat_session_state_changed,
1303 	NULL
1304 };
1305 
1306 static int * const mysql_caps_flags[] = {
1307 	&hf_mysql_cap_long_password,
1308 	&hf_mysql_cap_found_rows,
1309 	&hf_mysql_cap_long_flag,
1310 	&hf_mysql_cap_connect_with_db,
1311 	&hf_mysql_cap_no_schema,
1312 	&hf_mysql_cap_compress,
1313 	&hf_mysql_cap_odbc,
1314 	&hf_mysql_cap_local_files,
1315 	&hf_mysql_cap_ignore_space,
1316 	&hf_mysql_cap_change_user,
1317 	&hf_mysql_cap_interactive,
1318 	&hf_mysql_cap_ssl,
1319 	&hf_mysql_cap_ignore_sigpipe,
1320 	&hf_mysql_cap_transactions,
1321 	&hf_mysql_cap_reserved,
1322 	&hf_mysql_cap_secure_connect,
1323 	NULL
1324 };
1325 
1326 static int * const mysql_extcaps_flags[] = {
1327 	&hf_mysql_cap_multi_statements,
1328 	&hf_mysql_cap_multi_results,
1329 	&hf_mysql_cap_ps_multi_results,
1330 	&hf_mysql_cap_plugin_auth,
1331 	&hf_mysql_cap_connect_attrs,
1332 	&hf_mysql_cap_plugin_auth_lenenc_client_data,
1333 	&hf_mysql_cap_client_can_handle_expired_passwords,
1334 	&hf_mysql_cap_session_track,
1335 	&hf_mysql_cap_deprecate_eof,
1336 	&hf_mysql_cap_unused,
1337 	NULL
1338 };
1339 
1340 static int * const mariadb_extcaps_flags[] = {
1341 	&hf_mariadb_cap_progress,
1342 	&hf_mariadb_cap_commulti,
1343 	&hf_mariadb_cap_bulk,
1344 	&hf_mariadb_cap_extmetadata,
1345 	NULL
1346 };
1347 
1348 static int * const mariadb_bulk_caps_flags[] = {
1349 	&hf_mariadb_bulk_flag_autoid,
1350 	&hf_mariadb_bulk_flag_sendtypes,
1351 	NULL
1352 };
1353 
1354 static int * const mysql_fld_flags[] = {
1355 	&hf_mysql_fld_not_null,
1356 	&hf_mysql_fld_primary_key,
1357 	&hf_mysql_fld_unique_key,
1358 	&hf_mysql_fld_multiple_key,
1359 	&hf_mysql_fld_blob,
1360 	&hf_mysql_fld_unsigned,
1361 	&hf_mysql_fld_zero_fill,
1362 	&hf_mysql_fld_binary,
1363 	&hf_mysql_fld_enum,
1364 	&hf_mysql_fld_auto_increment,
1365 	&hf_mysql_fld_timestamp,
1366 	&hf_mysql_fld_set,
1367 	NULL
1368 };
1369 
1370 /* Helper function to only set state on first pass */
mysql_set_conn_state(packet_info * pinfo,mysql_conn_data_t * conn_data,mysql_state_t state)1371 static void mysql_set_conn_state(packet_info *pinfo, mysql_conn_data_t *conn_data, mysql_state_t state)
1372 {
1373 	if (!pinfo->fd->visited)
1374 	{
1375 		conn_data->state = state;
1376 	}
1377 }
1378 
mysql_get_remaining_field_packet_count(mysql_conn_data_t * conn_data)1379 static guint64 mysql_get_remaining_field_packet_count(mysql_conn_data_t *conn_data)
1380 {
1381 	return conn_data->remaining_field_packet_count;
1382 }
1383 
mysql_dec_remaining_field_packet_count(mysql_conn_data_t * conn_data)1384 static void mysql_dec_remaining_field_packet_count(mysql_conn_data_t *conn_data)
1385 {
1386 	conn_data->remaining_field_packet_count--;
1387 }
1388 
mysql_set_remaining_field_packet_count(mysql_conn_data_t * conn_data,guint64 num_fields)1389 static void mysql_set_remaining_field_packet_count(mysql_conn_data_t *conn_data, guint64 num_fields)
1390 {
1391 	conn_data->remaining_field_packet_count = num_fields;
1392 }
1393 
1394 static int
mysql_dissect_greeting(tvbuff_t * tvb,packet_info * pinfo,int offset,proto_tree * tree,mysql_conn_data_t * conn_data)1395 mysql_dissect_greeting(tvbuff_t *tvb, packet_info *pinfo, int offset,
1396 		       proto_tree *tree, mysql_conn_data_t *conn_data)
1397 {
1398 	gint protocol;
1399 	gint lenstr;
1400 	int ver_offset;
1401 
1402 	proto_item *tf;
1403 	proto_item *greeting_tree;
1404 	char buffer[7];
1405 
1406 	protocol= tvb_get_guint8(tvb, offset);
1407 
1408 	if (protocol == 0xff) {
1409 		return mysql_dissect_error_packet(tvb, pinfo, offset+1, tree);
1410 	}
1411 
1412 	mysql_set_conn_state(pinfo, conn_data, LOGIN);
1413 
1414 	tf = proto_tree_add_item(tree, hf_mysql_server_greeting, tvb, offset, -1, ENC_NA);
1415 	greeting_tree = proto_item_add_subtree(tf, ett_server_greeting);
1416 
1417 	col_append_fstr(pinfo->cinfo, COL_INFO, " proto=%d", protocol) ;
1418 
1419 	proto_tree_add_item(greeting_tree, hf_mysql_protocol, tvb, offset, 1, ENC_NA);
1420 
1421 	offset += 1;
1422 
1423 	/* version string */
1424 	lenstr = tvb_strsize(tvb,offset);
1425 
1426 	/* check if it is a MariaDB Server: MariaDB always sends 5.5.5- before real version number */
1427 	tvb_get_raw_bytes_as_string(tvb, offset, buffer, 7);
1428 	if (lenstr > 6 && strncmp(buffer, MARIADB_RPL_VERSION_HACK, sizeof(MARIADB_RPL_VERSION_HACK) - 1) == 0)
1429 	{
1430 		conn_data->is_mariadb_server= 1;
1431 	}
1432 
1433 	col_append_fstr(pinfo->cinfo, COL_INFO, " version=%s ",
1434 			tvb_format_text(pinfo->pool, tvb, conn_data->is_mariadb_server ? offset + 6 : offset, conn_data->is_mariadb_server ? lenstr - 7 : lenstr-1));
1435 	col_set_fence(pinfo->cinfo, COL_INFO);
1436 
1437 	proto_tree_add_item(greeting_tree, hf_mysql_version, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1438 	conn_data->major_version = 0;
1439 	for (ver_offset = 0; ver_offset < lenstr; ver_offset++) {
1440 		guint8 ver_char = tvb_get_guint8(tvb, offset + ver_offset);
1441 		if (ver_char == '.') break;
1442 		conn_data->major_version = conn_data->major_version * 10 + ver_char - '0';
1443 	}
1444 	offset += lenstr;
1445 
1446 	/* 4 bytes little endian thread_id */
1447 	proto_tree_add_item(greeting_tree, hf_mysql_thread_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1448 	offset += 4;
1449 
1450 	/* salt string */
1451 	lenstr = tvb_strsize(tvb,offset);
1452 	proto_tree_add_item(greeting_tree, hf_mysql_salt, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1453 	offset += lenstr;
1454 
1455 	/* rest is optional */
1456 	if (!tvb_reported_length_remaining(tvb, offset)) return offset;
1457 
1458 	/* 2 bytes CAPS */
1459 	offset = mysql_dissect_caps(tvb, offset, greeting_tree, hf_mysql_caps_server, &conn_data->srv_caps);
1460 
1461 	/* rest is optional */
1462 	if (!tvb_reported_length_remaining(tvb, offset)) return offset;
1463 
1464 	proto_tree_add_item(greeting_tree, conn_data->is_mariadb_server ? hf_mariadb_server_language : hf_mysql_server_language, tvb, offset, 1, ENC_NA);
1465 	offset += 1; /* for charset */
1466 
1467 	offset = mysql_dissect_server_status(tvb, offset, greeting_tree, NULL);
1468 
1469 	/* 2 bytes ExtCAPS */
1470 	offset = mysql_dissect_extcaps(tvb, offset, greeting_tree, hf_mysql_extcaps_server, &conn_data->srv_caps_ext);
1471 
1472 	/* 1 byte Auth Plugin Length */
1473 	proto_tree_add_item(greeting_tree, hf_mysql_auth_plugin_length, tvb, offset, 1, ENC_NA);
1474 	offset += 1;
1475 
1476 	if (conn_data->is_mariadb_server)
1477 	{
1478 		/* 6 bytes unused */
1479 		proto_tree_add_item(greeting_tree, hf_mysql_unused, tvb, offset, 6, ENC_NA);
1480     offset += 6;
1481 		/* MariaDB specific extended capabilities */
1482 		offset= mariadb_dissect_caps_or_flags(tvb, offset, FT_UINT32, greeting_tree,
1483 										hf_mariadb_extcaps_server, mariadb_extcaps_flags, &conn_data->mariadb_server_ext_caps);
1484 	} else {
1485 		/* 10 bytes unused */
1486 		proto_tree_add_item(greeting_tree, hf_mysql_unused, tvb, offset, 10, ENC_NA);
1487 		offset += 10;
1488 	}
1489 
1490 	/* 4.1+ server: rest of salt */
1491 	if (tvb_reported_length_remaining(tvb, offset)) {
1492 		lenstr = tvb_strsize(tvb,offset);
1493 		proto_tree_add_item(greeting_tree, hf_mysql_salt2, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1494 		offset += lenstr;
1495 	}
1496 
1497 	/* 5.x server: auth plugin */
1498 	if (tvb_reported_length_remaining(tvb, offset)) {
1499 		lenstr = tvb_strsize(tvb,offset);
1500 		proto_tree_add_item(greeting_tree, hf_mysql_auth_plugin, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1501 		offset += lenstr;
1502 	}
1503 
1504 	return offset;
1505 }
1506 
1507 
1508 /*
1509   Add a connect attributs entry to the connattrs subtree
1510 
1511   return bytes read
1512 */
1513 static int
add_connattrs_entry_to_tree(tvbuff_t * tvb,packet_info * pinfo _U_,proto_item * tree,int offset)1514 add_connattrs_entry_to_tree(tvbuff_t *tvb, packet_info *pinfo _U_, proto_item *tree, int offset) {
1515 	guint64 lenstr;
1516 	int orig_offset = offset, lenfle;
1517 	proto_item *ti;
1518 	proto_tree *connattrs_tree;
1519 	const guint8 *str;
1520 
1521 	ti = proto_tree_add_item(tree, hf_mysql_connattrs_attr, tvb, offset, 1, ENC_NA);
1522 	connattrs_tree = proto_item_add_subtree(ti, ett_connattrs_attr);
1523 
1524 	lenfle = tvb_get_fle(tvb, connattrs_tree, offset, &lenstr, NULL);
1525 	proto_tree_add_uint64(connattrs_tree, hf_mysql_connattrs_name_length, tvb, offset, lenfle, lenstr);
1526 	offset += lenfle;
1527 
1528 	proto_tree_add_item_ret_string(connattrs_tree, hf_mysql_connattrs_name, tvb, offset, (gint)lenstr, ENC_ASCII|ENC_NA, pinfo->pool, &str);
1529 	proto_item_append_text(ti, " - %s", str);
1530 	offset += (int)lenstr;
1531 
1532 	lenfle = tvb_get_fle(tvb, connattrs_tree, offset, &lenstr, NULL);
1533 	proto_tree_add_uint64(connattrs_tree, hf_mysql_connattrs_value_length, tvb, offset, lenfle, lenstr);
1534 	offset += lenfle;
1535 
1536 	proto_tree_add_item_ret_string(connattrs_tree, hf_mysql_connattrs_value, tvb, offset, (gint)lenstr, ENC_ASCII|ENC_NA, pinfo->pool, &str);
1537 	proto_item_append_text(ti, ": %s", str);
1538 	offset += (int)lenstr;
1539 
1540 	proto_item_set_len(ti, offset - orig_offset);
1541 
1542 	return (offset - orig_offset);
1543 }
1544 
1545 static int
mysql_dissect_login(tvbuff_t * tvb,packet_info * pinfo,int offset,proto_tree * tree,mysql_conn_data_t * conn_data)1546 mysql_dissect_login(tvbuff_t *tvb, packet_info *pinfo, int offset,
1547 		    proto_tree *tree, mysql_conn_data_t *conn_data)
1548 {
1549 	gint lenstr;
1550 
1551 	proto_item *tf;
1552 	proto_item *login_tree;
1553 
1554 	/* after login there can be OK or DENIED */
1555 	mysql_set_conn_state(pinfo, conn_data, RESPONSE_OK);
1556 
1557 	tf = proto_tree_add_item(tree, hf_mysql_login_request, tvb, offset, -1, ENC_NA);
1558 	login_tree = proto_item_add_subtree(tf, ett_login_request);
1559 
1560 	offset = mysql_dissect_caps(tvb, offset, login_tree, hf_mysql_caps_client, &conn_data->clnt_caps);
1561 
1562 	/* MariaDB clients don't have the CLIENT_MYSQL/CLIENT_LONG_PASSWORD capability */
1563 	if (!(conn_data->clnt_caps & MYSQL_CAPS_LP))
1564 	{
1565 		conn_data->is_mariadb_client= 1;
1566 	}
1567 
1568 	if (!(conn_data->frame_start_ssl) && conn_data->clnt_caps & MYSQL_CAPS_SL) /* Next packet will be use SSL */
1569 	{
1570 		col_set_str(pinfo->cinfo, COL_INFO, "Response: SSL Handshake");
1571 		conn_data->frame_start_ssl = pinfo->num;
1572 		ssl_starttls_ack(tls_handle, pinfo, mysql_handle);
1573 	}
1574 	if (conn_data->clnt_caps & MYSQL_CAPS_CU) /* 4.1 protocol */{
1575 		offset = mysql_dissect_extcaps(tvb, offset, login_tree, hf_mysql_extcaps_client, &conn_data->clnt_caps_ext);
1576 
1577 		proto_tree_add_item(login_tree, hf_mysql_max_packet, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1578 		offset += 4;
1579 
1580 		proto_tree_add_item(login_tree, conn_data->is_mariadb_server ? hf_mariadb_charset : hf_mysql_charset, tvb, offset, 1, ENC_NA);
1581 		offset += 1; /* for charset */
1582 
1583 		if (conn_data->is_mariadb_client){
1584 			/* 19 bytes unused */
1585 			proto_tree_add_item(login_tree, hf_mysql_unused, tvb, offset, 19, ENC_NA);
1586 			offset += 19;
1587 			offset= mariadb_dissect_caps_or_flags(tvb, offset, FT_UINT32, login_tree, hf_mariadb_extcaps_client, mariadb_extcaps_flags, &conn_data->mariadb_client_ext_caps);
1588 		} else {
1589 			/* 23 bytes unused */
1590 			proto_tree_add_item(login_tree, hf_mysql_unused, tvb, offset, 23, ENC_NA);
1591 			offset += 23;
1592 		}
1593 
1594 	} else { /* pre-4.1 */
1595 		proto_tree_add_item(login_tree, hf_mysql_max_packet, tvb, offset, 3, ENC_LITTLE_ENDIAN);
1596 		offset += 3;
1597 	}
1598 
1599 	/* User name */
1600 	lenstr = my_tvb_strsize(tvb, offset);
1601 	col_append_fstr(pinfo->cinfo, COL_INFO, " user=%s ",
1602 			tvb_format_text(pinfo->pool, tvb, offset, lenstr-1));
1603 	proto_tree_add_item(login_tree, hf_mysql_user, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1604 	offset += lenstr;
1605 
1606 	/* rest is optional */
1607 	if (!tvb_reported_length_remaining(tvb, offset)) {
1608 		col_set_fence(pinfo->cinfo, COL_INFO);
1609 		return offset;
1610 	}
1611 
1612 	/* password: asciiz or length+ascii */
1613 	if (conn_data->clnt_caps & MYSQL_CAPS_SC) {
1614 		lenstr = tvb_get_guint8(tvb, offset);
1615 		offset += 1;
1616 	} else {
1617 		lenstr = my_tvb_strsize(tvb, offset);
1618 	}
1619 	if (tree && lenstr > 1) {
1620 		proto_tree_add_item(login_tree, hf_mysql_passwd, tvb, offset, lenstr, ENC_NA);
1621 	}
1622 	offset += lenstr;
1623 
1624 	/* optional: initial schema */
1625 	if (conn_data->clnt_caps & MYSQL_CAPS_CD)
1626 	{
1627 		lenstr= my_tvb_strsize(tvb,offset);
1628 		if(lenstr<0){
1629 			return offset;
1630 		}
1631 
1632 		col_append_fstr(pinfo->cinfo, COL_INFO, "db=%s ",
1633 			tvb_format_text(pinfo->pool, tvb, offset, lenstr-1));
1634 		col_set_fence(pinfo->cinfo, COL_INFO);
1635 
1636 		proto_tree_add_item(login_tree, hf_mysql_schema, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1637 		offset += lenstr;
1638 	}
1639 
1640 	/* optional: authentication plugin */
1641 	if (conn_data->clnt_caps_ext & MYSQL_CAPS_PA)
1642 	{
1643 		mysql_set_conn_state(pinfo, conn_data, AUTH_SWITCH_REQUEST);
1644 		lenstr= my_tvb_strsize(tvb,offset);
1645 		proto_tree_add_item(login_tree, hf_mysql_client_auth_plugin, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1646 		offset += lenstr;
1647 	}
1648 
1649 	/* optional: connection attributes */
1650 	if (conn_data->clnt_caps_ext & MYSQL_CAPS_CA && tvb_reported_length_remaining(tvb, offset))
1651 	{
1652 		proto_tree *connattrs_tree;
1653 		int lenfle;
1654 		guint64 connattrs_length;
1655 		int length;
1656 
1657 		lenfle = tvb_get_fle(tvb, login_tree, offset, &connattrs_length, NULL);
1658 		tf = proto_tree_add_item(login_tree, hf_mysql_connattrs, tvb, offset, (guint32)connattrs_length, ENC_NA);
1659 		connattrs_tree = proto_item_add_subtree(tf, ett_connattrs);
1660 		proto_tree_add_uint64(connattrs_tree, hf_mysql_connattrs_length, tvb, offset, lenfle, connattrs_length);
1661 		offset += lenfle;
1662 
1663 		while (connattrs_length > 0) {
1664 			length = add_connattrs_entry_to_tree(tvb, pinfo, connattrs_tree, offset);
1665 			offset += length;
1666 			connattrs_length -= length;
1667 		}
1668 	}
1669 
1670 	return offset;
1671 }
1672 
1673 
1674 static void
mysql_dissect_exec_string(tvbuff_t * tvb,int * param_offset,proto_item * field_tree)1675 mysql_dissect_exec_string(tvbuff_t *tvb, int *param_offset, proto_item *field_tree)
1676 {
1677 	guint32 param_len32;
1678 	guint8 param_len;
1679 
1680 	param_len = tvb_get_guint8(tvb, *param_offset);
1681 
1682 	switch (param_len) {
1683 		case 0xfc: /* 252 - 64k chars */
1684 			*param_offset += 1;
1685 			param_len32 = tvb_get_letohs(tvb, *param_offset);
1686 			proto_tree_add_item(field_tree, hf_mysql_exec_field_string,
1687 					    tvb, *param_offset, 2, ENC_ASCII | ENC_LITTLE_ENDIAN);
1688 			*param_offset += param_len32 + 2;
1689 			break;
1690 		case 0xfd: /* 64k - 16M chars */
1691 			*param_offset += 1;
1692 			param_len32 = tvb_get_letoh24(tvb, *param_offset);
1693 			proto_tree_add_item(field_tree, hf_mysql_exec_field_string,
1694 					    tvb, *param_offset, 3, ENC_ASCII | ENC_LITTLE_ENDIAN);
1695 			*param_offset += param_len32 + 3;
1696 			break;
1697 		default: /* < 252 chars */
1698 			proto_tree_add_item(field_tree, hf_mysql_exec_field_string,
1699 					    tvb, *param_offset, 1, ENC_ASCII | ENC_NA);
1700 			*param_offset += param_len + 1;
1701 			break;
1702 	}
1703 }
1704 
1705 static void
mysql_dissect_exec_time(tvbuff_t * tvb,int * param_offset,proto_item * field_tree)1706 mysql_dissect_exec_time(tvbuff_t *tvb, int *param_offset, proto_item *field_tree)
1707 {
1708 	guint8 param_len;
1709 
1710 	param_len = tvb_get_guint8(tvb, *param_offset);
1711 	proto_tree_add_item(field_tree, hf_mysql_exec_field_time_length, tvb, *param_offset, 1, ENC_NA);
1712 	*param_offset += 1;
1713 	if (param_len >= 1) {
1714 		proto_tree_add_item(field_tree, hf_mysql_exec_field_time_sign, tvb, *param_offset, 1, ENC_NA);
1715 	}
1716 	if (param_len >= 5) {
1717 		proto_tree_add_item(field_tree, hf_mysql_exec_field_time_days, tvb, *param_offset + 1, 4, ENC_LITTLE_ENDIAN);
1718 	}
1719 	if (param_len >= 8) {
1720 		proto_tree_add_item(field_tree, hf_mysql_exec_field_hour, tvb, *param_offset + 5, 1, ENC_NA);
1721 		proto_tree_add_item(field_tree, hf_mysql_exec_field_minute, tvb, *param_offset + 6, 1, ENC_NA);
1722 		proto_tree_add_item(field_tree, hf_mysql_exec_field_second, tvb, *param_offset + 7, 1, ENC_NA);
1723 	}
1724 	if (param_len >= 12) {
1725 		proto_tree_add_item(field_tree, hf_mysql_exec_field_second_b, tvb, *param_offset + 8, 4, ENC_LITTLE_ENDIAN);
1726 	}
1727 	*param_offset += param_len;
1728 }
1729 
1730 static void
mysql_dissect_exec_datetime(tvbuff_t * tvb,int * param_offset,proto_item * field_tree)1731 mysql_dissect_exec_datetime(tvbuff_t *tvb, int *param_offset, proto_item *field_tree)
1732 {
1733 	guint8 param_len;
1734 
1735 	param_len = tvb_get_guint8(tvb, *param_offset);
1736 	proto_tree_add_item(field_tree, hf_mysql_exec_field_datetime_length, tvb, *param_offset, 1, ENC_NA);
1737 	*param_offset += 1;
1738 	if (param_len >= 2) {
1739 		proto_tree_add_item(field_tree, hf_mysql_exec_field_year, tvb, *param_offset, 2, ENC_LITTLE_ENDIAN);
1740 	}
1741 	if (param_len >= 4) {
1742 		proto_tree_add_item(field_tree, hf_mysql_exec_field_month, tvb, *param_offset + 2, 1, ENC_NA);
1743 		proto_tree_add_item(field_tree, hf_mysql_exec_field_day, tvb, *param_offset + 3, 1, ENC_NA);
1744 	}
1745 	if (param_len >= 7) {
1746 		proto_tree_add_item(field_tree, hf_mysql_exec_field_hour, tvb, *param_offset + 4, 1, ENC_NA);
1747 		proto_tree_add_item(field_tree, hf_mysql_exec_field_minute, tvb, *param_offset + 5, 1, ENC_NA);
1748 		proto_tree_add_item(field_tree, hf_mysql_exec_field_second, tvb, *param_offset + 6, 1, ENC_NA);
1749 	}
1750 	if (param_len >= 11) {
1751 		proto_tree_add_item(field_tree, hf_mysql_exec_field_second_b, tvb, *param_offset + 7, 4, ENC_LITTLE_ENDIAN);
1752 	}
1753 	*param_offset += param_len;
1754 }
1755 
1756 static void
mysql_dissect_exec_primitive(tvbuff_t * tvb,int * param_offset,proto_item * field_tree,const int hfindex,const int offset)1757 mysql_dissect_exec_primitive(tvbuff_t *tvb, int *param_offset, proto_item *field_tree, const int hfindex, const int offset)
1758 {
1759 	proto_tree_add_item(field_tree, hfindex, tvb, *param_offset, offset, ENC_LITTLE_ENDIAN);
1760 	*param_offset += offset;
1761 }
1762 
1763 static void
mysql_dissect_exec_tiny(tvbuff_t * tvb,int * param_offset,proto_item * field_tree)1764 mysql_dissect_exec_tiny(tvbuff_t *tvb, int *param_offset, proto_item *field_tree)
1765 {
1766 	mysql_dissect_exec_primitive(tvb, param_offset, field_tree, hf_mysql_exec_field_tiny, 1);
1767 }
1768 
1769 static void
mysql_dissect_exec_short(tvbuff_t * tvb,int * param_offset,proto_item * field_tree)1770 mysql_dissect_exec_short(tvbuff_t *tvb, int *param_offset, proto_item *field_tree)
1771 {
1772 	mysql_dissect_exec_primitive(tvb, param_offset, field_tree, hf_mysql_exec_field_short, 2);
1773 }
1774 
1775 static void
mysql_dissect_exec_long(tvbuff_t * tvb,int * param_offset,proto_item * field_tree)1776 mysql_dissect_exec_long(tvbuff_t *tvb, int *param_offset, proto_item *field_tree)
1777 {
1778 	mysql_dissect_exec_primitive(tvb, param_offset, field_tree, hf_mysql_exec_field_long, 4);
1779 }
1780 
1781 static void
mysql_dissect_exec_float(tvbuff_t * tvb,int * param_offset,proto_item * field_tree)1782 mysql_dissect_exec_float(tvbuff_t *tvb, int *param_offset, proto_item *field_tree)
1783 {
1784 	mysql_dissect_exec_primitive(tvb, param_offset, field_tree, hf_mysql_exec_field_float, 4);
1785 }
1786 
1787 static void
mysql_dissect_exec_double(tvbuff_t * tvb,int * param_offset,proto_item * field_tree)1788 mysql_dissect_exec_double(tvbuff_t *tvb, int *param_offset, proto_item *field_tree)
1789 {
1790 	mysql_dissect_exec_primitive(tvb, param_offset, field_tree, hf_mysql_exec_field_double, 8);
1791 }
1792 
1793 static void
mysql_dissect_exec_longlong(tvbuff_t * tvb,int * param_offset,proto_item * field_tree)1794 mysql_dissect_exec_longlong(tvbuff_t *tvb, int *param_offset, proto_item *field_tree)
1795 {
1796 	mysql_dissect_exec_primitive(tvb, param_offset, field_tree, hf_mysql_exec_field_longlong, 8);
1797 }
1798 
1799 static void
mysql_dissect_exec_null(tvbuff_t * tvb _U_,int * param_offset _U_,proto_item * field_tree _U_)1800 mysql_dissect_exec_null(tvbuff_t *tvb _U_, int *param_offset _U_, proto_item *field_tree _U_)
1801 {}
1802 
1803 static char
mysql_dissect_exec_param(proto_item * req_tree,tvbuff_t * tvb,int * offset,int * param_offset,guint8 param_flags,packet_info * pinfo)1804 mysql_dissect_exec_param(proto_item *req_tree, tvbuff_t *tvb, int *offset,
1805 			 int *param_offset, guint8 param_flags,
1806 			 packet_info *pinfo)
1807 {
1808 	guint8 param_type, param_unsigned;
1809 	proto_item *tf;
1810 	proto_item *field_tree;
1811 	int dissector_index = 0;
1812 
1813 	tf = proto_tree_add_item(req_tree, hf_mysql_exec_param, tvb, *offset, 2, ENC_NA);
1814 	field_tree = proto_item_add_subtree(tf, ett_stat);
1815 	proto_tree_add_item(field_tree, hf_mysql_fld_type, tvb, *offset, 1, ENC_NA);
1816 	param_type = tvb_get_guint8(tvb, *offset);
1817 	*offset += 1; /* type */
1818 	proto_tree_add_item(field_tree, hf_mysql_exec_unsigned, tvb, *offset, 1, ENC_NA);
1819 	param_unsigned = tvb_get_guint8(tvb, *offset);
1820 	*offset += 1; /* signedness */
1821 	if ((param_flags & MYSQL_PARAM_FLAG_STREAMED) == MYSQL_PARAM_FLAG_STREAMED) {
1822 		expert_add_info(pinfo, field_tree, &ei_mysql_streamed_param);
1823 		return 1;
1824 	}
1825 	while (mysql_exec_dissectors[dissector_index].dissector != NULL) {
1826 		if (mysql_exec_dissectors[dissector_index].type == param_type &&
1827 			mysql_exec_dissectors[dissector_index].unsigned_flag == param_unsigned) {
1828 			mysql_exec_dissectors[dissector_index].dissector(tvb, param_offset, field_tree);
1829 			return 1;
1830 		}
1831 		dissector_index++;
1832 	}
1833 	return 0;
1834 }
1835 
1836 static int
mysql_dissect_request(tvbuff_t * tvb,packet_info * pinfo,int offset,proto_tree * tree,mysql_conn_data_t * conn_data,mysql_state_t current_state)1837 mysql_dissect_request(tvbuff_t *tvb,packet_info *pinfo, int offset, proto_tree *tree, mysql_conn_data_t *conn_data, mysql_state_t current_state)
1838 {
1839 	gint opcode;
1840 	gint lenstr;
1841 	proto_item *request_item, *tf = NULL, *ti;
1842 	proto_item *req_tree;
1843 	guint32 stmt_id;
1844 	my_stmt_data_t *stmt_data;
1845 	int stmt_pos, param_offset;
1846 
1847 	if(current_state == AUTH_SWITCH_RESPONSE){
1848 		return mysql_dissect_auth_switch_response(tvb, pinfo, offset, tree, conn_data);
1849 	}
1850 
1851 	request_item = proto_tree_add_item(tree, hf_mysql_request, tvb, offset, -1, ENC_NA);
1852 	req_tree = proto_item_add_subtree(request_item, ett_request);
1853 
1854 	opcode = tvb_get_guint8(tvb, offset);
1855 	col_append_fstr(pinfo->cinfo, COL_INFO, " %s", val_to_str_ext(opcode, &mysql_command_vals_ext, "Unknown (%u) "));
1856 
1857 	proto_tree_add_item(req_tree, hf_mysql_command, tvb, offset, 1, ENC_NA);
1858 	proto_item_append_text(request_item, " %s", val_to_str_ext(opcode, &mysql_command_vals_ext, "Unknown (%u)"));
1859 	offset += 1;
1860 
1861 
1862 	switch (opcode) {
1863 
1864 	case MYSQL_QUIT:
1865 		break;
1866 
1867 	case MYSQL_PROCESS_INFO:
1868 		mysql_set_conn_state(pinfo, conn_data, RESPONSE_TABULAR);
1869 		break;
1870 
1871 	case MYSQL_DEBUG:
1872 	case MYSQL_PING:
1873 		mysql_set_conn_state(pinfo, conn_data, RESPONSE_OK);
1874 		break;
1875 
1876 	case MYSQL_STATISTICS:
1877 		mysql_set_conn_state(pinfo, conn_data, RESPONSE_MESSAGE);
1878 		break;
1879 
1880 	case MYSQL_INIT_DB:
1881 	case MYSQL_CREATE_DB:
1882 	case MYSQL_DROP_DB:
1883 		lenstr = my_tvb_strsize(tvb, offset);
1884 		proto_tree_add_item(req_tree, hf_mysql_schema, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1885 		offset += lenstr;
1886 		mysql_set_conn_state(pinfo, conn_data, RESPONSE_OK);
1887 		break;
1888 
1889 	case MYSQL_QUERY:
1890 		lenstr = my_tvb_strsize(tvb, offset);
1891 		proto_tree_add_item(req_tree, hf_mysql_query, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1892 		if (mysql_showquery) {
1893 			col_append_fstr(pinfo->cinfo, COL_INFO, " { %s } ",
1894 					tvb_format_text(pinfo->pool, tvb, offset, lenstr));
1895 			col_set_fence(pinfo->cinfo, COL_INFO);
1896 		}
1897 		offset += lenstr;
1898 		mysql_set_conn_state(pinfo, conn_data, RESPONSE_TABULAR);
1899 		break;
1900 
1901 	case MYSQL_STMT_PREPARE:
1902 		lenstr = my_tvb_strsize(tvb, offset);
1903 		proto_tree_add_item(req_tree, hf_mysql_query, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1904 		offset += lenstr;
1905 		mysql_set_conn_state(pinfo, conn_data, RESPONSE_PREPARE);
1906 		break;
1907 
1908 	case MYSQL_STMT_CLOSE:
1909 		proto_tree_add_item(req_tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1910 		offset += 4;
1911 		mysql_set_conn_state(pinfo, conn_data, REQUEST);
1912 		break;
1913 
1914 	case MYSQL_STMT_RESET:
1915 		proto_tree_add_item(req_tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1916 		offset += 4;
1917 		mysql_set_conn_state(pinfo, conn_data, RESPONSE_OK);
1918 		break;
1919 
1920 	case MYSQL_FIELD_LIST:
1921 		lenstr = my_tvb_strsize(tvb, offset);
1922 		proto_tree_add_item(req_tree, hf_mysql_table_name, tvb,  offset, lenstr, ENC_ASCII|ENC_NA);
1923 		offset += lenstr;
1924 		mysql_set_conn_state(pinfo, conn_data, RESPONSE_SHOW_FIELDS);
1925 		break;
1926 
1927 	case MYSQL_PROCESS_KILL:
1928 		proto_tree_add_item(req_tree, hf_mysql_thd_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1929 		offset += 4;
1930 		mysql_set_conn_state(pinfo, conn_data, RESPONSE_OK);
1931 		break;
1932 
1933 	case MYSQL_CHANGE_USER:
1934 		lenstr = tvb_strsize(tvb, offset);
1935 		proto_tree_add_item(req_tree, hf_mysql_user, tvb,  offset, lenstr, ENC_ASCII|ENC_NA);
1936 		offset += lenstr;
1937 
1938 		if (conn_data->clnt_caps & MYSQL_CAPS_SC) {
1939 			lenstr = tvb_get_guint8(tvb, offset);
1940 			offset += 1;
1941 		} else {
1942 			lenstr = tvb_strsize(tvb, offset);
1943 		}
1944 		proto_tree_add_item(req_tree, hf_mysql_passwd, tvb, offset, lenstr, ENC_NA);
1945 		offset += lenstr;
1946 
1947 		lenstr = my_tvb_strsize(tvb, offset);
1948 		proto_tree_add_item(req_tree, hf_mysql_schema, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1949 		offset += lenstr;
1950 
1951 		if (tvb_reported_length_remaining(tvb, offset) > 0) {
1952 			proto_tree_add_item(req_tree, conn_data->is_mariadb_server ? hf_mariadb_charset : hf_mysql_charset, tvb, offset, 1, ENC_NA);
1953 			offset += 2; /* for charset */
1954 		}
1955 		mysql_set_conn_state(pinfo, conn_data, RESPONSE_OK);
1956 
1957 		/* optional: authentication plugin */
1958 		if (conn_data->clnt_caps_ext & MYSQL_CAPS_PA)
1959 		{
1960 			mysql_set_conn_state(pinfo, conn_data, AUTH_SWITCH_REQUEST);
1961 			lenstr= my_tvb_strsize(tvb,offset);
1962 			proto_tree_add_item(req_tree, hf_mysql_client_auth_plugin, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1963 			offset += lenstr;
1964 		}
1965 
1966 		/* optional: connection attributes */
1967 		if (conn_data->clnt_caps_ext & MYSQL_CAPS_CA)
1968 		{
1969 			proto_tree *connattrs_tree;
1970 			int lenfle;
1971 			guint64 connattrs_length;
1972 			int length;
1973 
1974 			lenfle = tvb_get_fle(tvb, req_tree, offset, &connattrs_length, NULL);
1975 			tf = proto_tree_add_item(req_tree, hf_mysql_connattrs, tvb, offset, (guint32)connattrs_length, ENC_NA);
1976 			connattrs_tree = proto_item_add_subtree(tf, ett_connattrs);
1977 			proto_tree_add_uint64(connattrs_tree, hf_mysql_connattrs_length, tvb, offset, lenfle, connattrs_length);
1978 			offset += lenfle;
1979 
1980 			while (connattrs_length > 0) {
1981 				length = add_connattrs_entry_to_tree(tvb, pinfo, connattrs_tree, offset);
1982 				offset += length;
1983 				connattrs_length -= length;
1984 			}
1985 		}
1986 		break;
1987 
1988 	case MYSQL_REFRESH:
1989 		proto_tree_add_bitmask_with_flags(req_tree, tvb, offset,
1990 		    hf_mysql_refresh, ett_refresh, mysql_rfsh_flags,
1991 		    ENC_BIG_ENDIAN, BMT_NO_APPEND);
1992 		offset += 1;
1993 		mysql_set_conn_state(pinfo, conn_data, RESPONSE_OK);
1994 		break;
1995 
1996 	case MYSQL_SHUTDOWN:
1997 		proto_tree_add_item(req_tree, hf_mysql_shutdown, tvb, offset, 1, ENC_NA);
1998 		offset += 1;
1999 		mysql_set_conn_state(pinfo, conn_data, RESPONSE_OK);
2000 		break;
2001 
2002 	case MYSQL_SET_OPTION:
2003 		proto_tree_add_item(req_tree, hf_mysql_option, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2004 		offset += 2;
2005 		mysql_set_conn_state(pinfo, conn_data, RESPONSE_OK);
2006 		break;
2007 
2008 	case MYSQL_STMT_FETCH:
2009 		proto_tree_add_item(req_tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2010 		offset += 4;
2011 
2012 		proto_tree_add_item(req_tree, hf_mysql_num_rows, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2013 		offset += 4;
2014 		mysql_set_conn_state(pinfo, conn_data, RESPONSE_TABULAR);
2015 		break;
2016 
2017 	case MYSQL_STMT_SEND_LONG_DATA:
2018 		proto_tree_add_item(req_tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2019 		stmt_id = tvb_get_letohl(tvb, offset);
2020 		offset += 4;
2021 
2022 		stmt_data = (my_stmt_data_t *)wmem_tree_lookup32(conn_data->stmts, stmt_id);
2023 		if (stmt_data != NULL) {
2024 			guint16 data_param = tvb_get_letohs(tvb, offset);
2025 			if (stmt_data->nparam > data_param) {
2026 				stmt_data->param_flags[data_param] |= MYSQL_PARAM_FLAG_STREAMED;
2027 			}
2028 		}
2029 
2030 		proto_tree_add_item(req_tree, hf_mysql_param, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2031 		offset += 2;
2032 
2033 		/* rest is data */
2034 		lenstr = tvb_reported_length_remaining(tvb, offset);
2035 		if (tree &&  lenstr > 0) {
2036 			proto_tree_add_item(req_tree, hf_mysql_payload, tvb, offset, lenstr, ENC_NA);
2037 		}
2038 		offset += lenstr;
2039 		mysql_set_conn_state(pinfo, conn_data, REQUEST);
2040 		break;
2041 
2042 	case MARIADB_STMT_BULK_EXECUTE:
2043 		proto_tree_add_item(req_tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2044 		stmt_id = tvb_get_letohl(tvb, offset);
2045 		offset += 4;
2046 		stmt_data = (my_stmt_data_t *)wmem_tree_lookup32(conn_data->stmts, stmt_id);
2047 
2048 		if (stmt_data != NULL) {
2049 			guint32 row_nr = 1;
2050 			proto_item *param_tree;
2051 
2052 			mariadb_dissect_caps_or_flags(tvb, offset, FT_UINT16, req_tree, hf_mariadb_bulk_caps_flags, mariadb_bulk_caps_flags, &stmt_data->bulk_flags);
2053 			offset += 2;
2054 
2055 			if ((stmt_data->bulk_flags & MARIADB_BULK_SEND_TYPES) && stmt_data->nparam)
2056 			{
2057 				tf = proto_tree_add_item(req_tree, hf_mariadb_bulk_paramtypes, tvb, offset, -1, ENC_NA);
2058 				param_tree = proto_item_add_subtree(tf, ett_exec_param);
2059 				for (stmt_pos = 0; stmt_pos < stmt_data->nparam; stmt_pos++) {
2060 					stmt_data->param_types[stmt_pos] = tvb_get_guint8(tvb, offset);
2061 					proto_tree_add_item(param_tree, hf_mysql_fld_type, tvb, offset, 1, ENC_NA);
2062 					offset+= 1;
2063 					stmt_data->param_flags[stmt_pos] = tvb_get_guint8(tvb, offset);
2064 					proto_tree_add_item(param_tree, hf_mysql_exec_unsigned, tvb, offset, 1, ENC_NA);
2065 					offset+= 1;
2066 				}
2067 			}
2068 			while (tvb_reported_length_remaining(tvb, offset) > 0){
2069 				tf = proto_tree_add_text_internal(req_tree, tvb, offset, 0, "%d. Dataset", row_nr++);
2070 				param_tree = proto_item_add_subtree(tf, ett_bulk_param);
2071 
2072 				for (stmt_pos = 0; stmt_pos < stmt_data->nparam; stmt_pos++)
2073 				{
2074 					guint8 indicator= tvb_get_guint8(tvb, offset);
2075 					proto_tree_add_item(param_tree, hf_mariadb_bulk_indicator, tvb, offset, 1, ENC_NA);
2076 					offset++;
2077 					/* If no indicator was specified, data will follow */
2078 					if (!indicator) {
2079 						int dissector_index= 0;
2080 						while (mysql_exec_dissectors[dissector_index].dissector != NULL) {
2081 							if (mysql_exec_dissectors[dissector_index].type == stmt_data->param_types[stmt_pos])
2082 	/*	&&
2083 								mysql_exec_dissectors[dissector_index].unsigned_flag == stmt_data->param_flags[stmt_pos]) */
2084 							{
2085 								mysql_exec_dissectors[dissector_index].dissector(tvb, &offset, param_tree);
2086 								break;
2087 							}
2088 							dissector_index++;
2089 						}
2090 					}
2091 				}
2092 			}
2093 		}
2094 		break;
2095 
2096 	case MYSQL_STMT_EXECUTE:
2097 		proto_tree_add_item(req_tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2098 		stmt_id = tvb_get_letohl(tvb, offset);
2099 		offset += 4;
2100 
2101 		if (conn_data->major_version >= 5) {
2102 			proto_tree_add_item(req_tree, hf_mysql_exec_flags5, tvb, offset, 1, ENC_NA);
2103 		} else {
2104 			proto_tree_add_item(req_tree, hf_mysql_exec_flags4, tvb, offset, 1, ENC_NA);
2105 		}
2106 		offset += 1;
2107 
2108 		proto_tree_add_item(req_tree, hf_mysql_exec_iter, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2109 		offset += 4;
2110 
2111 		stmt_data = (my_stmt_data_t *)wmem_tree_lookup32(conn_data->stmts, stmt_id);
2112 		if (stmt_data != NULL) {
2113 			if (stmt_data->nparam != 0) {
2114 				guint8 stmt_bound;
2115 				offset += (stmt_data->nparam + 7) / 8; /* NULL bitmap */
2116 				proto_tree_add_item(req_tree, hf_mysql_new_parameter_bound_flag, tvb, offset, 1, ENC_NA);
2117 				stmt_bound = tvb_get_guint8(tvb, offset);
2118 				offset += 1;
2119 				if (stmt_bound == 1) {
2120 					param_offset = offset + stmt_data->nparam * 2;
2121 					for (stmt_pos = 0; stmt_pos < stmt_data->nparam; stmt_pos++) {
2122 						if (!mysql_dissect_exec_param(req_tree, tvb, &offset, &param_offset,
2123 									      stmt_data->param_flags[stmt_pos], pinfo))
2124 							break;
2125 					}
2126 					offset = param_offset;
2127 				}
2128 			}
2129 		} else {
2130 			lenstr = tvb_reported_length_remaining(tvb, offset);
2131 			if (tree &&  lenstr > 0) {
2132 				ti = proto_tree_add_item(req_tree, hf_mysql_payload, tvb, offset, lenstr, ENC_NA);
2133 				expert_add_info(pinfo, ti, &ei_mysql_prepare_response_needed);
2134 			}
2135 			offset += lenstr;
2136 		}
2137 #if 0
2138 /* FIXME: rest needs metadata about statement */
2139 #else
2140 		lenstr = tvb_reported_length_remaining(tvb, offset);
2141 		if (tree &&  lenstr > 0) {
2142 			ti = proto_tree_add_item(req_tree, hf_mysql_payload, tvb, offset, lenstr, ENC_NA);
2143 			expert_add_info_format(pinfo, ti, &ei_mysql_dissector_incomplete, "FIXME: execute dissector incomplete");
2144 		}
2145 		offset += lenstr;
2146 #endif
2147 		mysql_set_conn_state(pinfo, conn_data, RESPONSE_TABULAR);
2148 		break;
2149 
2150 	case MYSQL_BINLOG_DUMP_GTID:
2151 	case MYSQL_BINLOG_DUMP:
2152 		proto_tree_add_item(req_tree, hf_mysql_binlog_position, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2153 		offset += 4;
2154 
2155 		proto_tree_add_item(req_tree, hf_mysql_binlog_flags, tvb, offset, 2, ENC_BIG_ENDIAN);
2156 		offset += 2;
2157 
2158 		proto_tree_add_item(req_tree, hf_mysql_binlog_server_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2159 		offset += 4;
2160 
2161 		/* binlog file name ? */
2162 		lenstr = tvb_reported_length_remaining(tvb, offset);
2163 		if (tree &&  lenstr > 0) {
2164 			proto_tree_add_item(req_tree, hf_mysql_binlog_file_name, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
2165 		}
2166 		offset += lenstr;
2167 
2168 		mysql_set_conn_state(pinfo, conn_data, REQUEST);
2169 		break;
2170 /* FIXME: implement replication packets */
2171 	case MYSQL_TABLE_DUMP:
2172 	case MYSQL_CONNECT_OUT:
2173 	case MYSQL_REGISTER_SLAVE:
2174 		ti = proto_tree_add_item(req_tree, hf_mysql_payload, tvb, offset, -1, ENC_NA);
2175 		expert_add_info_format(pinfo, ti, &ei_mysql_dissector_incomplete, "FIXME: implement replication packets");
2176 		offset += tvb_reported_length_remaining(tvb, offset);
2177 		mysql_set_conn_state(pinfo, conn_data, REQUEST);
2178 		break;
2179 
2180 	default:
2181 		ti = proto_tree_add_item(req_tree, hf_mysql_payload, tvb, offset, -1, ENC_NA);
2182 		expert_add_info(pinfo, ti, &ei_mysql_command);
2183 		offset += tvb_reported_length_remaining(tvb, offset);
2184 		mysql_set_conn_state(pinfo, conn_data, UNDEFINED);
2185 	}
2186 
2187 	proto_item_set_end(request_item, tvb, offset);
2188 	return offset;
2189 }
2190 
2191 /*
2192  * Decode the header of a compressed packet
2193  * https://dev.mysql.com/doc/internals/en/compressed-packet-header.html
2194  */
2195 static int
mysql_dissect_compressed_header(tvbuff_t * tvb,int offset,proto_tree * mysql_tree)2196 mysql_dissect_compressed_header(tvbuff_t *tvb, int offset, proto_tree *mysql_tree)
2197 {
2198 	proto_tree_add_item(mysql_tree, hf_mysql_compressed_packet_length, tvb, offset, 3, ENC_LITTLE_ENDIAN);
2199 	offset += 3;
2200 
2201 	proto_tree_add_item(mysql_tree, hf_mysql_compressed_packet_number, tvb, offset, 1, ENC_NA);
2202 	offset += 1;
2203 
2204 	proto_tree_add_item(mysql_tree, hf_mysql_compressed_packet_length_uncompressed, tvb, offset, 3, ENC_LITTLE_ENDIAN);
2205 	offset += 3;
2206 
2207 	return offset;
2208 }
2209 
2210 static int
mysql_dissect_response(tvbuff_t * tvb,packet_info * pinfo,int offset,proto_tree * tree,mysql_conn_data_t * conn_data,mysql_state_t current_state)2211 mysql_dissect_response(tvbuff_t *tvb, packet_info *pinfo, int offset,
2212 		       proto_tree *tree, mysql_conn_data_t *conn_data, mysql_state_t current_state)
2213 {
2214 	gint response_code;
2215 	gint lenstr;
2216 	proto_item *ti;
2217 	guint16 server_status = 0;
2218 
2219 	response_code = tvb_get_guint8(tvb, offset);
2220 
2221 	if (response_code == 0xff ) {
2222 		proto_tree_add_item(tree, hf_mysql_response_code, tvb, offset, 1, ENC_NA);
2223 		offset = mysql_dissect_error_packet(tvb, pinfo, offset+1, tree);
2224 		mysql_set_conn_state(pinfo, conn_data, REQUEST);
2225 	}
2226 
2227 	else if (response_code == 0xfe && tvb_reported_length_remaining(tvb, offset) < 9) {
2228 
2229 		proto_tree_add_item(tree, hf_mysql_response_code, tvb, offset, 1, ENC_NA);
2230 		ti = proto_tree_add_item(tree, hf_mysql_eof, tvb, offset, 1, ENC_NA);
2231 
2232 		offset += 1;
2233 
2234 		/* pre-4.1 packet ends here */
2235 		if (tvb_reported_length_remaining(tvb, offset)) {
2236 			if (conn_data->clnt_caps_ext & MYSQL_CAPS_DE) {
2237 				offset = mysql_dissect_ok_packet(tvb, pinfo, offset, tree, conn_data);
2238 			} else {
2239 				proto_tree_add_item(tree, hf_mysql_num_warn, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2240 				offset = mysql_dissect_server_status(tvb, offset, tree, &server_status);
2241 			}
2242 		}
2243 
2244 		switch (current_state) {
2245 		case FIELD_PACKET:
2246 			mysql_set_conn_state(pinfo, conn_data, ROW_PACKET);
2247 			break;
2248 		case ROW_PACKET:
2249 			if (server_status & MYSQL_STAT_MU) {
2250 				mysql_set_conn_state(pinfo, conn_data, RESPONSE_TABULAR);
2251 			} else {
2252 				mysql_set_conn_state(pinfo, conn_data, REQUEST);
2253 			}
2254 			break;
2255 		case PREPARED_PARAMETERS:
2256 			if (conn_data->stmt_num_fields > 0) {
2257 				mysql_set_conn_state(pinfo, conn_data, PREPARED_FIELDS);
2258 			} else {
2259 				mysql_set_conn_state(pinfo, conn_data, REQUEST);
2260 			}
2261 			break;
2262 		case PREPARED_FIELDS:
2263 			mysql_set_conn_state(pinfo, conn_data, REQUEST);
2264 			break;
2265 		default:
2266 			/* This should be an unreachable case */
2267 			mysql_set_conn_state(pinfo, conn_data, REQUEST);
2268 			expert_add_info(pinfo, ti, &ei_mysql_eof);
2269 		}
2270 	}
2271 
2272 	else if (response_code == 0) {
2273 		proto_tree_add_item(tree, hf_mysql_response_code, tvb, offset, 1, ENC_NA);
2274 		if (current_state == RESPONSE_PREPARE) {
2275 			offset = mysql_dissect_response_prepare(tvb, pinfo, offset, tree, conn_data);
2276 		} else if (tvb_reported_length_remaining(tvb, offset+1)  > tvb_get_fle(tvb, tree, offset+1, NULL, NULL)) {
2277 			offset = mysql_dissect_ok_packet(tvb, pinfo, offset+1, tree, conn_data);
2278 			if (conn_data->compressed_state == MYSQL_COMPRESS_INIT) {
2279 				/* This is the OK packet which follows the compressed protocol setup */
2280 				conn_data->compressed_state = MYSQL_COMPRESS_ACTIVE;
2281 			}
2282 		} else {
2283 			offset = mysql_dissect_result_header(tvb, pinfo, offset, tree, conn_data);
2284 		}
2285 	}
2286 
2287 	else {
2288 		switch (current_state) {
2289 		case RESPONSE_MESSAGE:
2290 			if ((lenstr = tvb_reported_length_remaining(tvb, offset))) {
2291 				proto_tree_add_item(tree, hf_mysql_message, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
2292 				offset += lenstr;
2293 			}
2294 			mysql_set_conn_state(pinfo, conn_data, REQUEST);
2295 			break;
2296 
2297 		case RESPONSE_TABULAR:
2298 		case REQUEST: /* That shouldn't be the case; maybe two requests in a row (s. bug 15074) */
2299 			offset = mysql_dissect_result_header(tvb, pinfo, offset, tree, conn_data);
2300 			break;
2301 
2302 		case FIELD_PACKET:
2303 		case RESPONSE_SHOW_FIELDS:
2304 		case RESPONSE_PREPARE:
2305 		case PREPARED_PARAMETERS:
2306 			offset = mysql_dissect_field_packet(tvb, offset, tree, conn_data);
2307 			mysql_dec_remaining_field_packet_count(conn_data);
2308 			if ((conn_data->clnt_caps_ext & MYSQL_CAPS_DE) && (mysql_get_remaining_field_packet_count(conn_data) == 0)) {
2309 				mysql_set_conn_state(pinfo, conn_data, ROW_PACKET);
2310 			}
2311 			break;
2312 
2313 		case ROW_PACKET:
2314 			offset = mysql_dissect_row_packet(tvb, offset, tree);
2315 			break;
2316 
2317 		case PREPARED_FIELDS:
2318 			offset = mysql_dissect_field_packet(tvb, offset, tree, conn_data);
2319 			break;
2320 
2321 		case AUTH_SWITCH_REQUEST:
2322 			offset = mysql_dissect_auth_switch_request(tvb, pinfo, offset, tree, conn_data);
2323 			break;
2324 
2325 
2326 		default:
2327 			ti = proto_tree_add_item(tree, hf_mysql_payload, tvb, offset, -1, ENC_NA);
2328 			expert_add_info(pinfo, ti, &ei_mysql_unknown_response);
2329 			offset += tvb_reported_length_remaining(tvb, offset);
2330 			mysql_set_conn_state(pinfo, conn_data, UNDEFINED);
2331 		}
2332 	}
2333 
2334 	return offset;
2335 }
2336 
2337 
2338 static int
mysql_dissect_error_packet(tvbuff_t * tvb,packet_info * pinfo,int offset,proto_tree * tree)2339 mysql_dissect_error_packet(tvbuff_t *tvb, packet_info *pinfo,
2340 			   int offset, proto_tree *tree)
2341 {
2342 	col_append_fstr(pinfo->cinfo, COL_INFO, " Error %d ", tvb_get_letohs(tvb, offset));
2343 	col_set_fence(pinfo->cinfo, COL_INFO);
2344 
2345 	proto_tree_add_item(tree, hf_mysql_error_code, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2346 	offset += 2;
2347 
2348 	if (tvb_get_guint8(tvb, offset) == '#')
2349 	{
2350 		offset += 1;
2351 		proto_tree_add_item(tree, hf_mysql_sqlstate, tvb, offset, 5, ENC_ASCII|ENC_NA);
2352 		offset += 5;
2353 	}
2354 
2355 	proto_tree_add_item(tree, hf_mysql_error_string, tvb, offset, -1, ENC_ASCII|ENC_NA);
2356 	offset += tvb_reported_length_remaining(tvb, offset);
2357 
2358 	return offset;
2359 }
2360 
2361 /*
2362   Add a session track entry to the session tracking subtree
2363 
2364   return bytes read
2365 */
2366 static int
add_session_tracker_entry_to_tree(tvbuff_t * tvb,packet_info * pinfo,proto_item * tree,int offset)2367 add_session_tracker_entry_to_tree(tvbuff_t *tvb, packet_info *pinfo, proto_item *tree, int offset) {
2368 	guint8 data_type; /* session tracker type */
2369 	guint64 length; /* complete length of session tracking entry */
2370 	guint64 lenstr;
2371 	int orig_offset = offset, lenfle;
2372 	proto_item *item, *ti;
2373 	proto_tree *session_track_tree;
2374 
2375 	ti = proto_tree_add_item(tree, hf_mysql_session_track, tvb, offset, 1, ENC_NA);
2376 	session_track_tree = proto_item_add_subtree(ti, ett_session_track);
2377 
2378 	proto_tree_add_item(session_track_tree, hf_mysql_session_track_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2379 	data_type = tvb_get_guint8(tvb, offset);
2380 	offset += 1;
2381 
2382 	lenfle = tvb_get_fle(tvb, session_track_tree, offset, &length, NULL);
2383 	proto_tree_add_uint64(session_track_tree, hf_mysql_session_track_length, tvb, offset, lenfle, length);
2384 	offset += lenfle;
2385 
2386 	switch (data_type) {
2387 	case 0: /* SESSION_SYSVARS_TRACKER */
2388 		lenfle = tvb_get_fle(tvb, session_track_tree, offset, &lenstr, NULL);
2389 		proto_tree_add_uint64(session_track_tree, hf_mysql_session_track_sysvar_length, tvb, offset, lenfle, lenstr);
2390 		offset += lenfle;
2391 
2392 		proto_tree_add_item(session_track_tree, hf_mysql_session_track_sysvar_name, tvb, offset, (gint)lenstr, ENC_ASCII|ENC_NA);
2393 		offset += (int)lenstr;
2394 
2395 		lenfle = tvb_get_fle(tvb, session_track_tree, offset, &lenstr, NULL);
2396 		proto_tree_add_uint64(session_track_tree, hf_mysql_session_track_sysvar_length, tvb, offset, lenfle, lenstr);
2397 		offset += lenfle;
2398 
2399 		proto_tree_add_item(session_track_tree, hf_mysql_session_track_sysvar_value, tvb, offset, (gint)lenstr, ENC_ASCII|ENC_NA);
2400 		offset += (int)lenstr;
2401 		break;
2402 	case 1: /* CURRENT_SCHEMA_TRACKER */
2403 		lenfle = tvb_get_fle(tvb, session_track_tree, offset, &lenstr, NULL);
2404 		proto_tree_add_uint64(session_track_tree, hf_mysql_session_track_schema_length, tvb, offset, lenfle, lenstr);
2405 		offset += lenfle;
2406 
2407 		proto_tree_add_item(session_track_tree, hf_mysql_session_track_schema, tvb, offset, (gint)lenstr, ENC_ASCII|ENC_NA);
2408 		offset += (int)lenstr;
2409 		break;
2410 	case 2: /* SESSION_STATE_CHANGE_TRACKER */
2411 		proto_tree_add_item(session_track_tree, hf_mysql_session_state_change, tvb, offset, 1, ENC_ASCII|ENC_NA);
2412 		offset++;
2413 		break;
2414 	case 3: /* SESSION_TRACK_GTIDS */
2415 		proto_tree_add_item(session_track_tree, hf_mysql_session_track_gtids_encoding, tvb, offset, 1, ENC_NA);
2416 		offset++;
2417 		lenfle = tvb_get_fle(tvb, session_track_tree, offset, &lenstr, NULL);
2418 		proto_tree_add_uint64(session_track_tree, hf_mysql_session_track_gtids_length, tvb, offset, lenfle, lenstr);
2419 		offset += lenfle;
2420 
2421 		proto_tree_add_item(session_track_tree, hf_mysql_session_track_gtids, tvb, offset, (gint)lenstr, ENC_ASCII|ENC_NA);
2422 		offset += (int)lenstr;
2423 		break;
2424 	case 4: /* SESSION_TRACK_TRANSACTION_CHARACTERISTICS */
2425 		lenfle = tvb_get_fle(tvb, session_track_tree, offset, &lenstr, NULL);
2426 		proto_tree_add_uint64(session_track_tree, hf_mysql_session_track_transaction_characteristics_length, tvb, offset, lenfle, lenstr);
2427 		offset += lenfle;
2428 
2429 		proto_tree_add_item(session_track_tree, hf_mysql_session_track_transaction_characteristics, tvb, offset, (gint)lenstr, ENC_ASCII|ENC_NA);
2430 		offset += (int)lenstr;
2431 		break;
2432 	case 5: /* SESSION_TRACK_TRANSACTION_STATE */
2433 		lenfle = tvb_get_fle(tvb, session_track_tree, offset, &lenstr, NULL);
2434 		proto_tree_add_uint64(session_track_tree, hf_mysql_session_track_transaction_state_length, tvb, offset, lenfle, lenstr);
2435 		offset += lenfle;
2436 
2437 		proto_tree_add_item(session_track_tree, hf_mysql_session_track_transaction_state, tvb, offset, (gint)lenstr, ENC_ASCII|ENC_NA);
2438 		offset += (int)lenstr;
2439 		break;
2440 	default: /* unsupported types skipped */
2441 		item = proto_tree_add_item(session_track_tree, hf_mysql_payload, tvb, offset, (gint)length, ENC_NA);
2442 		expert_add_info_format(pinfo, item, &ei_mysql_dissector_incomplete, "FIXME: unrecognized session tracker data");
2443 		offset += (int)length;
2444 	}
2445 	proto_item_set_len(ti, offset - orig_offset);
2446 
2447 	return (offset - orig_offset);
2448 }
2449 
2450 static int
mysql_dissect_ok_packet(tvbuff_t * tvb,packet_info * pinfo,int offset,proto_tree * tree,mysql_conn_data_t * conn_data)2451 mysql_dissect_ok_packet(tvbuff_t *tvb, packet_info *pinfo, int offset,
2452 			proto_tree *tree, mysql_conn_data_t *conn_data)
2453 {
2454 	guint64 lenstr;
2455 	guint64 affected_rows;
2456 	guint64 insert_id;
2457 	int fle;
2458 	guint16 server_status = 0;
2459 
2460 	col_append_str(pinfo->cinfo, COL_INFO, " OK " );
2461 	col_set_fence(pinfo->cinfo, COL_INFO);
2462 
2463 	fle = tvb_get_fle(tvb, tree, offset, &affected_rows, NULL);
2464 	proto_tree_add_uint64(tree, hf_mysql_affected_rows, tvb, offset, fle, affected_rows);
2465 	offset += fle;
2466 
2467 	fle= tvb_get_fle(tvb, tree, offset, &insert_id, NULL);
2468 	if (tree && insert_id) {
2469 		proto_tree_add_uint64(tree, hf_mysql_insert_id, tvb, offset, fle, insert_id);
2470 	}
2471 	offset += fle;
2472 
2473 	if (tvb_reported_length_remaining(tvb, offset) > 0) {
2474 		offset = mysql_dissect_server_status(tvb, offset, tree, &server_status);
2475 
2476 		/* 4.1+ protocol only: 2 bytes number of warnings */
2477 		if (conn_data->clnt_caps & conn_data->srv_caps & MYSQL_CAPS_CU) {
2478 			proto_tree_add_item(tree, hf_mysql_num_warn, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2479 		offset += 2;
2480 		}
2481 	}
2482 
2483 	if (conn_data->clnt_caps_ext & MYSQL_CAPS_ST) {
2484 		if (tvb_reported_length_remaining(tvb, offset) > 0) {
2485 			guint64 session_track_length;
2486 			proto_item *tf;
2487 			proto_item *session_track_tree = NULL;
2488 			int length;
2489 
2490 			offset += tvb_get_fle(tvb, tree, offset, &lenstr, NULL);
2491 			/* first read the optional message */
2492 			if (lenstr) {
2493 				proto_tree_add_item(tree, hf_mysql_message, tvb, offset, (gint)lenstr, ENC_ASCII|ENC_NA);
2494 				offset += (int)lenstr;
2495 			}
2496 
2497 			/* session state tracking */
2498 			if (server_status & MYSQL_STAT_SESSION_STATE_CHANGED) {
2499 				fle = tvb_get_fle(tvb, tree, offset, &session_track_length, NULL);
2500 				tf = proto_tree_add_item(tree, hf_mysql_session_track_data, tvb, offset, -1, ENC_NA);
2501 				session_track_tree = proto_item_add_subtree(tf, ett_session_track_data);
2502 				proto_tree_add_uint64(tf, hf_mysql_session_track_data_length, tvb, offset, fle, session_track_length);
2503 				offset += fle;
2504 
2505 				while (session_track_length > 0) {
2506 					length = add_session_tracker_entry_to_tree(tvb, pinfo, session_track_tree, offset);
2507 					offset += length;
2508 					session_track_length -= length;
2509 				}
2510 			}
2511 		}
2512 	} else {
2513 		/* optional: message string */
2514 		if (tvb_reported_length_remaining(tvb, offset) > 0) {
2515 			lenstr = tvb_reported_length_remaining(tvb, offset);
2516 			proto_tree_add_item(tree, hf_mysql_message, tvb, offset, (gint)lenstr, ENC_ASCII|ENC_NA);
2517 			offset += (int)lenstr;
2518 		}
2519 	}
2520 
2521 	mysql_set_conn_state(pinfo, conn_data, REQUEST);
2522 	return offset;
2523 }
2524 
2525 
2526 static int
mysql_dissect_server_status(tvbuff_t * tvb,int offset,proto_tree * tree,guint16 * server_status)2527 mysql_dissect_server_status(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *server_status)
2528 {
2529 
2530 	if (server_status) {
2531 		*server_status = tvb_get_letohs(tvb, offset);
2532 	}
2533 	proto_tree_add_bitmask_with_flags(tree, tvb, offset, hf_mysql_server_status, ett_stat, mysql_stat_flags, ENC_LITTLE_ENDIAN, BMT_NO_APPEND);
2534 
2535 	offset += 2;
2536 
2537 	return offset;
2538 }
2539 
2540 
2541 static int
mysql_dissect_caps(tvbuff_t * tvb,int offset,proto_tree * tree,int mysql_caps,guint16 * caps)2542 mysql_dissect_caps(tvbuff_t *tvb, int offset, proto_tree *tree, int mysql_caps, guint16 *caps)
2543 {
2544 
2545 	*caps= tvb_get_letohs(tvb, offset);
2546 
2547 	proto_tree_add_bitmask_with_flags(tree, tvb, offset, mysql_caps, ett_caps, mysql_caps_flags, ENC_LITTLE_ENDIAN, BMT_NO_APPEND);
2548 
2549 	offset += 2;
2550 	return offset;
2551 }
2552 
2553 static int
mysql_dissect_extcaps(tvbuff_t * tvb,int offset,proto_tree * tree,int mysql_extcaps,guint16 * ext_caps)2554 mysql_dissect_extcaps(tvbuff_t *tvb, int offset, proto_tree *tree, int mysql_extcaps, guint16 *ext_caps)
2555 {
2556 
2557 	*ext_caps= tvb_get_letohs(tvb, offset);
2558 
2559 	proto_tree_add_bitmask_with_flags(tree, tvb, offset, mysql_extcaps, ett_extcaps, mysql_extcaps_flags, ENC_LITTLE_ENDIAN, BMT_NO_APPEND);
2560 
2561 	offset += 2;
2562 	return offset;
2563 }
2564 
mariadb_dissect_caps_or_flags(tvbuff_t * tvb,int offset,enum ftenum type,proto_tree * tree,int mariadb_caps,int * const * fields,void * value)2565 static int mariadb_dissect_caps_or_flags(tvbuff_t *tvb, int offset, enum ftenum type, proto_tree *tree,
2566                                 int mariadb_caps, int * const *fields, void *value)
2567 {
2568 	guint8 diff= 0;
2569 
2570 	switch (type) {
2571 	case FT_UINT8:
2572 		*((guint8 *)value)= tvb_get_guint8(tvb, offset);
2573 		diff= 1;
2574 		break;
2575 	case FT_UINT16:
2576 		*((guint16 *)value)= tvb_get_letohs(tvb, offset);
2577 		diff= 2;
2578 		break;
2579 	case FT_UINT32:
2580 		*((guint32 *)value)= tvb_get_letohl(tvb, offset);
2581 		diff= 4;
2582 		break;
2583 	default:
2584 		return 0;
2585 	}
2586 	proto_tree_add_bitmask_with_flags(tree, tvb, offset, mariadb_caps, ett_extcaps, fields, ENC_LITTLE_ENDIAN, BMT_NO_APPEND);
2587 
2588 	offset+= diff;
2589 	return offset;
2590 }
2591 
2592 
2593 static int
mysql_dissect_result_header(tvbuff_t * tvb,packet_info * pinfo,int offset,proto_tree * tree,mysql_conn_data_t * conn_data)2594 mysql_dissect_result_header(tvbuff_t *tvb, packet_info *pinfo, int offset,
2595 			    proto_tree *tree, mysql_conn_data_t *conn_data)
2596 {
2597 	gint fle;
2598 	guint64 num_fields, extra;
2599 
2600 	col_append_str(pinfo->cinfo, COL_INFO, "TABULAR " );
2601 	col_set_fence(pinfo->cinfo, COL_INFO);
2602 
2603 	fle = tvb_get_fle(tvb, tree, offset, &num_fields, NULL);
2604 	proto_tree_add_uint64(tree, hf_mysql_num_fields, tvb, offset, fle, num_fields);
2605 	offset += fle;
2606 
2607 	if (tvb_reported_length_remaining(tvb, offset)) {
2608 		fle = tvb_get_fle(tvb, tree, offset, &extra, NULL);
2609 		proto_tree_add_uint64(tree, hf_mysql_extra, tvb, offset, fle, extra);
2610 		offset += fle;
2611 	}
2612 
2613 	if (num_fields) {
2614 		mysql_set_conn_state(pinfo, conn_data, FIELD_PACKET);
2615 		mysql_set_remaining_field_packet_count(conn_data, num_fields);
2616 	} else {
2617 		mysql_set_conn_state(pinfo, conn_data, ROW_PACKET);
2618 	}
2619 
2620 	return offset;
2621 }
2622 
2623 
2624 /*
2625  * Add length encoded string to tree
2626  */
2627 static int
mysql_field_add_lestring(tvbuff_t * tvb,int offset,proto_tree * tree,int field)2628 mysql_field_add_lestring(tvbuff_t *tvb, int offset, proto_tree *tree, int field)
2629 {
2630 	guint64 lelen;
2631 	guint8 is_null;
2632 	header_field_info* hfi;
2633 	proto_item* ti;
2634 	proto_tree* sub_tree;
2635 	int start_offset = offset;
2636 
2637 	hfi = proto_registrar_get_nth(field);
2638 	DISSECTOR_ASSERT(hfi != NULL);
2639 
2640 	sub_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1, ett_mysql_field, &ti, "%s", hfi->name);
2641 
2642 	offset += tvb_get_fle(tvb, sub_tree, offset, &lelen, &is_null);
2643 	if(is_null)
2644 		proto_tree_add_string(sub_tree, field, tvb, offset, 0, "NULL");
2645 	else
2646 	{
2647 		proto_tree_add_item(sub_tree, field, tvb, offset, (int)lelen, ENC_NA);
2648 		/* Prevent infinite loop due to overflow */
2649 		if (offset + (int)lelen < offset) {
2650 			offset = tvb_reported_length(tvb);
2651 		}
2652 		else {
2653 			offset += (int)lelen;
2654 		}
2655 	}
2656 	proto_item_set_len(ti, offset -start_offset);
2657 	return offset;
2658 }
2659 
2660 
2661 static int
mysql_dissect_field_packet(tvbuff_t * tvb,int offset,proto_tree * tree,mysql_conn_data_t * conn_data _U_)2662 mysql_dissect_field_packet(tvbuff_t *tvb, int offset, proto_tree *tree, mysql_conn_data_t *conn_data _U_)
2663 {
2664 	int length = tvb_reported_length(tvb);
2665 
2666 	/* Are these fields optional? a trace suggests they are...*/
2667 	offset = mysql_field_add_lestring(tvb, offset, tree, hf_mysql_fld_catalog);
2668 	if (offset >= length) {
2669 		return offset;
2670 	}
2671 	offset = mysql_field_add_lestring(tvb, offset, tree, hf_mysql_fld_db);
2672 	offset = mysql_field_add_lestring(tvb, offset, tree, hf_mysql_fld_table);
2673 	offset = mysql_field_add_lestring(tvb, offset, tree, hf_mysql_fld_org_table);
2674 	offset = mysql_field_add_lestring(tvb, offset, tree, hf_mysql_fld_name);
2675 	offset = mysql_field_add_lestring(tvb, offset, tree, hf_mysql_fld_org_name);
2676 	offset +=1; /* filler */
2677 
2678 	proto_tree_add_item(tree, hf_mysql_fld_charsetnr, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2679 	offset += 2; /* charset */
2680 
2681 	proto_tree_add_item(tree, hf_mysql_fld_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2682 	offset += 4; /* length */
2683 
2684 	proto_tree_add_item(tree, hf_mysql_fld_type, tvb, offset, 1, ENC_NA);
2685 	offset += 1; /* type */
2686 
2687 	proto_tree_add_bitmask_with_flags(tree, tvb, offset, hf_mysql_fld_flags, ett_field_flags, mysql_fld_flags, ENC_LITTLE_ENDIAN, BMT_NO_APPEND);
2688 	offset += 2; /* flags */
2689 
2690 	proto_tree_add_item(tree, hf_mysql_fld_decimals, tvb, offset, 1, ENC_NA);
2691 	offset += 1; /* decimals */
2692 
2693 	offset += 2; /* filler */
2694 
2695 	/* default (Only use for show fields) */
2696 	if (tree && tvb_reported_length_remaining(tvb, offset) > 0) {
2697 		offset = mysql_field_add_lestring(tvb, offset, tree, hf_mysql_fld_default);
2698 	}
2699 	return offset;
2700 }
2701 
2702 
2703 static int
mysql_dissect_row_packet(tvbuff_t * tvb,int offset,proto_tree * tree)2704 mysql_dissect_row_packet(tvbuff_t *tvb, int offset, proto_tree *tree)
2705 {
2706 	while (tvb_reported_length_remaining(tvb, offset) > 0) {
2707 		offset = mysql_field_add_lestring(tvb, offset, tree, hf_mysql_row_text);
2708 	}
2709 
2710 	return offset;
2711 }
2712 
2713 
2714 static int
mysql_dissect_response_prepare(tvbuff_t * tvb,packet_info * pinfo,int offset,proto_tree * tree,mysql_conn_data_t * conn_data)2715 mysql_dissect_response_prepare(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, mysql_conn_data_t *conn_data)
2716 {
2717 	my_stmt_data_t *stmt_data;
2718 	guint32 stmt_id;
2719 	int flagsize;
2720 
2721 	/* 0, marker for OK packet */
2722 	offset += 1;
2723 	proto_tree_add_item(tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2724 	stmt_id = tvb_get_letohl(tvb, offset);
2725 	offset += 4;
2726 	proto_tree_add_item(tree, hf_mysql_num_fields, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2727 	conn_data->stmt_num_fields = tvb_get_letohs(tvb, offset);
2728 	offset += 2;
2729 	proto_tree_add_item(tree, hf_mysql_num_params, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2730 	conn_data->stmt_num_params = tvb_get_letohs(tvb, offset);
2731 	stmt_data = wmem_new(wmem_file_scope(), struct my_stmt_data);
2732 	stmt_data->nparam = conn_data->stmt_num_params;
2733 	flagsize = (int)(sizeof(guint8) * stmt_data->nparam);
2734 	stmt_data->param_flags = (guint8 *)wmem_alloc(wmem_file_scope(), flagsize);
2735 	memset(stmt_data->param_flags, 0, flagsize);
2736 	stmt_data->param_types = (guint8 *)wmem_alloc(wmem_file_scope(), flagsize);
2737 	memset(stmt_data->param_types, 0, flagsize);
2738 
2739 	wmem_tree_insert32(conn_data->stmts, stmt_id, stmt_data);
2740 	offset += 2;
2741 	/* Filler */
2742 	offset += 1;
2743 	proto_tree_add_item(tree, hf_mysql_num_warn, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2744 
2745 	if (conn_data->stmt_num_params > 0)
2746 		mysql_set_conn_state(pinfo, conn_data, PREPARED_PARAMETERS);
2747 	else if (conn_data->stmt_num_fields > 0)
2748 		mysql_set_conn_state(pinfo, conn_data, PREPARED_FIELDS);
2749 	else
2750 		mysql_set_conn_state(pinfo, conn_data, REQUEST);
2751 
2752 	return offset + tvb_reported_length_remaining(tvb, offset);
2753 }
2754 
2755 
2756 static int
mysql_dissect_auth_switch_request(tvbuff_t * tvb,packet_info * pinfo,int offset,proto_tree * tree,mysql_conn_data_t * conn_data _U_)2757 mysql_dissect_auth_switch_request(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, mysql_conn_data_t *conn_data _U_)
2758 {
2759 	gint lenstr;
2760 
2761 	col_set_str(pinfo->cinfo, COL_INFO, "Auth Switch Request " );
2762 	col_set_fence(pinfo->cinfo, COL_INFO);
2763 	mysql_set_conn_state(pinfo, conn_data, AUTH_SWITCH_RESPONSE);
2764 
2765 	/* Status (Always 0xfe) */
2766 	proto_tree_add_item(tree, hf_mysql_auth_switch_request_status, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2767 	offset += 1;
2768 
2769 	/* name */
2770 	lenstr = my_tvb_strsize(tvb, offset);
2771 	proto_tree_add_item(tree, hf_mysql_auth_switch_request_name, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
2772 	offset += lenstr;
2773 
2774 	/* Data */
2775 	lenstr = my_tvb_strsize(tvb, offset);
2776 	proto_tree_add_item(tree, hf_mysql_auth_switch_request_data, tvb, offset, lenstr, ENC_NA);
2777 	offset += lenstr;
2778 
2779 	return offset + tvb_reported_length_remaining(tvb, offset);
2780 
2781 }
2782 static int
mysql_dissect_auth_switch_response(tvbuff_t * tvb,packet_info * pinfo,int offset,proto_tree * tree,mysql_conn_data_t * conn_data _U_)2783 mysql_dissect_auth_switch_response(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, mysql_conn_data_t *conn_data _U_)
2784 {
2785 	gint lenstr;
2786 
2787 	col_set_str(pinfo->cinfo, COL_INFO, "Auth Switch Response " );
2788 	col_set_fence(pinfo->cinfo, COL_INFO);
2789 
2790 	/* Data */
2791 	lenstr = my_tvb_strsize(tvb, offset);
2792 	proto_tree_add_item(tree, hf_mysql_auth_switch_response_data, tvb, offset, lenstr, ENC_NA);
2793 	offset += lenstr;
2794 
2795 	return offset + tvb_reported_length_remaining(tvb, offset);
2796 
2797 }
2798 /*
2799  get length of string in packet buffer
2800 
2801  SYNOPSIS
2802    my_tvb_strsize()
2803      tvb      packet buffer
2804      offset   current offset
2805 
2806  DESCRIPTION
2807    deliver length of string, delimited by either \0 or end of buffer
2808 
2809  RETURN VALUE
2810    length of string found, including \0 (if present)
2811 
2812 */
2813 static gint
my_tvb_strsize(tvbuff_t * tvb,int offset)2814 my_tvb_strsize(tvbuff_t *tvb, int offset)
2815 {
2816 	gint len = tvb_strnlen(tvb, offset, -1);
2817 	if (len == -1) {
2818 		len = tvb_reported_length_remaining(tvb, offset);
2819 	} else {
2820 		len++; /* the trailing \0 */
2821 	}
2822 	return len;
2823 }
2824 
2825 /*
2826  read "field length encoded" value from packet buffer
2827 
2828  SYNOPSIS
2829    tvb_get_fle()
2830      tvb     in    packet buffer
2831      tree    in....protocol tree
2832      offset  in    offset in buffer
2833      res     out   where to store FLE value, may be NULL
2834      is_null out   where to store ISNULL flag, may be NULL
2835 
2836  DESCRIPTION
2837    read FLE from packet buffer and store its value and ISNULL flag
2838    in caller provided variables
2839 
2840  RETURN VALUE
2841    length of FLE
2842 */
2843 static int
tvb_get_fle(tvbuff_t * tvb,proto_tree * tree,int offset,guint64 * res,guint8 * is_null)2844 tvb_get_fle(tvbuff_t *tvb, proto_tree *tree, int offset, guint64 *res, guint8 *is_null)
2845 {
2846 	guint32 prefix;
2847 	proto_item* ti;
2848 	int num_bytes, len_len;
2849 	guint64 length;
2850 
2851 	ti = proto_tree_add_item_ret_uint(tree, hf_mysql_prefix, tvb, offset, 1, ENC_BIG_ENDIAN, &prefix);
2852 
2853 	if (is_null) {
2854 		*is_null = 0;
2855 	}
2856 
2857 	switch (prefix) {
2858 	case 251:
2859 		if (res)
2860 			*res = 0;
2861 		if (is_null)
2862 			*is_null = 1;
2863 		proto_item_append_text(ti, "(NULL)");
2864 		return 1;
2865 	case 252:
2866 		proto_item_append_text(ti, " Length in following 2 bytes");
2867 		num_bytes = 3;
2868 		len_len = 2;
2869 		offset++;
2870 		break;
2871 	case 253:
2872 		proto_item_append_text(ti, " Length in following 4 bytes");
2873 		num_bytes = 5;
2874 		len_len = 4;
2875 		offset++;
2876 		break;
2877 	case 254:
2878 		proto_item_append_text(ti, " Length in following 8 bytes");
2879 		num_bytes = 9;
2880 		len_len = 8;
2881 		offset++;
2882 		break;
2883 	default:
2884 		len_len = 1;
2885 		num_bytes = 1;
2886 	}
2887 
2888 	proto_tree_add_item_ret_uint64(tree, hf_mysql_length, tvb, offset, len_len, ENC_LITTLE_ENDIAN, &length);
2889 	if (res) {
2890 		*res = length;
2891 	}
2892 	return num_bytes;
2893 }
2894 
2895 /* dissector helper: length of PDU */
2896 static guint
get_mysql_pdu_len(packet_info * pinfo,tvbuff_t * tvb,int offset,void * data _U_)2897 get_mysql_pdu_len(packet_info *pinfo, tvbuff_t *tvb, int offset, void *data _U_)
2898 {
2899 	/* Regular packet header: length (3) + sequence number (1) */
2900 	conversation_t	   *conversation;
2901 	mysql_conn_data_t  *conn_data;
2902 	guint		    len = 4 + tvb_get_letoh24(tvb, offset);
2903 
2904 	conversation = find_conversation_pinfo(pinfo, 0);
2905 	if (conversation) {
2906 		conn_data = (mysql_conn_data_t *)conversation_get_proto_data(conversation, proto_mysql);
2907 		if (conn_data && conn_data->compressed_state == MYSQL_COMPRESS_ACTIVE &&
2908 			pinfo->num > conn_data->frame_start_compressed) {
2909 			/* Compressed packet header includes uncompressed packet length (3) */
2910 			len += 3;
2911 		}
2912 	}
2913 
2914 	return len;
2915 }
2916 
2917 /* dissector main function: handle one PDU */
2918 static int
dissect_mysql_pdu(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2919 dissect_mysql_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2920 {
2921 	proto_tree      *mysql_tree= NULL;
2922 	proto_item      *ti;
2923 	conversation_t  *conversation;
2924 	int             offset = 0;
2925 	guint           packet_number;
2926 	gboolean        is_response, is_tls = FALSE;
2927 	mysql_conn_data_t  *conn_data;
2928 #ifdef CTDEBUG
2929 	mysql_state_t conn_state_in, conn_state_out, frame_state;
2930 	guint64         generation;
2931 	proto_item *pi;
2932 #endif
2933 	struct mysql_frame_data  *mysql_frame_data_p;
2934 
2935 	/* get conversation, create if necessary*/
2936 	conversation= find_or_create_conversation(pinfo);
2937 
2938 	/* get associated state information, create if necessary */
2939 	conn_data= (mysql_conn_data_t *)conversation_get_proto_data(conversation, proto_mysql);
2940 	if (!conn_data) {
2941 		conn_data = wmem_new0(wmem_file_scope(), mysql_conn_data_t);
2942 		conn_data->stmts = wmem_tree_new(wmem_file_scope());
2943 		conversation_add_proto_data(conversation, proto_mysql, conn_data);
2944 	}
2945 
2946 	/* Using tvb_raw_offset(tvb) allows storage of multiple "proto data" in a single frame
2947 	 * (when there are multiple MySQL pdus in a single frame) */
2948 	mysql_frame_data_p = (struct mysql_frame_data *)p_get_proto_data(wmem_file_scope(), pinfo, proto_mysql, tvb_raw_offset(tvb));
2949 	if (!mysql_frame_data_p) {
2950 		/*  We haven't seen this frame before.  Store the state of the
2951 		 *  conversation now so if/when we dissect the frame again
2952 		 *  we'll start with the same state.
2953 		 */
2954 		mysql_frame_data_p = wmem_new(wmem_file_scope(), struct mysql_frame_data);
2955 		mysql_frame_data_p->state = conn_data->state;
2956 		p_add_proto_data(wmem_file_scope(), pinfo, proto_mysql, tvb_raw_offset(tvb), mysql_frame_data_p);
2957 	}
2958 
2959 	if ((conn_data->frame_start_compressed) && (pinfo->num > conn_data->frame_start_compressed)) {
2960 		if (conn_data->compressed_state == MYSQL_COMPRESS_ACTIVE) {
2961 			offset = mysql_dissect_compressed_header(tvb, offset, tree);
2962 		}
2963 	}
2964 
2965 	ti = proto_tree_add_item(tree, proto_mysql, tvb, offset, -1, ENC_NA);
2966 	mysql_tree = proto_item_add_subtree(ti, ett_mysql);
2967 	proto_tree_add_item(mysql_tree, hf_mysql_packet_length, tvb, offset, 3, ENC_LITTLE_ENDIAN);
2968 	offset+= 3;
2969 
2970 	col_set_str(pinfo->cinfo, COL_PROTOCOL, "MySQL");
2971 
2972 	if (pinfo->destport == pinfo->match_uint) {
2973 		is_response= FALSE;
2974 	} else {
2975 		is_response= TRUE;
2976 	}
2977 
2978 	packet_number = tvb_get_guint8(tvb, offset);
2979 	proto_tree_add_item(mysql_tree, hf_mysql_packet_number, tvb, offset, 1, ENC_NA);
2980 	offset += 1;
2981 
2982 #ifdef CTDEBUG
2983 	conn_state_in= conn_data->state;
2984 	frame_state = mysql_frame_data_p->state;
2985 	generation= conn_data->generation;
2986 	if (tree) {
2987 		pi = proto_tree_add_debug_text(mysql_tree, "conversation: %p", conversation);
2988 		proto_item_set_generated(pi);
2989 		pi = proto_tree_add_debug_text(mysql_tree, "generation: %" G_GINT64_MODIFIER "d", generation);
2990 		proto_item_set_generated(pi);
2991 		pi = proto_tree_add_debug_text(mysql_tree, "conn state: %s (%u)",
2992 				    val_to_str(conn_state_in, state_vals, "Unknown (%u)"),
2993 				    conn_state_in);
2994 		proto_item_set_generated(pi);
2995 		pi = proto_tree_add_debug_text(mysql_tree, "frame state: %s (%u)",
2996 				    val_to_str(frame_state, state_vals, "Unknown (%u)"),
2997 				    frame_state);
2998 		proto_item_set_generated(pi);
2999 	}
3000 #endif
3001 
3002 	is_tls = proto_is_frame_protocol(pinfo->layers, "tls");
3003 
3004 	if (is_response) {
3005 		if (packet_number == 0 && mysql_frame_data_p->state == UNDEFINED) {
3006 			col_set_str(pinfo->cinfo, COL_INFO, "Server Greeting ");
3007 			offset = mysql_dissect_greeting(tvb, pinfo, offset, mysql_tree, conn_data);
3008 		} else {
3009 			col_set_str(pinfo->cinfo, COL_INFO, "Response ");
3010 			offset = mysql_dissect_response(tvb, pinfo, offset, mysql_tree, conn_data, mysql_frame_data_p->state);
3011 		}
3012 	} else {
3013 		if (mysql_frame_data_p->state == LOGIN && (packet_number == 1 || (packet_number == 2 && is_tls))) {
3014 			col_set_str(pinfo->cinfo, COL_INFO, "Login Request");
3015 			offset = mysql_dissect_login(tvb, pinfo, offset, mysql_tree, conn_data);
3016 			if (conn_data->srv_caps & MYSQL_CAPS_CP) {
3017 				if (conn_data->clnt_caps & MYSQL_CAPS_CP) {
3018 					conn_data->frame_start_compressed = pinfo->num;
3019 					conn_data->compressed_state = MYSQL_COMPRESS_INIT;
3020 				}
3021 			}
3022 		} else {
3023 			col_set_str(pinfo->cinfo, COL_INFO, "Request");
3024 			offset = mysql_dissect_request(tvb, pinfo, offset, mysql_tree, conn_data, mysql_frame_data_p->state);
3025 		}
3026 	}
3027 
3028 #ifdef CTDEBUG
3029 	conn_state_out= conn_data->state;
3030 	++(conn_data->generation);
3031 	pi = proto_tree_add_debug_text(mysql_tree, "next proto state: %s (%u)",
3032 			    val_to_str(conn_state_out, state_vals, "Unknown (%u)"),
3033 			    conn_state_out);
3034 	proto_item_set_generated(pi);
3035 #endif
3036 
3037 	/* remaining payload indicates an error */
3038 	if (tvb_reported_length_remaining(tvb, offset) > 0) {
3039 		ti = proto_tree_add_item(mysql_tree, hf_mysql_payload, tvb, offset, -1, ENC_NA);
3040 		expert_add_info(pinfo, ti, &ei_mysql_dissector_incomplete);
3041 	}
3042 
3043 	return tvb_reported_length(tvb);
3044 }
3045 
3046 /* dissector entrypoint, handles TCP-desegmentation */
3047 static int
dissect_mysql(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3048 dissect_mysql(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
3049 {
3050 	tcp_dissect_pdus(tvb, pinfo, tree, mysql_desegment, 3,
3051 			 get_mysql_pdu_len, dissect_mysql_pdu, data);
3052 
3053 	return tvb_reported_length(tvb);
3054 }
3055 
3056 /* protocol registration */
proto_register_mysql(void)3057 void proto_register_mysql(void)
3058 {
3059 	static hf_register_info hf[]=
3060 	{
3061 		{ &hf_mysql_packet_length,
3062 		{ "Packet Length", "mysql.packet_length",
3063 		FT_UINT24, BASE_DEC, NULL,  0x0,
3064 		NULL, HFILL }},
3065 
3066 		{ &hf_mysql_packet_number,
3067 		{ "Packet Number", "mysql.packet_number",
3068 		FT_UINT8, BASE_DEC, NULL, 0x0,
3069 		"Packet Number (now called: Sequence ID)", HFILL }},
3070 
3071 		{ &hf_mysql_request,
3072 		{ "Request Command", "mysql.request",
3073 		FT_NONE, BASE_NONE, NULL, 0x0,
3074 		NULL, HFILL }},
3075 
3076 		{ &hf_mysql_command,
3077 		{ "Command", "mysql.command",
3078 		FT_UINT8, BASE_DEC|BASE_EXT_STRING, &mysql_command_vals_ext, 0x0,
3079 		NULL, HFILL }},
3080 
3081 		{ &hf_mysql_response_code,
3082 		{ "Response Code", "mysql.response_code",
3083 		FT_UINT8, BASE_HEX, VALS(mysql_response_code_vals), 0x0,
3084 		NULL, HFILL }},
3085 
3086 		{ &hf_mysql_error_code,
3087 		{ "Error Code", "mysql.error_code",
3088 		FT_UINT16, BASE_DEC, NULL, 0x0,
3089 		NULL, HFILL }},
3090 
3091 		{ &hf_mysql_error_string,
3092 		{ "Error message", "mysql.error.message",
3093 		FT_STRING, BASE_NONE, NULL, 0x0,
3094 		"Error string in case of MySQL error message", HFILL }},
3095 
3096 		{ &hf_mysql_sqlstate,
3097 		{ "SQL state", "mysql.sqlstate",
3098 		FT_STRING, BASE_NONE, NULL, 0x0,
3099 		NULL, HFILL }},
3100 
3101 		{ &hf_mysql_message,
3102 		{ "Message", "mysql.message",
3103 		FT_STRINGZ, BASE_NONE, NULL, 0x0,
3104 		NULL, HFILL }},
3105 
3106 		{ &hf_mysql_server_greeting,
3107 		{ "Server Greeting", "mysql.server_greeting",
3108 		FT_NONE, BASE_NONE, NULL, 0x0,
3109 		NULL, HFILL }},
3110 
3111 		{ &hf_mysql_protocol,
3112 		{ "Protocol", "mysql.protocol",
3113 		FT_UINT8, BASE_DEC, NULL, 0x0,
3114 		"Protocol Version", HFILL }},
3115 
3116 		{ &hf_mysql_version,
3117 		{ "Version", "mysql.version",
3118 		FT_STRINGZ, BASE_NONE, NULL, 0x0,
3119 		"MySQL Version", HFILL }},
3120 
3121 		{ &hf_mysql_session_track,
3122 		{ "Session Track", "mysql.session_track",
3123 		  FT_NONE, BASE_NONE, NULL, 0x0,
3124 		  NULL, HFILL }},
3125 
3126 		{ &hf_mysql_session_track_type,
3127 		{ "Session tracking type", "mysql.session_track.type",
3128 		  FT_UINT8, BASE_DEC, VALS(mysql_session_track_type_vals), 0x0,
3129 		  NULL, HFILL }},
3130 
3131 		{ &hf_mysql_session_track_length,
3132 		{ "Session tracking length", "mysql.session_track.length",
3133 		  FT_UINT64, BASE_DEC, NULL, 0x0,
3134 		  NULL, HFILL }},
3135 
3136 		{ &hf_mysql_session_track_data,
3137 		{ "Session tracking data", "mysql.session_track.data",
3138 		  FT_NONE, BASE_NONE, NULL, 0x0,
3139 		  NULL, HFILL }},
3140 
3141 		{ &hf_mysql_session_track_data_length,
3142 		{ "Session tracking data length", "mysql.session_track.data.length",
3143 		  FT_UINT64, BASE_DEC, NULL, 0x0,
3144 		  NULL, HFILL }},
3145 
3146 		{ &hf_mysql_session_track_sysvar_length,
3147 		{ "System variable change Length", "mysql.session_track.sysvar.length",
3148 		  FT_UINT64, BASE_DEC, NULL, 0x0,
3149 		  NULL, HFILL }},
3150 
3151 		{ &hf_mysql_session_track_sysvar_name,
3152 		{ "System variable change Name", "mysql.session_track.sysvar.name",
3153 		  FT_STRINGZ, BASE_NONE, NULL, 0x0,
3154 		  NULL, HFILL }},
3155 
3156 		{ &hf_mysql_session_track_sysvar_value,
3157 		{ "System variable change Value", "mysql.session_track.sysvar.value",
3158 		  FT_STRINGZ, BASE_NONE, NULL, 0x0,
3159 		  NULL, HFILL }},
3160 
3161 		{ &hf_mysql_session_track_schema_length,
3162 		{ "Schema change length", "mysql.session_track.schema.length",
3163 		  FT_UINT64, BASE_DEC, NULL, 0x0,
3164 		  NULL, HFILL }},
3165 
3166 		{ &hf_mysql_session_track_schema,
3167 		{ "Schema change", "mysql.session_track.schema",
3168 		  FT_STRINGZ, BASE_NONE, NULL, 0x0,
3169 		  NULL, HFILL }},
3170 
3171 		{ &hf_mysql_session_state_change,
3172 		{ "State change", "mysql.session_track.state_change",
3173 		  FT_STRINGZ, BASE_NONE, NULL, 0x0,
3174 		  NULL, HFILL }},
3175 
3176 		{ &hf_mysql_session_track_gtids_encoding,
3177 		{ "GTIDs encoding", "mysql.session_track.gtids.encoding",
3178 		  FT_UINT8, BASE_DEC, NULL, 0x0,
3179 		  NULL, HFILL }},
3180 
3181 		{ &hf_mysql_session_track_gtids_length,
3182 		{ "GTIDs length", "mysql.session_track.gtids.length",
3183 		  FT_UINT64, BASE_DEC, NULL, 0x0,
3184 		  NULL, HFILL }},
3185 
3186 		{ &hf_mysql_session_track_gtids,
3187 		{ "GTIDs", "mysql.session_track.gtids",
3188 		  FT_STRINGZ, BASE_NONE, NULL, 0x0,
3189 		  NULL, HFILL }},
3190 
3191 		{ &hf_mysql_session_track_transaction_characteristics_length,
3192 		{ "Transaction characteristics length", "mysql.session_track.transaction_characteristics.length",
3193 		  FT_UINT64, BASE_DEC, NULL, 0x0,
3194 		  NULL, HFILL }},
3195 
3196 		{ &hf_mysql_session_track_transaction_characteristics,
3197 		{ "Transaction characteristics", "mysql.session_track.transaction_characteristics",
3198 		  FT_STRINGZ, BASE_NONE, NULL, 0x0,
3199 		  NULL, HFILL }},
3200 
3201 		{ &hf_mysql_session_track_transaction_state_length,
3202 		{ "Transaction state length", "mysql.session_track.transaction_state.length",
3203 		  FT_UINT64, BASE_DEC, NULL, 0x0,
3204 		  NULL, HFILL }},
3205 
3206 		{ &hf_mysql_session_track_transaction_state,
3207 		{ "Transaction state", "mysql.session_track.transaction_state",
3208 		  FT_STRINGZ, BASE_NONE, NULL, 0x0,
3209 		  NULL, HFILL }},
3210 
3211 		{ &hf_mysql_caps_server,
3212 		{ "Server Capabilities", "mysql.caps.server",
3213 		FT_UINT16, BASE_HEX, NULL, 0x0,
3214 		"MySQL Capabilities", HFILL }},
3215 
3216 		{ &hf_mysql_caps_client,
3217 		{ "Client Capabilities", "mysql.caps.client",
3218 		FT_UINT16, BASE_HEX, NULL, 0x0,
3219 		"MySQL Capabilities", HFILL }},
3220 
3221 		{ &hf_mysql_cap_long_password,
3222 		{ "Long Password","mysql.caps.lp",
3223 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_LP,
3224 		NULL, HFILL }},
3225 
3226 		{ &hf_mysql_cap_found_rows,
3227 		{ "Found Rows","mysql.caps.fr",
3228 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_FR,
3229 		NULL, HFILL }},
3230 
3231 		{ &hf_mysql_cap_long_flag,
3232 		{ "Long Column Flags","mysql.caps.lf",
3233 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_LF,
3234 		NULL, HFILL }},
3235 
3236 		{ &hf_mysql_cap_connect_with_db,
3237 		{ "Connect With Database","mysql.caps.cd",
3238 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_CD,
3239 		NULL, HFILL }},
3240 
3241 		{ &hf_mysql_cap_no_schema,
3242 		{ "Don't Allow database.table.column","mysql.caps.ns",
3243 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_NS,
3244 		NULL, HFILL }},
3245 
3246 		{ &hf_mysql_cap_compress,
3247 		{ "Can use compression protocol","mysql.caps.cp",
3248 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_CP,
3249 		NULL, HFILL }},
3250 
3251 		{ &hf_mysql_cap_odbc,
3252 		{ "ODBC Client","mysql.caps.ob",
3253 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_OB,
3254 		NULL, HFILL }},
3255 
3256 		{ &hf_mysql_cap_local_files,
3257 		{ "Can Use LOAD DATA LOCAL","mysql.caps.li",
3258 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_LI,
3259 		NULL, HFILL }},
3260 
3261 		{ &hf_mysql_cap_ignore_space,
3262 		{ "Ignore Spaces before '('","mysql.caps.is",
3263 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_IS,
3264 		NULL, HFILL }},
3265 
3266 		{ &hf_mysql_cap_change_user,
3267 		{ "Speaks 4.1 protocol (new flag)","mysql.caps.cu",
3268 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_CU,
3269 		NULL, HFILL }},
3270 
3271 		{ &hf_mysql_cap_interactive,
3272 		{ "Interactive Client","mysql.caps.ia",
3273 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_IA,
3274 		NULL, HFILL }},
3275 
3276 		{ &hf_mysql_cap_ssl,
3277 		{ "Switch to SSL after handshake","mysql.caps.sl",
3278 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_SL,
3279 		NULL, HFILL }},
3280 
3281 		{ &hf_mysql_cap_ignore_sigpipe,
3282 		{ "Ignore sigpipes","mysql.caps.ii",
3283 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_II,
3284 		NULL, HFILL }},
3285 
3286 		{ &hf_mysql_cap_transactions,
3287 		{ "Knows about transactions","mysql.caps.ta",
3288 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_TA,
3289 		NULL, HFILL }},
3290 
3291 		{ &hf_mysql_cap_reserved,
3292 		{ "Speaks 4.1 protocol (old flag)","mysql.caps.rs",
3293 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_RS,
3294 		NULL, HFILL }},
3295 
3296 		{ &hf_mysql_cap_secure_connect,
3297 		{ "Can do 4.1 authentication","mysql.caps.sc",
3298 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_SC,
3299 		NULL, HFILL }},
3300 
3301 		{ &hf_mysql_extcaps_server,
3302 		{ "Extended Server Capabilities", "mysql.extcaps.server",
3303 		FT_UINT16, BASE_HEX, NULL, 0x0,
3304 		"MySQL Extended Capabilities", HFILL }},
3305 
3306 		{ &hf_mysql_extcaps_client,
3307 		{ "Extended Client Capabilities", "mysql.extcaps.client",
3308 		FT_UINT16, BASE_HEX, NULL, 0x0,
3309 		"MySQL Extended Capabilities", HFILL }},
3310 
3311 		{ &hf_mysql_cap_multi_statements,
3312 		{ "Multiple statements","mysql.caps.ms",
3313 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_MS,
3314 		NULL, HFILL }},
3315 
3316 		{ &hf_mysql_cap_multi_results,
3317 		{ "Multiple results","mysql.caps.mr",
3318 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_MR,
3319 		NULL, HFILL }},
3320 
3321 		{ &hf_mysql_cap_ps_multi_results,
3322 		{ "PS Multiple results","mysql.caps.pm",
3323 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_PM,
3324 		NULL, HFILL }},
3325 
3326 		{ &hf_mysql_cap_plugin_auth,
3327 		{ "Plugin Auth","mysql.caps.pa",
3328 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_PA,
3329 		NULL, HFILL }},
3330 
3331 		{ &hf_mysql_cap_connect_attrs,
3332 		{ "Connect attrs","mysql.caps.ca",
3333 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_CA,
3334 		NULL, HFILL }},
3335 
3336 		{ &hf_mysql_cap_plugin_auth_lenenc_client_data,
3337 		{ "Plugin Auth LENENC Client Data","mysql.caps.pm",
3338 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_AL,
3339 		NULL, HFILL }},
3340 
3341 		{ &hf_mysql_cap_client_can_handle_expired_passwords,
3342 		{ "Client can handle expired passwords","mysql.caps.ep",
3343 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_EP,
3344 		NULL, HFILL }},
3345 
3346 		{ &hf_mysql_cap_session_track,
3347 		{ "Session variable tracking","mysql.caps.session_track",
3348 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_ST,
3349 		NULL, HFILL }},
3350 
3351 		{ &hf_mysql_cap_deprecate_eof,
3352 		{ "Deprecate EOF","mysql.caps.deprecate_eof",
3353 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_DE,
3354 		NULL, HFILL }},
3355 
3356 		{ &hf_mysql_cap_unused,
3357 		{ "Unused","mysql.caps.unused",
3358 		FT_UINT16, BASE_HEX, NULL, MYSQL_CAPS_UNUSED,
3359 		NULL, HFILL }},
3360 
3361 		{ &hf_mysql_login_request,
3362 		{ "Login Request", "mysql.login_request",
3363 		FT_NONE, BASE_NONE, NULL, 0x0,
3364 		NULL, HFILL }},
3365 
3366 		{ &hf_mysql_max_packet,
3367 		{ "MAX Packet", "mysql.max_packet",
3368 		FT_UINT32, BASE_DEC, NULL, 0x0,
3369 		"MySQL Max packet", HFILL }},
3370 
3371 		{ &hf_mysql_charset,
3372 		{ "Charset", "mysql.charset",
3373 		FT_UINT8, BASE_DEC|BASE_EXT_STRING, &mysql_collation_vals_ext, 0x0,
3374 		"MySQL Charset", HFILL }},
3375 
3376 		{ &hf_mariadb_charset,
3377 		{ "Charset", "mariadb.charset",
3378 		FT_UINT8, BASE_DEC|BASE_EXT_STRING, &mariadb_collation_vals_ext, 0x0,
3379 		"MySQL Charset", HFILL }},
3380 
3381 		{ &hf_mysql_table_name,
3382 		{ "Table Name", "mysql.table_name",
3383 		FT_STRINGZ, BASE_NONE, NULL, 0x0,
3384 		NULL, HFILL }},
3385 
3386 		{ &hf_mysql_user,
3387 		{ "Username", "mysql.user",
3388 		FT_STRINGZ, BASE_NONE, NULL, 0x0,
3389 		"Login Username", HFILL }},
3390 
3391 		{ &hf_mysql_schema,
3392 		{ "Schema", "mysql.schema",
3393 		FT_STRING, BASE_NONE, NULL, 0x0,
3394 		"Login Schema", HFILL }},
3395 
3396 		{ &hf_mysql_client_auth_plugin,
3397 		{ "Client Auth Plugin", "mysql.client_auth_plugin",
3398 		FT_STRING, BASE_NONE, NULL, 0x0,
3399 		NULL, HFILL }},
3400 
3401 		{ &hf_mysql_connattrs,
3402 		{ "Connection Attributes", "mysql.connattrs",
3403 		FT_NONE, BASE_NONE, NULL, 0x0,
3404 		NULL, HFILL }},
3405 
3406 		{ &hf_mysql_connattrs_length,
3407 		{ "Connection Attributes length", "mysql.connattrs.length",
3408 		  FT_UINT64, BASE_DEC, NULL, 0x0,
3409 		  NULL, HFILL }},
3410 
3411 		{ &hf_mysql_connattrs_attr,
3412 		{ "Connection Attribute", "mysql.connattrs.attr",
3413 		  FT_NONE, BASE_NONE, NULL, 0x0,
3414 		  NULL, HFILL }},
3415 
3416 		{ &hf_mysql_connattrs_name_length,
3417 		{ "Connection Attribute Name Length", "mysql.connattrs.name.length",
3418 		  FT_UINT64, BASE_DEC, NULL, 0x0,
3419 		  NULL, HFILL }},
3420 
3421 		{ &hf_mysql_connattrs_name,
3422 		{ "Connection Attribute Name", "mysql.connattrs.name",
3423 		  FT_STRINGZ, BASE_NONE, NULL, 0x0,
3424 		  NULL, HFILL }},
3425 
3426 		{ &hf_mysql_connattrs_value_length,
3427 		{ "Connection Attribute Name Length", "mysql.connattrs.name.length",
3428 		  FT_UINT64, BASE_DEC, NULL, 0x0,
3429 		  NULL, HFILL }},
3430 
3431 		{ &hf_mysql_connattrs_value,
3432 		{ "Connection Attribute Value", "mysql.connattrs.value",
3433 		  FT_STRINGZ, BASE_NONE, NULL, 0x0,
3434 		  NULL, HFILL }},
3435 
3436 		{ &hf_mysql_salt,
3437 		{ "Salt", "mysql.salt",
3438 		FT_STRINGZ, BASE_NONE, NULL, 0x0,
3439 		NULL, HFILL }},
3440 
3441 		{ &hf_mysql_salt2,
3442 		{ "Salt", "mysql.salt2",
3443 		FT_STRINGZ, BASE_NONE, NULL, 0x0,
3444 		NULL, HFILL }},
3445 
3446 		{ &hf_mysql_auth_plugin_length,
3447 		{ "Authentication Plugin Length", "mysql.auth_plugin.length",
3448 		FT_UINT8, BASE_DEC, NULL, 0x0,
3449 		NULL, HFILL }},
3450 
3451 		{ &hf_mysql_auth_plugin,
3452 		{ "Authentication Plugin", "mysql.auth_plugin",
3453 		FT_STRINGZ, BASE_NONE, NULL, 0x0,
3454 		NULL, HFILL }},
3455 
3456 		{ &hf_mysql_thread_id,
3457 		{ "Thread ID", "mysql.thread_id",
3458 		FT_UINT32, BASE_DEC, NULL, 0x0,
3459 		"MySQL Thread ID", HFILL }},
3460 
3461 		{ &hf_mysql_server_language,
3462 		{ "Server Language", "mysql.server_language",
3463 		FT_UINT8, BASE_DEC|BASE_EXT_STRING, &mysql_collation_vals_ext, 0x0,
3464 		"MySQL Charset", HFILL }},
3465 
3466 		{ &hf_mariadb_server_language,
3467 		{ "Server Language", "mariadb.server_language",
3468 		FT_UINT8, BASE_DEC|BASE_EXT_STRING, &mariadb_collation_vals_ext, 0x0,
3469 		"MySQL Charset", HFILL }},
3470 
3471 		{ &hf_mysql_server_status,
3472 		{ "Server Status", "mysql.server_status",
3473 		FT_UINT16, BASE_HEX, NULL, 0x0,
3474 		"MySQL Status", HFILL }},
3475 
3476 		{ &hf_mysql_stat_it,
3477 		{ "In transaction", "mysql.stat.it",
3478 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_IT,
3479 		NULL, HFILL }},
3480 
3481 		{ &hf_mysql_stat_ac,
3482 		{ "AUTO_COMMIT", "mysql.stat.ac",
3483 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_AC,
3484 		NULL, HFILL }},
3485 
3486 		{ &hf_mysql_stat_mr,
3487 		{ "More results", "mysql.stat.mr",
3488 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_MR,
3489 		NULL, HFILL }},
3490 
3491 		{ &hf_mysql_stat_mu,
3492 		{ "Multi query / Unused", "mysql.stat.mu",
3493 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_MU,
3494 		"Multi query / Unused with MySQL >= 5.6", HFILL }},
3495 
3496 		{ &hf_mysql_stat_bi,
3497 		{ "Bad index used", "mysql.stat.bi",
3498 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_BI,
3499 		NULL, HFILL }},
3500 
3501 		{ &hf_mysql_stat_ni,
3502 		{ "No index used", "mysql.stat.ni",
3503 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_NI,
3504 		NULL, HFILL }},
3505 
3506 		{ &hf_mysql_stat_cr,
3507 		{ "Cursor exists", "mysql.stat.cr",
3508 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_CR,
3509 		NULL, HFILL }},
3510 
3511 		{ &hf_mysql_stat_lr,
3512 		{ "Last row sent", "mysql.stat.lr",
3513 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_LR,
3514 		NULL, HFILL }},
3515 
3516 		{ &hf_mysql_stat_dr,
3517 		{ "Database dropped", "mysql.stat.dr",
3518 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_DR,
3519 		NULL, HFILL }},
3520 
3521 		{ &hf_mysql_stat_bs,
3522 		{ "No backslash escapes", "mysql.stat.bs",
3523 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_BS,
3524 		NULL, HFILL }},
3525 
3526 		{ &hf_mysql_stat_mc,
3527 		{ "Metadata changed", "mysql.stat.mc",
3528 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_MC,
3529 		NULL, HFILL }},
3530 
3531 		{ &hf_mysql_stat_session_state_changed,
3532 		{ "Session state changed", "mysql.stat.session_state_changed",
3533 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_SESSION_STATE_CHANGED,
3534 		NULL, HFILL }},
3535 
3536 		{ &hf_mysql_stat_query_was_slow,
3537 		{ "Query was slow", "mysql.stat.query_was_slow",
3538 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_QUERY_WAS_SLOW,
3539 		NULL, HFILL }},
3540 
3541 		{ &hf_mysql_stat_ps_out_params,
3542 		{ "PS Out Params", "mysql.stat.ps_out_params",
3543 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_PS_OUT_PARAMS,
3544 		NULL, HFILL }},
3545 
3546 		{ &hf_mysql_stat_trans_readonly,
3547 		{ "In Trans Readonly", "mysql.stat.trans_readonly",
3548 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_TRANS_READONLY,
3549 		NULL, HFILL }},
3550 
3551 		{ &hf_mysql_refresh,
3552 		{ "Refresh Option", "mysql.refresh",
3553 		FT_UINT8, BASE_HEX, NULL, 0x0,
3554 		NULL, HFILL }},
3555 
3556 		{ &hf_mysql_rfsh_grants,
3557 		{ "reload permissions", "mysql.rfsh.grants",
3558 		FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_GRANT,
3559 		NULL, HFILL }},
3560 
3561 		{ &hf_mysql_rfsh_log,
3562 		{ "flush logfiles", "mysql.rfsh.log",
3563 		FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_LOG,
3564 		NULL, HFILL }},
3565 
3566 		{ &hf_mysql_rfsh_tables,
3567 		{ "flush tables", "mysql.rfsh.tables",
3568 		FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_TABLES,
3569 		NULL, HFILL }},
3570 
3571 		{ &hf_mysql_rfsh_hosts,
3572 		{ "flush hosts", "mysql.rfsh.hosts",
3573 		FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_HOSTS,
3574 		NULL, HFILL }},
3575 
3576 		{ &hf_mysql_rfsh_status,
3577 		{ "reset statistics", "mysql.rfsh.status",
3578 		FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_STATUS,
3579 		NULL, HFILL }},
3580 
3581 		{ &hf_mysql_rfsh_threads,
3582 		{ "empty thread cache", "mysql.rfsh.threads",
3583 		FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_THREADS,
3584 		NULL, HFILL }},
3585 
3586 		{ &hf_mysql_rfsh_slave,
3587 		{ "flush slave status", "mysql.rfsh.slave",
3588 		FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_SLAVE,
3589 		NULL, HFILL }},
3590 
3591 		{ &hf_mysql_rfsh_master,
3592 		{ "flush master status", "mysql.rfsh.master",
3593 		FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_MASTER,
3594 		NULL, HFILL }},
3595 
3596 		{ &hf_mysql_unused,
3597 		{ "Unused", "mysql.unused",
3598 		FT_BYTES, BASE_NONE, NULL, 0x0,
3599 		NULL, HFILL }},
3600 
3601 		{ &hf_mysql_passwd,
3602 		{ "Password", "mysql.passwd",
3603 		FT_BYTES, BASE_NONE, NULL, 0x0,
3604 		NULL, HFILL }},
3605 
3606 		{ &hf_mysql_payload,
3607 		{ "Payload", "mysql.payload",
3608 		FT_BYTES, BASE_NONE, NULL, 0x0,
3609 		"Additional Payload", HFILL }},
3610 
3611 		{ &hf_mysql_affected_rows,
3612 		{ "Affected Rows", "mysql.affected_rows",
3613 		FT_UINT64, BASE_DEC, NULL, 0x0,
3614 		NULL, HFILL }},
3615 
3616 		{ &hf_mysql_insert_id,
3617 		{ "Last INSERT ID", "mysql.insert_id",
3618 		FT_UINT64, BASE_DEC, NULL, 0x0,
3619 		NULL, HFILL }},
3620 
3621 		{ &hf_mysql_num_warn,
3622 		{ "Warnings", "mysql.warnings",
3623 		FT_UINT16, BASE_DEC, NULL, 0x0,
3624 		NULL, HFILL }},
3625 
3626 		{ &hf_mysql_thd_id,
3627 		{ "Thread ID", "mysql.thd_id",
3628 		FT_UINT32, BASE_DEC, NULL, 0x0,
3629 		NULL, HFILL }},
3630 
3631 		{ &hf_mysql_stmt_id,
3632 		{ "Statement ID", "mysql.stmt_id",
3633 		FT_UINT32, BASE_DEC, NULL, 0x0,
3634 		NULL, HFILL }},
3635 
3636 		{ &hf_mysql_query,
3637 		{ "Statement", "mysql.query",
3638 		FT_STRING, BASE_NONE, NULL, 0x0,
3639 		NULL, HFILL }},
3640 
3641 		{ &hf_mysql_shutdown,
3642 		{ "Shutdown Level", "mysql.shutdown",
3643 		FT_UINT8, BASE_DEC, VALS(mysql_shutdown_vals), 0x0,
3644 		NULL, HFILL }},
3645 
3646 		{ &hf_mysql_option,
3647 		{ "Option", "mysql.option",
3648 		FT_UINT16, BASE_DEC, VALS(mysql_option_vals), 0x0,
3649 		NULL, HFILL }},
3650 
3651 		{ &hf_mysql_param,
3652 		{ "Parameter", "mysql.param",
3653 		FT_UINT16, BASE_DEC, NULL, 0x0,
3654 		NULL, HFILL }},
3655 
3656 		{ &hf_mysql_num_params,
3657 		{ "Number of parameter", "mysql.num_params",
3658 		FT_UINT16, BASE_DEC, NULL, 0x0,
3659 		NULL, HFILL }},
3660 
3661 		{ &hf_mysql_num_rows,
3662 		{ "Rows to fetch", "mysql.num_rows",
3663 		FT_UINT32, BASE_DEC, NULL, 0x0,
3664 		NULL, HFILL }},
3665 
3666 		{ &hf_mysql_exec_flags4,
3667 		{ "Flags (unused)", "mysql.exec_flags",
3668 		FT_UINT8, BASE_DEC, NULL, 0x0,
3669 		NULL, HFILL }},
3670 
3671 		{ &hf_mysql_exec_flags5,
3672 		{ "Flags", "mysql.exec_flags",
3673 		FT_UINT8, BASE_DEC, VALS(mysql_exec_flags_vals), 0x0,
3674 		NULL, HFILL }},
3675 
3676 		{ &hf_mysql_new_parameter_bound_flag,
3677 		{ "New parameter bound flag", "mysql.new_parameter_bound_flag",
3678 		FT_UINT8, BASE_DEC, VALS(mysql_new_parameter_bound_flag_vals), 0x0,
3679 		NULL, HFILL }},
3680 
3681 		{ &hf_mysql_exec_iter,
3682 		{ "Iterations (unused)", "mysql.exec_iter",
3683 		FT_UINT32, BASE_DEC, NULL, 0x0,
3684 		NULL, HFILL }},
3685 
3686 		{ &hf_mysql_binlog_position,
3687 		{ "Binlog Position", "mysql.binlog.position",
3688 		FT_UINT32, BASE_DEC, NULL, 0x0,
3689 		"Position to start at", HFILL }},
3690 
3691 		{ &hf_mysql_binlog_flags,
3692 		{ "Binlog Flags", "mysql.binlog.flags",
3693 		FT_UINT16, BASE_HEX, NULL, 0x0,
3694 		"(currently not used; always 0)", HFILL }},
3695 
3696 		{ &hf_mysql_binlog_server_id,
3697 		{ "Binlog server id", "mysql.binlog.server_id",
3698 		FT_UINT32, BASE_HEX, NULL, 0x0,
3699 		"server_id of the slave", HFILL }},
3700 
3701 		{ &hf_mysql_binlog_file_name,
3702 		{ "Binlog file name", "mysql.binlog.file_name",
3703 		FT_STRINGZ, BASE_NONE, NULL, 0x0,
3704 		NULL, HFILL }},
3705 
3706 		{ &hf_mysql_eof,
3707 		{ "EOF marker", "mysql.eof",
3708 		FT_UINT8, BASE_DEC, NULL, 0x0,
3709 		NULL, HFILL }},
3710 
3711 		{ &hf_mysql_num_fields,
3712 		{ "Number of fields", "mysql.num_fields",
3713 		FT_UINT64, BASE_DEC, NULL, 0x0,
3714 		NULL, HFILL }},
3715 
3716 		{ &hf_mysql_extra,
3717 		{ "Extra data", "mysql.extra",
3718 		FT_UINT64, BASE_DEC, NULL, 0x0,
3719 		NULL, HFILL }},
3720 
3721 		{ &hf_mysql_fld_catalog,
3722 		{ "Catalog", "mysql.field.catalog",
3723 		FT_STRING, BASE_NONE, NULL, 0x0,
3724 		"Field: catalog", HFILL }},
3725 
3726 		{ &hf_mysql_fld_db,
3727 		{ "Database", "mysql.field.db",
3728 		FT_STRING, BASE_NONE, NULL, 0x0,
3729 		"Field: database", HFILL }},
3730 
3731 		{ &hf_mysql_fld_table,
3732 		{ "Table", "mysql.field.table",
3733 		FT_STRING, BASE_NONE, NULL, 0x0,
3734 		"Field: table", HFILL }},
3735 
3736 		{ &hf_mysql_fld_org_table,
3737 		{ "Original table", "mysql.field.org_table",
3738 		FT_STRING, BASE_NONE, NULL, 0x0,
3739 		"Field: original table", HFILL }},
3740 
3741 		{ &hf_mysql_fld_name,
3742 		{ "Name", "mysql.field.name",
3743 		FT_STRING, BASE_NONE, NULL, 0x0,
3744 		"Field: name", HFILL }},
3745 
3746 		{ &hf_mysql_fld_org_name,
3747 		{ "Original name", "mysql.field.org_name",
3748 		FT_STRING, BASE_NONE, NULL, 0x0,
3749 		"Field: original name", HFILL }},
3750 
3751 		{ &hf_mysql_fld_charsetnr,
3752 		{ "Charset number", "mysql.field.charsetnr",
3753 		FT_UINT16, BASE_DEC|BASE_EXT_STRING, &mysql_collation_vals_ext, 0x0,
3754 		"Field: charset number", HFILL }},
3755 
3756 		//{ &hf_mariadb_fld_charsetnr,
3757 		//{ "Charset number", "mariadb.field.charsetnr",
3758 		//FT_UINT16, BASE_DEC|BASE_EXT_STRING, &mariadb_collation_vals_ext, 0x0,
3759 		//"Field: charset number", HFILL }},
3760 
3761 		{ &hf_mysql_fld_length,
3762 		{ "Length", "mysql.field.length",
3763 		FT_UINT32, BASE_DEC, NULL, 0x0,
3764 		"Field: length", HFILL }},
3765 
3766 		{ &hf_mysql_fld_type,
3767 		{ "Type", "mysql.field.type",
3768 		FT_UINT8, BASE_DEC, VALS(type_constants), 0x0,
3769 		"Field: type", HFILL }},
3770 
3771 		{ &hf_mysql_fld_flags,
3772 		{ "Flags", "mysql.field.flags",
3773 		FT_UINT16, BASE_HEX, NULL, 0x0,
3774 		"Field: flags", HFILL }},
3775 
3776 		{ &hf_mysql_fld_not_null,
3777 		{ "Not null", "mysql.field.flags.not_null",
3778 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_NOT_NULL_FLAG,
3779 		"Field: flag not null", HFILL }},
3780 
3781 		{ &hf_mysql_fld_primary_key,
3782 		{ "Primary key", "mysql.field.flags.primary_key",
3783 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_PRI_KEY_FLAG,
3784 		"Field: flag primary key", HFILL }},
3785 
3786 		{ &hf_mysql_fld_unique_key,
3787 		{ "Unique key", "mysql.field.flags.unique_key",
3788 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_UNIQUE_KEY_FLAG,
3789 		"Field: flag unique key", HFILL }},
3790 
3791 		{ &hf_mysql_fld_multiple_key,
3792 		{ "Multiple key", "mysql.field.flags.multiple_key",
3793 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_MULTIPLE_KEY_FLAG,
3794 		"Field: flag multiple key", HFILL }},
3795 
3796 		{ &hf_mysql_fld_blob,
3797 		{ "Blob", "mysql.field.flags.blob",
3798 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_BLOB_FLAG,
3799 		"Field: flag blob", HFILL }},
3800 
3801 		{ &hf_mysql_fld_unsigned,
3802 		{ "Unsigned", "mysql.field.flags.unsigned",
3803 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_UNSIGNED_FLAG,
3804 		"Field: flag unsigned", HFILL }},
3805 
3806 		{ &hf_mysql_fld_zero_fill,
3807 		{ "Zero fill", "mysql.field.flags.zero_fill",
3808 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_ZEROFILL_FLAG,
3809 		"Field: flag zero fill", HFILL }},
3810 
3811 		{ &hf_mysql_fld_binary,
3812 		{ "Binary", "mysql.field.flags.binary",
3813 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_BINARY_FLAG,
3814 		"Field: flag binary", HFILL }},
3815 
3816 		{ &hf_mysql_fld_enum,
3817 		{ "Enum", "mysql.field.flags.enum",
3818 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_ENUM_FLAG,
3819 		"Field: flag enum", HFILL }},
3820 
3821 		{ &hf_mysql_fld_auto_increment,
3822 		{ "Auto increment", "mysql.field.flags.auto_increment",
3823 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_AUTO_INCREMENT_FLAG,
3824 		"Field: flag auto increment", HFILL }},
3825 
3826 		{ &hf_mysql_fld_timestamp,
3827 		{ "Timestamp", "mysql.field.flags.timestamp",
3828 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_TIMESTAMP_FLAG,
3829 		"Field: flag timestamp", HFILL }},
3830 
3831 		{ &hf_mysql_fld_set,
3832 		{ "Set", "mysql.field.flags.set",
3833 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_SET_FLAG,
3834 		"Field: flag set", HFILL }},
3835 
3836 		{ &hf_mysql_fld_decimals,
3837 		{ "Decimals", "mysql.field.decimals",
3838 		FT_UINT8, BASE_DEC, NULL, 0x0,
3839 		"Field: decimals", HFILL }},
3840 
3841 		{ &hf_mysql_fld_default,
3842 		{ "Default", "mysql.field.default",
3843 		FT_STRING, BASE_NONE, NULL, 0x0,
3844 		"Field: default", HFILL }},
3845 
3846 		{ &hf_mysql_row_text,
3847 		{ "text", "mysql.row.text",
3848 		FT_STRING, BASE_NONE, NULL, 0x0,
3849 		"Field: row packet text", HFILL }},
3850 
3851 		{ &hf_mysql_exec_param,
3852 		{ "Parameter", "mysql.exec_param",
3853 		FT_NONE, BASE_NONE, NULL, 0x0,
3854 		NULL, HFILL }},
3855 
3856 		{ &hf_mysql_exec_unsigned,
3857 		{ "Unsigned", "mysql.exec.unsigned",
3858 		FT_UINT8, BASE_DEC, NULL, 0x0,
3859 		NULL, HFILL }},
3860 
3861 		{ &hf_mysql_exec_field_longlong,
3862 		{ "Value", "mysql.exec.field.longlong",
3863 		FT_INT64, BASE_DEC, NULL, 0x0,
3864 		NULL, HFILL }},
3865 
3866 		{ &hf_mysql_exec_field_string,
3867 		{ "Value", "mysql.exec.field.string",
3868 		FT_UINT_STRING, BASE_NONE, NULL, 0x0,
3869 		NULL, HFILL }},
3870 
3871 		{ &hf_mysql_exec_field_double,
3872 		{ "Value", "mysql.exec.field.double",
3873 		FT_DOUBLE, BASE_NONE, NULL, 0x0,
3874 		NULL, HFILL }},
3875 
3876 		{ &hf_mysql_exec_field_datetime_length,
3877 		{ "Length", "mysql.exec.field.datetime.length",
3878 		FT_INT8, BASE_DEC, NULL, 0x0,
3879 		NULL, HFILL }},
3880 
3881 		{ &hf_mysql_exec_field_year,
3882 		{ "Year", "mysql.exec.field.year",
3883 		FT_INT16, BASE_DEC, NULL, 0x0,
3884 		NULL, HFILL }},
3885 
3886 		{ &hf_mysql_exec_field_month,
3887 		{ "Month", "mysql.exec.field.month",
3888 		FT_INT8, BASE_DEC, NULL, 0x0,
3889 		NULL, HFILL }},
3890 
3891 		{ &hf_mysql_exec_field_day,
3892 		{ "Day", "mysql.exec.field.day",
3893 		FT_INT8, BASE_DEC, NULL, 0x0,
3894 		NULL, HFILL }},
3895 
3896 		{ &hf_mysql_exec_field_hour,
3897 		{ "Hour", "mysql.exec.field.hour",
3898 		FT_INT8, BASE_DEC, NULL, 0x0,
3899 		NULL, HFILL }},
3900 
3901 		{ &hf_mysql_exec_field_minute,
3902 		{ "Minute", "mysql.exec.field.minute",
3903 		FT_INT8, BASE_DEC, NULL, 0x0,
3904 		NULL, HFILL }},
3905 
3906 		{ &hf_mysql_exec_field_second,
3907 		{ "Second", "mysql.exec.field.second",
3908 		FT_INT8, BASE_DEC, NULL, 0x0,
3909 		NULL, HFILL }},
3910 
3911 		{ &hf_mysql_exec_field_second_b,
3912 		{ "Billionth of a second", "mysql.exec.field.secondb",
3913 		FT_INT32, BASE_DEC, NULL, 0x0,
3914 		NULL, HFILL }},
3915 
3916 		{ &hf_mysql_exec_field_long,
3917 		{ "Value", "mysql.exec.field.long",
3918 		FT_INT32, BASE_DEC, NULL, 0x0,
3919 		NULL, HFILL }},
3920 
3921 		{ &hf_mysql_exec_field_tiny,
3922 		{ "Value", "mysql.exec.field.tiny",
3923 		FT_INT8, BASE_DEC, NULL, 0x0,
3924 		NULL, HFILL }},
3925 
3926 		{ &hf_mysql_exec_field_short,
3927 		{ "Value", "mysql.exec.field.short",
3928 		FT_INT16, BASE_DEC, NULL, 0x0,
3929 		NULL, HFILL }},
3930 
3931 		{ &hf_mysql_exec_field_float,
3932 		{ "Value", "mysql.exec.field.float",
3933 		FT_FLOAT, BASE_NONE, NULL, 0x0,
3934 		NULL, HFILL }},
3935 
3936 		{ &hf_mysql_exec_field_time_length,
3937 		{ "Length", "mysql.exec.field.time.length",
3938 		FT_INT8, BASE_DEC, NULL, 0x0,
3939 		NULL, HFILL }},
3940 
3941 		{ &hf_mysql_exec_field_time_sign,
3942 		{ "Flags", "mysql.exec.field.time.sign",
3943 		FT_UINT8, BASE_DEC, VALS(mysql_exec_time_sign_vals), 0x0,
3944 		NULL, HFILL }},
3945 
3946 		{ &hf_mysql_exec_field_time_days,
3947 		{ "Days", "mysql.exec.field.time.days",
3948 		FT_INT32, BASE_DEC, NULL, 0x0,
3949 		NULL, HFILL }},
3950 
3951 		{ &hf_mysql_auth_switch_request_status,
3952 		{ "Status", "mysql.auth_switch_request.status",
3953 		FT_UINT8, BASE_HEX, NULL, 0x0,
3954 		NULL, HFILL }},
3955 
3956 		{ &hf_mysql_auth_switch_request_name,
3957 		{ "Auth Method Name", "mysql.auth_switch_request.name",
3958 		FT_STRING, BASE_NONE, NULL, 0x0,
3959 		NULL, HFILL }},
3960 
3961 		{ &hf_mysql_auth_switch_request_data,
3962 		{ "Auth Method Data", "mysql.auth_switch_request.data",
3963 		FT_BYTES, BASE_NONE, NULL, 0x0,
3964 		NULL, HFILL }},
3965 
3966 		{ &hf_mysql_auth_switch_response_data,
3967 		{ "Auth Method Data", "mysql.auth_switch_response.data",
3968 		FT_BYTES, BASE_NONE, NULL, 0x0,
3969 		NULL, HFILL }},
3970 
3971 		{ &hf_mysql_compressed_packet_length,
3972 		{ "Compressed Packet Length", "mysql.compressed_packet_length",
3973 		FT_UINT24, BASE_DEC, NULL,  0x0,
3974 		NULL, HFILL }},
3975 
3976 		{ &hf_mysql_compressed_packet_number,
3977 		{ "Compressed Packet Number", "mysql.compressed_packet_number",
3978 		FT_UINT24, BASE_DEC, NULL,  0x0,
3979 		NULL, HFILL }},
3980 
3981 		{ &hf_mysql_compressed_packet_length_uncompressed,
3982 		{ "Uncompressed Packet Length", "mysql.compressed_packet_length_uncompressed",
3983 		FT_UINT24, BASE_DEC, NULL,  0x0,
3984 		NULL, HFILL }},
3985 
3986 		{ &hf_mariadb_cap_progress,
3987 		{ "Progress indication", "mariadb.caps.pr",
3988 		FT_BOOLEAN, 32, TFS(&tfs_set_notset), MARIADB_CAPS_PR,
3989 		NULL, HFILL }},
3990 
3991 		{ &hf_mariadb_cap_commulti,
3992 		{ "Multi commands", "mariadb.caps.cm",
3993 		FT_BOOLEAN, 32, TFS(&tfs_set_notset), MARIADB_CAPS_CM,
3994 		NULL, HFILL }},
3995 
3996 		{ &hf_mariadb_cap_bulk,
3997 		{ "Bulk Operations", "mariadb.caps.bo",
3998 		FT_BOOLEAN, 32, TFS(&tfs_set_notset), MARIADB_CAPS_BO,
3999 		NULL, HFILL }},
4000 
4001 		{ &hf_mariadb_cap_extmetadata,
4002 		{ "Extended metadata", "mariadb.caps.em",
4003 		FT_BOOLEAN, 32, TFS(&tfs_set_notset), MARIADB_CAPS_EM,
4004 		NULL, HFILL }},
4005 
4006 		{ &hf_mariadb_extcaps_server,
4007 		{ "MariaDB Extended Server Capabilities", "mariadb.extcaps.server",
4008 		FT_UINT32, BASE_HEX, NULL, 0x0,
4009 		NULL, HFILL }},
4010 
4011 		{ &hf_mariadb_extcaps_client,
4012 		{ "MariaDB Extended Client Capabilities", "mariadb.extcaps.client",
4013 		FT_UINT32, BASE_HEX, NULL, 0x0,
4014 		NULL, HFILL }},
4015 
4016 		{ &hf_mariadb_bulk_flag_autoid,
4017 		{ "Return Generated Autoincrement IDs", "mariadb.bulk.flag.autoid",
4018 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MARIADB_BULK_AUTOID,
4019 		NULL, HFILL }},
4020 
4021 		{ &hf_mariadb_bulk_flag_sendtypes,
4022 		{ "Send Parameter Types", "mariadb.bulk.flag.sendtypes",
4023 		FT_BOOLEAN, 16, TFS(&tfs_set_notset), MARIADB_BULK_SEND_TYPES,
4024 		NULL, HFILL }},
4025 
4026 		{ &hf_mariadb_bulk_caps_flags,
4027 		{ "MariaDB Bulk Capabilities", "mariadb.bulk.flags",
4028 		FT_UINT16, BASE_HEX, NULL, 0x0,
4029 		NULL, HFILL }},
4030 
4031 		{ &hf_mariadb_bulk_paramtypes,
4032 		{ "Bulk Parameter Types", "mariadb.bulk.paramtypesg",
4033 		FT_NONE, BASE_NONE, NULL, 0x0,
4034 		NULL, HFILL }},
4035 
4036 		{ &hf_mariadb_bulk_indicator,
4037 		{ "Indicator", "mariadb.bulk.indicators",
4038 			FT_UINT8, BASE_HEX, VALS(mariadb_bulk_indicator_vals), 0x00,
4039 			NULL, HFILL }},
4040 		{ &hf_mysql_prefix,
4041 		{ "Prefix", "mariadb.prefix",
4042 			FT_UINT8, BASE_DEC, NULL, 0x00,
4043 			NULL, HFILL } },
4044 		{ &hf_mysql_length,
4045 		{ "Length", "mariadb.length",
4046 			FT_UINT64, BASE_DEC, NULL, 0x00,
4047 			NULL, HFILL } }
4048 	};
4049 
4050 	static gint *ett[]=
4051 	{
4052 		&ett_mysql,
4053 		&ett_server_greeting,
4054 		&ett_login_request,
4055 		&ett_caps,
4056 		&ett_extcaps,
4057 		&ett_stat,
4058 		&ett_request,
4059 		&ett_refresh,
4060 		&ett_field_flags,
4061 		&ett_exec_param,
4062 		&ett_bulk_param,
4063 		&ett_session_track,
4064 		&ett_session_track_data,
4065 		&ett_connattrs,
4066 		&ett_connattrs_attr,
4067 		&ett_mysql_field
4068 	};
4069 
4070 	static ei_register_info ei[] = {
4071 		{ &ei_mysql_dissector_incomplete, { "mysql.dissector_incomplete", PI_UNDECODED, PI_WARN, "FIXME - dissector is incomplete", EXPFILL }},
4072 		{ &ei_mysql_streamed_param, { "mysql.streamed_param", PI_SEQUENCE, PI_CHAT, "This parameter was streamed, its value can be found in Send BLOB packets", EXPFILL }},
4073 		{ &ei_mysql_prepare_response_needed, { "mysql.prepare_response_needed", PI_UNDECODED, PI_WARN, "PREPARE Response packet is needed to dissect the payload", EXPFILL }},
4074 		{ &ei_mysql_command, { "mysql.command.invalid", PI_PROTOCOL, PI_WARN, "Unknown/invalid command code", EXPFILL }},
4075 		{ &ei_mysql_eof, { "mysql.eof.wrong_state", PI_PROTOCOL, PI_WARN, "EOF Marker found while connection in wrong state.", EXPFILL }},
4076 		{ &ei_mysql_unknown_response, { "mysql.unknown_response", PI_UNDECODED, PI_WARN, "unknown/invalid response", EXPFILL }},
4077 	};
4078 
4079 	module_t *mysql_module;
4080 	expert_module_t* expert_mysql;
4081 
4082 	proto_mysql = proto_register_protocol("MySQL Protocol", "MySQL", "mysql");
4083 	proto_register_field_array(proto_mysql, hf, array_length(hf));
4084 	proto_register_subtree_array(ett, array_length(ett));
4085 	expert_mysql = expert_register_protocol(proto_mysql);
4086 	expert_register_field_array(expert_mysql, ei, array_length(ei));
4087 
4088 	mysql_module = prefs_register_protocol(proto_mysql, NULL);
4089 	prefs_register_bool_preference(mysql_module, "desegment_buffers",
4090 					"Reassemble MySQL buffers spanning multiple TCP segments",
4091 					"Whether the MySQL dissector should reassemble MySQL buffers spanning multiple TCP segments."
4092 					" To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
4093 					&mysql_desegment);
4094 	prefs_register_bool_preference(mysql_module, "show_sql_query",
4095 					"Show SQL Query string in INFO column",
4096 					"Whether the MySQL dissector should display the SQL query string in the INFO column.",
4097 					&mysql_showquery);
4098 
4099 	mysql_handle = register_dissector("mysql", dissect_mysql, proto_mysql);
4100 }
4101 
4102 /* dissector registration */
proto_reg_handoff_mysql(void)4103 void proto_reg_handoff_mysql(void)
4104 {
4105 	tls_handle = find_dissector("tls");
4106 	dissector_add_uint_with_preference("tcp.port", TCP_PORT_MySQL, mysql_handle);
4107 }
4108 
4109 /*
4110  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
4111  *
4112  * Local variables:
4113  * c-basic-offset: 8
4114  * tab-width: 8
4115  * indent-tabs-mode: t
4116  * End:
4117  *
4118  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
4119  * :indentSize=8:tabSize=8:noTabs=false:
4120  */
4121