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, ¶m_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