2 * Routines for mysql packet dissection
4 * Huagang XIE <huagang@intruvert.com>
6 * MySQL 4.1+ protocol by Axel Schwenke <axel@mysql.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * Copied from packet-tftp.c
14 * SPDX-License-Identifier: GPL-2.0-or-later
17 * the protocol spec at
18 * https://dev.mysql.com/doc/internals/en/client-server-protocol.html
19 * and MySQL source code
22 /* create extra output for conversation tracking */
23 /* #define CTDEBUG 1 */
27 #include <epan/packet.h>
28 #include <epan/prefs.h>
29 #include <epan/expert.h>
30 #include <epan/strutil.h>
31 #include <epan/proto_data.h>
32 #include "packet-tcp.h"
33 #include "packet-tls-utils.h"
35 void proto_register_mysql(void);
36 void proto_reg_handoff_mysql(void);
38 /* port for protocol registration */
39 #define TCP_PORT_MySQL 3306
41 /* client/server capabilities
42 * Source: http://dev.mysql.com/doc/internals/en/capability-flags.html
45 #define MYSQL_CAPS_LP 0x0001 /* CLIENT_LONG_PASSWORD */
46 #define MYSQL_CAPS_FR 0x0002 /* CLIENT_FOUND_ROWS */
47 #define MYSQL_CAPS_LF 0x0004 /* CLIENT_LONG_FLAG */
48 #define MYSQL_CAPS_CD 0x0008 /* CLIENT_CONNECT_WITH_DB */
49 #define MYSQL_CAPS_NS 0x0010 /* CLIENT_NO_SCHEMA */
50 #define MYSQL_CAPS_CP 0x0020 /* CLIENT_COMPRESS */
51 #define MYSQL_CAPS_OB 0x0040 /* CLIENT_ODBC */
52 #define MYSQL_CAPS_LI 0x0080 /* CLIENT_LOCAL_FILES */
53 #define MYSQL_CAPS_IS 0x0100 /* CLIENT_IGNORE_SPACE */
54 #define MYSQL_CAPS_CU 0x0200 /* CLIENT_PROTOCOL_41 */
55 #define MYSQL_CAPS_IA 0x0400 /* CLIENT_INTERACTIVE */
56 #define MYSQL_CAPS_SL 0x0800 /* CLIENT_SSL */
57 #define MYSQL_CAPS_II 0x1000 /* CLIENT_IGNORE_SPACE */
58 #define MYSQL_CAPS_TA 0x2000 /* CLIENT_TRANSACTIONS */
59 #define MYSQL_CAPS_RS 0x4000 /* CLIENT_RESERVED */
60 #define MYSQL_CAPS_SC 0x8000 /* CLIENT_SECURE_CONNECTION */
64 #define MYSQL_FLD_NOT_NULL_FLAG 0x0001
65 #define MYSQL_FLD_PRI_KEY_FLAG 0x0002
66 #define MYSQL_FLD_UNIQUE_KEY_FLAG 0x0004
67 #define MYSQL_FLD_MULTIPLE_KEY_FLAG 0x0008
68 #define MYSQL_FLD_BLOB_FLAG 0x0010
69 #define MYSQL_FLD_UNSIGNED_FLAG 0x0020
70 #define MYSQL_FLD_ZEROFILL_FLAG 0x0040
71 #define MYSQL_FLD_BINARY_FLAG 0x0080
72 #define MYSQL_FLD_ENUM_FLAG 0x0100
73 #define MYSQL_FLD_AUTO_INCREMENT_FLAG 0x0200
74 #define MYSQL_FLD_TIMESTAMP_FLAG 0x0400
75 #define MYSQL_FLD_SET_FLAG 0x0800
77 /* extended capabilities: 4.1+ client only
79 * These are libmysqlclient flags and NOT present
81 * CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30)
82 * CLIENT_REMEMBER_OPTIONS (1UL << 31)
84 #define MYSQL_CAPS_MS 0x0001 /* CLIENT_MULTI_STATMENTS */
85 #define MYSQL_CAPS_MR 0x0002 /* CLIENT_MULTI_RESULTS */
86 #define MYSQL_CAPS_PM 0x0004 /* CLIENT_PS_MULTI_RESULTS */
87 #define MYSQL_CAPS_PA 0x0008 /* CLIENT_PLUGIN_AUTH */
88 #define MYSQL_CAPS_CA 0x0010 /* CLIENT_CONNECT_ATTRS */
89 #define MYSQL_CAPS_AL 0x0020 /* CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA */
90 #define MYSQL_CAPS_EP 0x0040 /* CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS */
91 #define MYSQL_CAPS_ST 0x0080 /* CLIENT_SESSION_TRACK */
92 #define MYSQL_CAPS_DE 0x0100 /* CLIENT_DEPRECATE_EOF */
93 #define MYSQL_CAPS_UNUSED 0xFE00
96 #define MYSQL_STAT_IT 0x0001
97 #define MYSQL_STAT_AC 0x0002
98 #define MYSQL_STAT_MU 0x0004
99 #define MYSQL_STAT_MR 0x0008
100 #define MYSQL_STAT_BI 0x0010
101 #define MYSQL_STAT_NI 0x0020
102 #define MYSQL_STAT_CR 0x0040
103 #define MYSQL_STAT_LR 0x0080
104 #define MYSQL_STAT_DR 0x0100
105 #define MYSQL_STAT_BS 0x0200
106 #define MYSQL_STAT_MC 0x0400
107 #define MYSQL_STAT_QUERY_WAS_SLOW 0x0800
108 #define MYSQL_STAT_PS_OUT_PARAMS 0x1000
109 #define MYSQL_STAT_TRANS_READONLY 0x2000
110 #define MYSQL_STAT_SESSION_STATE_CHANGED 0x4000
112 /* bitfield for MYSQL_REFRESH */
113 #define MYSQL_RFSH_GRANT 1 /* Refresh grant tables */
114 #define MYSQL_RFSH_LOG 2 /* Start on new log file */
115 #define MYSQL_RFSH_TABLES 4 /* close all tables */
116 #define MYSQL_RFSH_HOSTS 8 /* Flush host cache */
117 #define MYSQL_RFSH_STATUS 16 /* Flush status variables */
118 #define MYSQL_RFSH_THREADS 32 /* Flush thread cache */
119 #define MYSQL_RFSH_SLAVE 64 /* Reset master info and restart slave thread */
120 #define MYSQL_RFSH_MASTER 128 /* Remove all bin logs in the index and truncate the index */
122 /* MySQL command codes (enum_server_command in mysql-server.git:include/my_command.h) */
123 #define MYSQL_SLEEP 0 /* not from client */
125 #define MYSQL_INIT_DB 2
126 #define MYSQL_QUERY 3
127 #define MYSQL_FIELD_LIST 4
128 #define MYSQL_CREATE_DB 5
129 #define MYSQL_DROP_DB 6
130 #define MYSQL_REFRESH 7
131 #define MYSQL_SHUTDOWN 8
132 #define MYSQL_STATISTICS 9
133 #define MYSQL_PROCESS_INFO 10
134 #define MYSQL_CONNECT 11 /* not from client */
135 #define MYSQL_PROCESS_KILL 12
136 #define MYSQL_DEBUG 13
137 #define MYSQL_PING 14
138 #define MYSQL_TIME 15 /* not from client */
139 #define MYSQL_DELAY_INSERT 16 /* not from client */
140 #define MYSQL_CHANGE_USER 17
141 #define MYSQL_BINLOG_DUMP 18 /* replication */
142 #define MYSQL_TABLE_DUMP 19 /* replication */
143 #define MYSQL_CONNECT_OUT 20 /* replication */
144 #define MYSQL_REGISTER_SLAVE 21 /* replication */
145 #define MYSQL_STMT_PREPARE 22
146 #define MYSQL_STMT_EXECUTE 23
147 #define MYSQL_STMT_SEND_LONG_DATA 24
148 #define MYSQL_STMT_CLOSE 25
149 #define MYSQL_STMT_RESET 26
150 #define MYSQL_SET_OPTION 27
151 #define MYSQL_STMT_FETCH 28
152 #define MYSQL_DAEMON 29
153 #define MYSQL_BINLOG_DUMP_GTID 30 /* replication */
154 #define MYSQL_RESET_CONNECTION 31
157 /* MySQL cursor types */
159 #define MYSQL_CURSOR_TYPE_NO_CURSOR 0
160 #define MYSQL_CURSOR_TYPE_READ_ONLY 1
161 #define MYSQL_CURSOR_TYPE_FOR_UPDATE 2
162 #define MYSQL_CURSOR_TYPE_SCROLLABLE 4
164 /* MySQL parameter flags -- used internally by the dissector */
166 #define MYSQL_PARAM_FLAG_STREAMED 0x01
168 /* Compression states, internal to the dissector */
169 #define MYSQL_COMPRESS_NONE 0
170 #define MYSQL_COMPRESS_INIT 1
171 #define MYSQL_COMPRESS_ACTIVE 2
173 /* Generic Response Codes */
174 #define MYSQL_RESPONSE_OK 0x00
175 #define MYSQL_RESPONSE_ERR 0xFF
176 #define MYSQL_RESPONSE_EOF 0xFE
178 /* decoding table: command */
179 static const value_string mysql_command_vals[] = {
180 {MYSQL_SLEEP, "SLEEP"},
181 {MYSQL_QUIT, "Quit"},
182 {MYSQL_INIT_DB, "Use Database"},
183 {MYSQL_QUERY, "Query"},
184 {MYSQL_FIELD_LIST, "Show Fields"},
185 {MYSQL_CREATE_DB, "Create Database"},
186 {MYSQL_DROP_DB , "Drop Database"},
187 {MYSQL_REFRESH , "Refresh"},
188 {MYSQL_SHUTDOWN , "Shutdown"},
189 {MYSQL_STATISTICS , "Statistics"},
190 {MYSQL_PROCESS_INFO , "Process List"},
191 {MYSQL_CONNECT , "Connect"},
192 {MYSQL_PROCESS_KILL , "Kill Server Thread"},
193 {MYSQL_DEBUG , "Dump Debuginfo"},
194 {MYSQL_PING , "Ping"},
195 {MYSQL_TIME , "Time"},
196 {MYSQL_DELAY_INSERT , "Insert Delayed"},
197 {MYSQL_CHANGE_USER , "Change User"},
198 {MYSQL_BINLOG_DUMP , "Send Binlog"},
199 {MYSQL_TABLE_DUMP, "Send Table"},
200 {MYSQL_CONNECT_OUT, "Slave Connect"},
201 {MYSQL_REGISTER_SLAVE, "Register Slave"},
202 {MYSQL_STMT_PREPARE, "Prepare Statement"},
203 {MYSQL_STMT_EXECUTE, "Execute Statement"},
204 {MYSQL_STMT_SEND_LONG_DATA, "Send BLOB"},
205 {MYSQL_STMT_CLOSE, "Close Statement"},
206 {MYSQL_STMT_RESET, "Reset Statement"},
207 {MYSQL_SET_OPTION, "Set Option"},
208 {MYSQL_STMT_FETCH, "Fetch Data"},
209 {MYSQL_BINLOG_DUMP_GTID, "Send Binlog GTID"},
212 static value_string_ext mysql_command_vals_ext = VALUE_STRING_EXT_INIT(mysql_command_vals);
214 /* decoding table: exec_flags */
215 static const value_string mysql_exec_flags_vals[] = {
216 {MYSQL_CURSOR_TYPE_NO_CURSOR, "Defaults"},
217 {MYSQL_CURSOR_TYPE_READ_ONLY, "Read-only cursor"},
218 {MYSQL_CURSOR_TYPE_FOR_UPDATE, "Cursor for update"},
219 {MYSQL_CURSOR_TYPE_SCROLLABLE, "Scrollable cursor"},
223 /* decoding table: new_parameter_bound_flag */
224 static const value_string mysql_new_parameter_bound_flag_vals[] = {
225 {0, "Subsequent call"},
226 {1, "First call or rebound"},
230 /* decoding table: exec_time_sign */
231 static const value_string mysql_exec_time_sign_vals[] = {
238 /* charset: pre-4.1 used the term 'charset', later changed to 'collation' */
239 static const value_string mysql_charset_vals[] = {
275 /* collation codes may change over time, recreate with the following SQL
277 SELECT CONCAT(' {', ID, ',"', CHARACTER_SET_NAME, ' COLLATE ', COLLATION_NAME, '"},')
278 FROM INFORMATION_SCHEMA.COLLATIONS
280 INTO OUTFILE '/tmp/mysql-collations';
283 static const value_string mysql_collation_vals[] = {
284 {3, "dec8 COLLATE dec8_swedish_ci"},
285 {4, "cp850 COLLATE cp850_general_ci"},
286 {5, "latin1 COLLATE latin1_german1_ci"},
287 {6, "hp8 COLLATE hp8_english_ci"},
288 {7, "koi8r COLLATE koi8r_general_ci"},
289 {8, "latin1 COLLATE latin1_swedish_ci"},
290 {9, "latin2 COLLATE latin2_general_ci"},
291 {10, "swe7 COLLATE swe7_swedish_ci"},
292 {11, "ascii COLLATE ascii_general_ci"},
293 {14, "cp1251 COLLATE cp1251_bulgarian_ci"},
294 {15, "latin1 COLLATE latin1_danish_ci"},
295 {16, "hebrew COLLATE hebrew_general_ci"},
296 {20, "latin7 COLLATE latin7_estonian_cs"},
297 {21, "latin2 COLLATE latin2_hungarian_ci"},
298 {22, "koi8u COLLATE koi8u_general_ci"},
299 {23, "cp1251 COLLATE cp1251_ukrainian_ci"},
300 {25, "greek COLLATE greek_general_ci"},
301 {26, "cp1250 COLLATE cp1250_general_ci"},
302 {27, "latin2 COLLATE latin2_croatian_ci"},
303 {29, "cp1257 COLLATE cp1257_lithuanian_ci"},
304 {30, "latin5 COLLATE latin5_turkish_ci"},
305 {31, "latin1 COLLATE latin1_german2_ci"},
306 {32, "armscii8 COLLATE armscii8_general_ci"},
307 {33, "utf8 COLLATE utf8_general_ci"},
308 {36, "cp866 COLLATE cp866_general_ci"},
309 {37, "keybcs2 COLLATE keybcs2_general_ci"},
310 {38, "macce COLLATE macce_general_ci"},
311 {39, "macroman COLLATE macroman_general_ci"},
312 {40, "cp852 COLLATE cp852_general_ci"},
313 {41, "latin7 COLLATE latin7_general_ci"},
314 {42, "latin7 COLLATE latin7_general_cs"},
315 {43, "macce COLLATE macce_bin"},
316 {44, "cp1250 COLLATE cp1250_croatian_ci"},
317 {45, "utf8mb4 COLLATE utf8mb4_general_ci"},
318 {46, "utf8mb4 COLLATE utf8mb4_bin"},
319 {47, "latin1 COLLATE latin1_bin"},
320 {48, "latin1 COLLATE latin1_general_ci"},
321 {49, "latin1 COLLATE latin1_general_cs"},
322 {50, "cp1251 COLLATE cp1251_bin"},
323 {51, "cp1251 COLLATE cp1251_general_ci"},
324 {52, "cp1251 COLLATE cp1251_general_cs"},
325 {53, "macroman COLLATE macroman_bin"},
326 {57, "cp1256 COLLATE cp1256_general_ci"},
327 {58, "cp1257 COLLATE cp1257_bin"},
328 {59, "cp1257 COLLATE cp1257_general_ci"},
329 {63, "binary COLLATE binary"},
330 {64, "armscii8 COLLATE armscii8_bin"},
331 {65, "ascii COLLATE ascii_bin"},
332 {66, "cp1250 COLLATE cp1250_bin"},
333 {67, "cp1256 COLLATE cp1256_bin"},
334 {68, "cp866 COLLATE cp866_bin"},
335 {69, "dec8 COLLATE dec8_bin"},
336 {70, "greek COLLATE greek_bin"},
337 {71, "hebrew COLLATE hebrew_bin"},
338 {72, "hp8 COLLATE hp8_bin"},
339 {73, "keybcs2 COLLATE keybcs2_bin"},
340 {74, "koi8r COLLATE koi8r_bin"},
341 {75, "koi8u COLLATE koi8u_bin"},
342 {77, "latin2 COLLATE latin2_bin"},
343 {78, "latin5 COLLATE latin5_bin"},
344 {79, "latin7 COLLATE latin7_bin"},
345 {80, "cp850 COLLATE cp850_bin"},
346 {81, "cp852 COLLATE cp852_bin"},
347 {82, "swe7 COLLATE swe7_bin"},
348 {83, "utf8 COLLATE utf8_bin"},
349 {92, "geostd8 COLLATE geostd8_general_ci"},
350 {93, "geostd8 COLLATE geostd8_bin"},
351 {94, "latin1 COLLATE latin1_spanish_ci"},
352 {99, "cp1250 COLLATE cp1250_polish_ci"},
353 {192, "utf8 COLLATE utf8_unicode_ci"},
354 {193, "utf8 COLLATE utf8_icelandic_ci"},
355 {194, "utf8 COLLATE utf8_latvian_ci"},
356 {195, "utf8 COLLATE utf8_romanian_ci"},
357 {196, "utf8 COLLATE utf8_slovenian_ci"},
358 {197, "utf8 COLLATE utf8_polish_ci"},
359 {198, "utf8 COLLATE utf8_estonian_ci"},
360 {199, "utf8 COLLATE utf8_spanish_ci"},
361 {200, "utf8 COLLATE utf8_swedish_ci"},
362 {201, "utf8 COLLATE utf8_turkish_ci"},
363 {202, "utf8 COLLATE utf8_czech_ci"},
364 {203, "utf8 COLLATE utf8_danish_ci"},
365 {204, "utf8 COLLATE utf8_lithuanian_ci"},
366 {205, "utf8 COLLATE utf8_slovak_ci"},
367 {206, "utf8 COLLATE utf8_spanish2_ci"},
368 {207, "utf8 COLLATE utf8_roman_ci"},
369 {208, "utf8 COLLATE utf8_persian_ci"},
370 {209, "utf8 COLLATE utf8_esperanto_ci"},
371 {210, "utf8 COLLATE utf8_hungarian_ci"},
372 {211, "utf8 COLLATE utf8_sinhala_ci"},
373 {212, "utf8 COLLATE utf8_german2_ci"},
374 {213, "utf8 COLLATE utf8_croatian_ci"},
375 {214, "utf8 COLLATE utf8_unicode_520_ci"},
376 {215, "utf8 COLLATE utf8_vietnamese_ci"},
377 {223, "utf8 COLLATE utf8_general_mysql500_ci"},
378 {224, "utf8mb4 COLLATE utf8mb4_unicode_ci"},
379 {225, "utf8mb4 COLLATE utf8mb4_icelandic_ci"},
380 {226, "utf8mb4 COLLATE utf8mb4_latvian_ci"},
381 {227, "utf8mb4 COLLATE utf8mb4_romanian_ci"},
382 {228, "utf8mb4 COLLATE utf8mb4_slovenian_ci"},
383 {229, "utf8mb4 COLLATE utf8mb4_polish_ci"},
384 {230, "utf8mb4 COLLATE utf8mb4_estonian_ci"},
385 {231, "utf8mb4 COLLATE utf8mb4_spanish_ci"},
386 {232, "utf8mb4 COLLATE utf8mb4_swedish_ci"},
387 {233, "utf8mb4 COLLATE utf8mb4_turkish_ci"},
388 {234, "utf8mb4 COLLATE utf8mb4_czech_ci"},
389 {235, "utf8mb4 COLLATE utf8mb4_danish_ci"},
390 {236, "utf8mb4 COLLATE utf8mb4_lithuanian_ci"},
391 {237, "utf8mb4 COLLATE utf8mb4_slovak_ci"},
392 {238, "utf8mb4 COLLATE utf8mb4_spanish2_ci"},
393 {239, "utf8mb4 COLLATE utf8mb4_roman_ci"},
394 {240, "utf8mb4 COLLATE utf8mb4_persian_ci"},
395 {241, "utf8mb4 COLLATE utf8mb4_esperanto_ci"},
396 {242, "utf8mb4 COLLATE utf8mb4_hungarian_ci"},
397 {243, "utf8mb4 COLLATE utf8mb4_sinhala_ci"},
398 {244, "utf8mb4 COLLATE utf8mb4_german2_ci"},
399 {245, "utf8mb4 COLLATE utf8mb4_croatian_ci"},
400 {246, "utf8mb4 COLLATE utf8mb4_unicode_520_ci"},
401 {247, "utf8mb4 COLLATE utf8mb4_vietnamese_ci"},
404 static value_string_ext mysql_collation_vals_ext = VALUE_STRING_EXT_INIT(mysql_collation_vals);
407 /* allowed MYSQL_SHUTDOWN levels */
408 static const value_string mysql_shutdown_vals[] = {
410 {1, "wait for connections to finish"},
411 {2, "wait for transactions to finish"},
412 {8, "wait for updates to finish"},
413 {16, "wait flush all buffers"},
414 {17, "wait flush critical buffers"},
415 {254, "kill running queries"},
416 {255, "kill connections"},
421 /* allowed MYSQL_SET_OPTION values */
422 static const value_string mysql_option_vals[] = {
423 {0, "multi statements on"},
424 {1, "multi statements off"},
428 static const value_string mysql_session_track_type_vals[] = {
429 {0, "SESSION_SYSVARS_TRACKER"},
430 {1, "CURRENT_SCHEMA_TRACKER"},
431 {2, "SESSION_STATE_CHANGE_TRACKER"},
435 static const value_string mysql_response_code_vals[] = {
436 { MYSQL_RESPONSE_OK, "OK Packet" },
437 { MYSQL_RESPONSE_ERR, "ERR Packet" },
438 { MYSQL_RESPONSE_EOF, "EOF Packet" },
443 static int proto_mysql = -1;
445 /* dissector configuration */
446 static gboolean mysql_desegment = TRUE;
447 static gboolean mysql_showquery = FALSE;
449 /* expand-the-tree flags */
450 static gint ett_mysql = -1;
451 static gint ett_server_greeting = -1;
452 static gint ett_login_request = -1;
453 static gint ett_caps = -1;
454 static gint ett_extcaps = -1;
455 static gint ett_stat = -1;
456 static gint ett_request = -1;
457 static gint ett_refresh = -1;
458 static gint ett_field_flags = -1;
459 static gint ett_exec_param = -1;
460 static gint ett_session_track = -1;
461 static gint ett_session_track_data = -1;
462 static gint ett_connattrs = -1;
463 static gint ett_connattrs_attr = -1;
465 /* protocol fields */
466 static int hf_mysql_caps_server = -1;
467 static int hf_mysql_caps_client = -1;
468 static int hf_mysql_cap_long_password = -1;
469 static int hf_mysql_cap_found_rows = -1;
470 static int hf_mysql_cap_long_flag = -1;
471 static int hf_mysql_cap_connect_with_db = -1;
472 static int hf_mysql_cap_no_schema = -1;
473 static int hf_mysql_cap_compress = -1;
474 static int hf_mysql_cap_odbc = -1;
475 static int hf_mysql_cap_local_files = -1;
476 static int hf_mysql_cap_ignore_space = -1;
477 static int hf_mysql_cap_change_user = -1;
478 static int hf_mysql_cap_interactive = -1;
479 static int hf_mysql_cap_ssl = -1;
480 static int hf_mysql_cap_ignore_sigpipe = -1;
481 static int hf_mysql_cap_transactions = -1;
482 static int hf_mysql_cap_reserved = -1;
483 static int hf_mysql_cap_secure_connect = -1;
484 static int hf_mysql_extcaps_server = -1;
485 static int hf_mysql_extcaps_client = -1;
486 static int hf_mysql_cap_multi_statements = -1;
487 static int hf_mysql_cap_multi_results = -1;
488 static int hf_mysql_cap_ps_multi_results = -1;
489 static int hf_mysql_cap_plugin_auth = -1;
490 static int hf_mysql_cap_connect_attrs = -1;
491 static int hf_mysql_cap_plugin_auth_lenenc_client_data = -1;
492 static int hf_mysql_cap_client_can_handle_expired_passwords = -1;
493 static int hf_mysql_cap_session_track = -1;
494 static int hf_mysql_cap_deprecate_eof = -1;
495 static int hf_mysql_cap_unused = -1;
496 static int hf_mysql_server_language = -1;
497 static int hf_mysql_server_status = -1;
498 static int hf_mysql_stat_it = -1;
499 static int hf_mysql_stat_ac = -1;
500 static int hf_mysql_stat_mr = -1;
501 static int hf_mysql_stat_mu = -1;
502 static int hf_mysql_stat_bi = -1;
503 static int hf_mysql_stat_ni = -1;
504 static int hf_mysql_stat_cr = -1;
505 static int hf_mysql_stat_lr = -1;
506 static int hf_mysql_stat_dr = -1;
507 static int hf_mysql_stat_bs = -1;
508 static int hf_mysql_stat_mc = -1;
509 static int hf_mysql_stat_session_state_changed = -1;
510 static int hf_mysql_stat_query_was_slow = -1;
511 static int hf_mysql_stat_ps_out_params = -1;
512 static int hf_mysql_stat_trans_readonly = -1;
513 static int hf_mysql_refresh = -1;
514 static int hf_mysql_rfsh_grants = -1;
515 static int hf_mysql_rfsh_log = -1;
516 static int hf_mysql_rfsh_tables = -1;
517 static int hf_mysql_rfsh_hosts = -1;
518 static int hf_mysql_rfsh_status = -1;
519 static int hf_mysql_rfsh_threads = -1;
520 static int hf_mysql_rfsh_slave = -1;
521 static int hf_mysql_rfsh_master = -1;
522 static int hf_mysql_packet_length = -1;
523 static int hf_mysql_packet_number = -1;
524 static int hf_mysql_request = -1;
525 static int hf_mysql_command = -1;
526 static int hf_mysql_response_code = -1;
527 static int hf_mysql_error_code = -1;
528 static int hf_mysql_error_string = -1;
529 static int hf_mysql_sqlstate = -1;
530 static int hf_mysql_message = -1;
531 static int hf_mysql_payload = -1;
532 static int hf_mysql_server_greeting = -1;
533 static int hf_mysql_session_track = -1;
534 static int hf_mysql_session_track_type = -1;
535 static int hf_mysql_session_track_length = -1;
536 static int hf_mysql_session_track_data = -1;
537 static int hf_mysql_session_track_data_length = -1;
538 static int hf_mysql_session_track_sysvar_length = -1;
539 static int hf_mysql_session_track_sysvar_name = -1;
540 static int hf_mysql_session_track_sysvar_value = -1;
541 static int hf_mysql_session_track_schema = -1;
542 static int hf_mysql_session_track_schema_length = -1;
543 static int hf_mysql_session_state_change = -1;
544 static int hf_mysql_protocol = -1;
545 static int hf_mysql_version = -1;
546 static int hf_mysql_login_request = -1;
547 static int hf_mysql_max_packet = -1;
548 static int hf_mysql_user = -1;
549 static int hf_mysql_table_name = -1;
550 static int hf_mysql_schema = -1;
551 static int hf_mysql_client_auth_plugin = -1;
552 static int hf_mysql_connattrs = -1;
553 static int hf_mysql_connattrs_length = -1;
554 static int hf_mysql_connattrs_attr = -1;
555 static int hf_mysql_connattrs_name_length = -1;
556 static int hf_mysql_connattrs_name = -1;
557 static int hf_mysql_connattrs_value_length = -1;
558 static int hf_mysql_connattrs_value = -1;
559 static int hf_mysql_thread_id = -1;
560 static int hf_mysql_salt = -1;
561 static int hf_mysql_salt2 = -1;
562 static int hf_mysql_auth_plugin_length = -1;
563 static int hf_mysql_auth_plugin = -1;
564 static int hf_mysql_charset = -1;
565 static int hf_mysql_passwd = -1;
566 static int hf_mysql_unused = -1;
567 static int hf_mysql_affected_rows = -1;
568 static int hf_mysql_insert_id = -1;
569 static int hf_mysql_num_warn = -1;
570 static int hf_mysql_thd_id = -1;
571 static int hf_mysql_stmt_id = -1;
572 static int hf_mysql_query = -1;
573 static int hf_mysql_shutdown = -1;
574 static int hf_mysql_option = -1;
575 static int hf_mysql_num_rows = -1;
576 static int hf_mysql_param = -1;
577 static int hf_mysql_num_params = -1;
578 static int hf_mysql_exec_flags4 = -1;
579 static int hf_mysql_exec_flags5 = -1;
580 static int hf_mysql_exec_iter = -1;
581 static int hf_mysql_binlog_position = -1;
582 static int hf_mysql_binlog_flags = -1;
583 static int hf_mysql_binlog_server_id = -1;
584 static int hf_mysql_binlog_file_name = -1;
585 static int hf_mysql_eof = -1;
586 static int hf_mysql_num_fields = -1;
587 static int hf_mysql_extra = -1;
588 static int hf_mysql_fld_catalog = -1;
589 static int hf_mysql_fld_db = -1;
590 static int hf_mysql_fld_table = -1;
591 static int hf_mysql_fld_org_table = -1;
592 static int hf_mysql_fld_name = -1;
593 static int hf_mysql_fld_org_name = -1;
594 static int hf_mysql_fld_charsetnr = -1;
595 static int hf_mysql_fld_length = -1;
596 static int hf_mysql_fld_type = -1;
597 static int hf_mysql_fld_flags = -1;
598 static int hf_mysql_fld_not_null = -1;
599 static int hf_mysql_fld_primary_key = -1;
600 static int hf_mysql_fld_unique_key = -1;
601 static int hf_mysql_fld_multiple_key = -1;
602 static int hf_mysql_fld_blob = -1;
603 static int hf_mysql_fld_unsigned = -1;
604 static int hf_mysql_fld_zero_fill = -1;
605 static int hf_mysql_fld_binary = -1;
606 static int hf_mysql_fld_enum = -1;
607 static int hf_mysql_fld_auto_increment = -1;
608 static int hf_mysql_fld_timestamp = -1;
609 static int hf_mysql_fld_set = -1;
610 static int hf_mysql_fld_decimals = -1;
611 static int hf_mysql_fld_default = -1;
612 static int hf_mysql_row_text = -1;
613 static int hf_mysql_new_parameter_bound_flag = -1;
614 static int hf_mysql_exec_param = -1;
615 static int hf_mysql_exec_unsigned = -1;
616 static int hf_mysql_exec_field_longlong = -1;
617 static int hf_mysql_exec_field_string = -1;
618 static int hf_mysql_exec_field_double = -1;
619 static int hf_mysql_exec_field_datetime_length = -1;
620 static int hf_mysql_exec_field_year = -1;
621 static int hf_mysql_exec_field_month = -1;
622 static int hf_mysql_exec_field_day = -1;
623 static int hf_mysql_exec_field_hour = -1;
624 static int hf_mysql_exec_field_minute = -1;
625 static int hf_mysql_exec_field_second = -1;
626 static int hf_mysql_exec_field_second_b = -1;
627 static int hf_mysql_exec_field_long = -1;
628 static int hf_mysql_exec_field_tiny = -1;
629 static int hf_mysql_exec_field_short = -1;
630 static int hf_mysql_exec_field_float = -1;
631 static int hf_mysql_exec_field_time_length = -1;
632 static int hf_mysql_exec_field_time_sign = -1;
633 static int hf_mysql_exec_field_time_days = -1;
634 static int hf_mysql_auth_switch_request_status = -1;
635 static int hf_mysql_auth_switch_request_name = -1;
636 static int hf_mysql_auth_switch_request_data = -1;
637 static int hf_mysql_auth_switch_response_data = -1;
638 static int hf_mysql_compressed_packet_length = -1;
639 static int hf_mysql_compressed_packet_length_uncompressed = -1;
640 static int hf_mysql_compressed_packet_number = -1;
642 static dissector_handle_t mysql_handle;
643 static dissector_handle_t tls_handle;
645 static expert_field ei_mysql_eof = EI_INIT;
646 static expert_field ei_mysql_dissector_incomplete = EI_INIT;
647 static expert_field ei_mysql_streamed_param = EI_INIT;
648 static expert_field ei_mysql_prepare_response_needed = EI_INIT;
649 static expert_field ei_mysql_unknown_response = EI_INIT;
650 static expert_field ei_mysql_command = EI_INIT;
653 static const value_string type_constants[] = {
654 {0x00, "FIELD_TYPE_DECIMAL" },
655 {0x01, "FIELD_TYPE_TINY" },
656 {0x02, "FIELD_TYPE_SHORT" },
657 {0x03, "FIELD_TYPE_LONG" },
658 {0x04, "FIELD_TYPE_FLOAT" },
659 {0x05, "FIELD_TYPE_DOUBLE" },
660 {0x06, "FIELD_TYPE_NULL" },
661 {0x07, "FIELD_TYPE_TIMESTAMP" },
662 {0x08, "FIELD_TYPE_LONGLONG" },
663 {0x09, "FIELD_TYPE_INT24" },
664 {0x0a, "FIELD_TYPE_DATE" },
665 {0x0b, "FIELD_TYPE_TIME" },
666 {0x0c, "FIELD_TYPE_DATETIME" },
667 {0x0d, "FIELD_TYPE_YEAR" },
668 {0x0e, "FIELD_TYPE_NEWDATE" },
669 {0x0f, "FIELD_TYPE_VARCHAR" },
670 {0x10, "FIELD_TYPE_BIT" },
671 {0xf6, "FIELD_TYPE_NEWDECIMAL" },
672 {0xf7, "FIELD_TYPE_ENUM" },
673 {0xf8, "FIELD_TYPE_SET" },
674 {0xf9, "FIELD_TYPE_TINY_BLOB" },
675 {0xfa, "FIELD_TYPE_MEDIUM_BLOB"},
676 {0xfb, "FIELD_TYPE_LONG_BLOB" },
677 {0xfc, "FIELD_TYPE_BLOB" },
678 {0xfd, "FIELD_TYPE_VAR_STRING" },
679 {0xfe, "FIELD_TYPE_STRING" },
680 {0xff, "FIELD_TYPE_GEOMETRY" },
684 typedef enum mysql_state {
691 RESPONSE_SHOW_FIELDS,
702 static const value_string state_vals[] = {
703 {UNDEFINED, "undefined"},
705 {REQUEST, "request"},
706 {RESPONSE_OK, "response OK"},
707 {RESPONSE_MESSAGE, "response message"},
708 {RESPONSE_TABULAR, "tabular response"},
709 {RESPONSE_SHOW_FIELDS, "response to SHOW FIELDS"},
710 {FIELD_PACKET, "field packet"},
711 {ROW_PACKET, "row packet"},
712 {RESPONSE_PREPARE, "response to PREPARE"},
713 {PREPARED_PARAMETERS, "parameters in response to PREPARE"},
714 {PREPARED_FIELDS, "fields in response to PREPARE"},
715 {AUTH_SWITCH_REQUEST, "authentication switch request"},
716 {AUTH_SWITCH_RESPONSE, "authentication switch response"},
721 typedef struct mysql_conn_data {
723 guint16 srv_caps_ext;
725 guint16 clnt_caps_ext;
727 guint16 stmt_num_params;
728 guint16 stmt_num_fields;
733 guint8 major_version;
734 guint32 frame_start_ssl;
735 guint32 frame_start_compressed;
736 guint8 compressed_state;
739 struct mysql_frame_data {
743 typedef struct my_stmt_data {
748 typedef struct mysql_exec_dissector {
750 guint8 unsigned_flag;
751 void (*dissector)(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
752 } mysql_exec_dissector_t;
754 /* function prototypes */
755 static int mysql_dissect_error_packet(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
756 static int mysql_dissect_ok_packet(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, mysql_conn_data_t *conn_data);
757 static int mysql_dissect_server_status(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *server_status);
758 static int mysql_dissect_caps(tvbuff_t *tvb, int offset, proto_tree *tree, int mysql_caps, guint16 *caps);
759 static int mysql_dissect_extcaps(tvbuff_t *tvb, int offset, proto_tree *tree, int mysql_extcaps, guint16 *caps);
760 static int mysql_dissect_result_header(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, mysql_conn_data_t *conn_data);
761 static int mysql_dissect_field_packet(tvbuff_t *tvb, int offset, proto_tree *tree, mysql_conn_data_t *conn_data);
762 static int mysql_dissect_row_packet(tvbuff_t *tvb, int offset, proto_tree *tree);
763 static int mysql_dissect_response_prepare(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, mysql_conn_data_t *conn_data);
764 static int mysql_dissect_auth_switch_request(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, mysql_conn_data_t *conn_data);
765 static int mysql_dissect_auth_switch_response(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, mysql_conn_data_t *conn_data);
766 static void mysql_dissect_exec_string(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
767 static void mysql_dissect_exec_datetime(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
768 static void mysql_dissect_exec_tiny(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
769 static void mysql_dissect_exec_short(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
770 static void mysql_dissect_exec_long(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
771 static void mysql_dissect_exec_float(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
772 static void mysql_dissect_exec_double(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
773 static void mysql_dissect_exec_longlong(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
774 static void mysql_dissect_exec_null(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
775 static char mysql_dissect_exec_param(proto_item *req_tree, tvbuff_t *tvb, int *offset,
776 int *param_offset, guint8 param_flags, packet_info *pinfo);
777 static void mysql_dissect_exec_primitive(tvbuff_t *tvb, int *param_offset,
778 proto_item *field_tree, const int hfindex, const int offset);
779 static void mysql_dissect_exec_time(tvbuff_t *tvb, int *param_offset, proto_item *field_tree);
781 static gint my_tvb_strsize(tvbuff_t *tvb, int offset);
782 static int tvb_get_fle(tvbuff_t *tvb, int offset, guint64 *res, guint8 *is_null);
784 static const mysql_exec_dissector_t mysql_exec_dissectors[] = {
785 { 0x01, 0, mysql_dissect_exec_tiny },
786 { 0x02, 0, mysql_dissect_exec_short },
787 { 0x03, 0, mysql_dissect_exec_long },
788 { 0x04, 0, mysql_dissect_exec_float },
789 { 0x05, 0, mysql_dissect_exec_double },
790 { 0x06, 0, mysql_dissect_exec_null },
791 { 0x07, 0, mysql_dissect_exec_datetime },
792 { 0x08, 0, mysql_dissect_exec_longlong },
793 { 0x0a, 0, mysql_dissect_exec_datetime },
794 { 0x0b, 0, mysql_dissect_exec_time },
795 { 0x0c, 0, mysql_dissect_exec_datetime },
796 { 0xf6, 0, mysql_dissect_exec_string },
797 { 0xfc, 0, mysql_dissect_exec_string },
798 { 0xfd, 0, mysql_dissect_exec_string },
799 { 0xfe, 0, mysql_dissect_exec_string },
803 static const int *mysql_rfsh_flags[] = {
804 &hf_mysql_rfsh_grants,
806 &hf_mysql_rfsh_tables,
807 &hf_mysql_rfsh_hosts,
808 &hf_mysql_rfsh_status,
809 &hf_mysql_rfsh_threads,
810 &hf_mysql_rfsh_slave,
811 &hf_mysql_rfsh_master,
815 static const int *mysql_stat_flags[] = {
827 &hf_mysql_stat_query_was_slow,
828 &hf_mysql_stat_ps_out_params,
829 &hf_mysql_stat_trans_readonly,
830 &hf_mysql_stat_session_state_changed,
834 static const int *mysql_caps_flags[] = {
835 &hf_mysql_cap_long_password,
836 &hf_mysql_cap_found_rows,
837 &hf_mysql_cap_long_flag,
838 &hf_mysql_cap_connect_with_db,
839 &hf_mysql_cap_no_schema,
840 &hf_mysql_cap_compress,
842 &hf_mysql_cap_local_files,
843 &hf_mysql_cap_ignore_space,
844 &hf_mysql_cap_change_user,
845 &hf_mysql_cap_interactive,
847 &hf_mysql_cap_ignore_sigpipe,
848 &hf_mysql_cap_transactions,
849 &hf_mysql_cap_reserved,
850 &hf_mysql_cap_secure_connect,
854 static const int * mysql_extcaps_flags[] = {
855 &hf_mysql_cap_multi_statements,
856 &hf_mysql_cap_multi_results,
857 &hf_mysql_cap_ps_multi_results,
858 &hf_mysql_cap_plugin_auth,
859 &hf_mysql_cap_connect_attrs,
860 &hf_mysql_cap_plugin_auth_lenenc_client_data,
861 &hf_mysql_cap_client_can_handle_expired_passwords,
862 &hf_mysql_cap_session_track,
863 &hf_mysql_cap_deprecate_eof,
864 &hf_mysql_cap_unused,
868 static const int * mysql_fld_flags[] = {
869 &hf_mysql_fld_not_null,
870 &hf_mysql_fld_primary_key,
871 &hf_mysql_fld_unique_key,
872 &hf_mysql_fld_multiple_key,
874 &hf_mysql_fld_unsigned,
875 &hf_mysql_fld_zero_fill,
876 &hf_mysql_fld_binary,
878 &hf_mysql_fld_auto_increment,
879 &hf_mysql_fld_timestamp,
884 /* Helper function to only set state on first pass */
885 static void mysql_set_conn_state(packet_info *pinfo, mysql_conn_data_t *conn_data, mysql_state_t state)
887 if (!pinfo->fd->visited)
889 conn_data->state = state;
894 mysql_dissect_greeting(tvbuff_t *tvb, packet_info *pinfo, int offset,
895 proto_tree *tree, mysql_conn_data_t *conn_data)
902 proto_item *greeting_tree;
904 protocol= tvb_get_guint8(tvb, offset);
906 if (protocol == 0xff) {
907 return mysql_dissect_error_packet(tvb, pinfo, offset+1, tree);
910 mysql_set_conn_state(pinfo, conn_data, LOGIN);
912 tf = proto_tree_add_item(tree, hf_mysql_server_greeting, tvb, offset, -1, ENC_NA);
913 greeting_tree = proto_item_add_subtree(tf, ett_server_greeting);
915 col_append_fstr(pinfo->cinfo, COL_INFO, " proto=%d", protocol) ;
917 proto_tree_add_item(greeting_tree, hf_mysql_protocol, tvb, offset, 1, ENC_NA);
922 lenstr = tvb_strsize(tvb,offset);
923 col_append_fstr(pinfo->cinfo, COL_INFO, " version=%s",
924 tvb_format_text(tvb, offset, lenstr-1));
926 proto_tree_add_item(greeting_tree, hf_mysql_version, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
927 conn_data->major_version = 0;
928 for (ver_offset = 0; ver_offset < lenstr; ver_offset++) {
929 guint8 ver_char = tvb_get_guint8(tvb, offset + ver_offset);
930 if (ver_char == '.') break;
931 conn_data->major_version = conn_data->major_version * 10 + ver_char - '0';
935 /* 4 bytes little endian thread_id */
936 proto_tree_add_item(greeting_tree, hf_mysql_thread_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
940 lenstr = tvb_strsize(tvb,offset);
941 proto_tree_add_item(greeting_tree, hf_mysql_salt, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
944 /* rest is optional */
945 if (!tvb_reported_length_remaining(tvb, offset)) return offset;
948 offset = mysql_dissect_caps(tvb, offset, greeting_tree, hf_mysql_caps_server, &conn_data->srv_caps);
950 /* rest is optional */
951 if (!tvb_reported_length_remaining(tvb, offset)) return offset;
953 proto_tree_add_item(greeting_tree, hf_mysql_server_language, tvb, offset, 1, ENC_NA);
954 offset += 1; /* for charset */
956 offset = mysql_dissect_server_status(tvb, offset, greeting_tree, NULL);
958 /* 2 bytes ExtCAPS */
959 offset = mysql_dissect_extcaps(tvb, offset, greeting_tree, hf_mysql_extcaps_server, &conn_data->srv_caps_ext);
961 /* 1 byte Auth Plugin Length */
962 proto_tree_add_item(greeting_tree, hf_mysql_auth_plugin_length, tvb, offset, 1, ENC_NA);
965 /* 10 bytes unused */
966 proto_tree_add_item(greeting_tree, hf_mysql_unused, tvb, offset, 10, ENC_NA);
969 /* 4.1+ server: rest of salt */
970 if (tvb_reported_length_remaining(tvb, offset)) {
971 lenstr = tvb_strsize(tvb,offset);
972 proto_tree_add_item(greeting_tree, hf_mysql_salt2, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
976 /* 5.x server: auth plugin */
977 if (tvb_reported_length_remaining(tvb, offset)) {
978 lenstr = tvb_strsize(tvb,offset);
979 proto_tree_add_item(greeting_tree, hf_mysql_auth_plugin, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
988 Add a connect attributs entry to the connattrs subtree
993 add_connattrs_entry_to_tree(tvbuff_t *tvb, packet_info *pinfo _U_, proto_item *tree, int offset) {
995 int orig_offset = offset, lenfle;
997 proto_tree *connattrs_tree;
1000 ti = proto_tree_add_item(tree, hf_mysql_connattrs_attr, tvb, offset, 1, ENC_NA);
1001 connattrs_tree = proto_item_add_subtree(ti, ett_connattrs_attr);
1003 lenfle = tvb_get_fle(tvb, offset, &lenstr, NULL);
1004 proto_tree_add_uint64(connattrs_tree, hf_mysql_connattrs_name_length, tvb, offset, lenfle, lenstr);
1007 proto_tree_add_item_ret_string(connattrs_tree, hf_mysql_connattrs_name, tvb, offset, (gint)lenstr, ENC_ASCII|ENC_NA, wmem_packet_scope(), &str);
1008 proto_item_append_text(ti, " - %s", str);
1009 offset += (int)lenstr;
1011 lenfle = tvb_get_fle(tvb, offset, &lenstr, NULL);
1012 proto_tree_add_uint64(connattrs_tree, hf_mysql_connattrs_value_length, tvb, offset, lenfle, lenstr);
1015 proto_tree_add_item_ret_string(connattrs_tree, hf_mysql_connattrs_value, tvb, offset, (gint)lenstr, ENC_ASCII|ENC_NA, wmem_packet_scope(), &str);
1016 proto_item_append_text(ti, ": %s", str);
1017 offset += (int)lenstr;
1019 proto_item_set_len(ti, offset - orig_offset);
1021 return (offset - orig_offset);
1025 mysql_dissect_login(tvbuff_t *tvb, packet_info *pinfo, int offset,
1026 proto_tree *tree, mysql_conn_data_t *conn_data)
1031 proto_item *login_tree;
1033 /* after login there can be OK or DENIED */
1034 mysql_set_conn_state(pinfo, conn_data, RESPONSE_OK);
1036 tf = proto_tree_add_item(tree, hf_mysql_login_request, tvb, offset, -1, ENC_NA);
1037 login_tree = proto_item_add_subtree(tf, ett_login_request);
1039 offset = mysql_dissect_caps(tvb, offset, login_tree, hf_mysql_caps_client, &conn_data->clnt_caps);
1041 if (!(conn_data->frame_start_ssl) && conn_data->clnt_caps & MYSQL_CAPS_SL) /* Next packet will be use SSL */
1043 col_set_str(pinfo->cinfo, COL_INFO, "Response: SSL Handshake");
1044 conn_data->frame_start_ssl = pinfo->num;
1045 ssl_starttls_ack(tls_handle, pinfo, mysql_handle);
1047 if (conn_data->clnt_caps & MYSQL_CAPS_CU) /* 4.1 protocol */
1049 offset = mysql_dissect_extcaps(tvb, offset, login_tree, hf_mysql_extcaps_client, &conn_data->clnt_caps_ext);
1051 proto_tree_add_item(login_tree, hf_mysql_max_packet, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1054 proto_tree_add_item(login_tree, hf_mysql_charset, tvb, offset, 1, ENC_NA);
1055 offset += 1; /* for charset */
1057 offset += 23; /* filler bytes */
1059 } else { /* pre-4.1 */
1060 proto_tree_add_item(login_tree, hf_mysql_max_packet, tvb, offset, 3, ENC_LITTLE_ENDIAN);
1065 lenstr = my_tvb_strsize(tvb, offset);
1066 col_append_fstr(pinfo->cinfo, COL_INFO, " user=%s",
1067 tvb_format_text(tvb, offset, lenstr-1));
1068 proto_tree_add_item(login_tree, hf_mysql_user, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1071 /* rest is optional */
1072 if (!tvb_reported_length_remaining(tvb, offset)) return offset;
1074 /* password: asciiz or length+ascii */
1075 if (conn_data->clnt_caps & MYSQL_CAPS_SC) {
1076 lenstr = tvb_get_guint8(tvb, offset);
1079 lenstr = my_tvb_strsize(tvb, offset);
1081 if (tree && lenstr > 1) {
1082 proto_tree_add_item(login_tree, hf_mysql_passwd, tvb, offset, lenstr, ENC_NA);
1086 /* optional: initial schema */
1087 if (conn_data->clnt_caps & MYSQL_CAPS_CD)
1089 lenstr= my_tvb_strsize(tvb,offset);
1094 col_append_fstr(pinfo->cinfo, COL_INFO, " db=%s",
1095 tvb_format_text(tvb, offset, lenstr-1));
1097 proto_tree_add_item(login_tree, hf_mysql_schema, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1101 /* optional: authentication plugin */
1102 if (conn_data->clnt_caps_ext & MYSQL_CAPS_PA)
1104 mysql_set_conn_state(pinfo, conn_data, AUTH_SWITCH_REQUEST);
1105 lenstr= my_tvb_strsize(tvb,offset);
1106 proto_tree_add_item(login_tree, hf_mysql_client_auth_plugin, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1110 /* optional: connection attributes */
1111 if (conn_data->clnt_caps_ext & MYSQL_CAPS_CA && tvb_reported_length_remaining(tvb, offset))
1113 proto_tree *connattrs_tree;
1115 guint64 connattrs_length;
1118 lenfle = tvb_get_fle(tvb, offset, &connattrs_length, NULL);
1119 tf = proto_tree_add_item(login_tree, hf_mysql_connattrs, tvb, offset, (guint32)connattrs_length, ENC_NA);
1120 connattrs_tree = proto_item_add_subtree(tf, ett_connattrs);
1121 proto_tree_add_uint64(connattrs_tree, hf_mysql_connattrs_length, tvb, offset, lenfle, connattrs_length);
1124 while (connattrs_length > 0) {
1125 length = add_connattrs_entry_to_tree(tvb, pinfo, connattrs_tree, offset);
1127 connattrs_length -= length;
1136 mysql_dissect_exec_string(tvbuff_t *tvb, int *param_offset, proto_item *field_tree)
1138 guint32 param_len32;
1141 param_len = tvb_get_guint8(tvb, *param_offset);
1143 switch (param_len) {
1144 case 0xfc: /* 252 - 64k chars */
1146 param_len32 = tvb_get_letohs(tvb, *param_offset);
1147 proto_tree_add_item(field_tree, hf_mysql_exec_field_string,
1148 tvb, *param_offset, 2, ENC_ASCII | ENC_LITTLE_ENDIAN);
1149 *param_offset += param_len32 + 2;
1151 case 0xfd: /* 64k - 16M chars */
1153 param_len32 = tvb_get_letoh24(tvb, *param_offset);
1154 proto_tree_add_item(field_tree, hf_mysql_exec_field_string,
1155 tvb, *param_offset, 3, ENC_ASCII | ENC_LITTLE_ENDIAN);
1156 *param_offset += param_len32 + 3;
1158 default: /* < 252 chars */
1159 proto_tree_add_item(field_tree, hf_mysql_exec_field_string,
1160 tvb, *param_offset, 1, ENC_ASCII | ENC_NA);
1161 *param_offset += param_len + 1;
1167 mysql_dissect_exec_time(tvbuff_t *tvb, int *param_offset, proto_item *field_tree)
1171 param_len = tvb_get_guint8(tvb, *param_offset);
1172 proto_tree_add_item(field_tree, hf_mysql_exec_field_time_length,
1173 tvb, *param_offset, 1, ENC_NA);
1175 if (param_len >= 1) {
1176 proto_tree_add_item(field_tree, hf_mysql_exec_field_time_sign,
1177 tvb, *param_offset, 1, ENC_NA);
1179 if (param_len >= 5) {
1180 proto_tree_add_item(field_tree, hf_mysql_exec_field_time_days,
1181 tvb, *param_offset + 1, 4, ENC_LITTLE_ENDIAN);
1183 if (param_len >= 8) {
1184 proto_tree_add_item(field_tree, hf_mysql_exec_field_hour,
1185 tvb, *param_offset + 5, 1, ENC_NA);
1186 proto_tree_add_item(field_tree, hf_mysql_exec_field_minute,
1187 tvb, *param_offset + 6, 1, ENC_NA);
1188 proto_tree_add_item(field_tree, hf_mysql_exec_field_second,
1189 tvb, *param_offset + 7, 1, ENC_NA);
1191 if (param_len >= 12) {
1192 proto_tree_add_item(field_tree, hf_mysql_exec_field_second_b,
1193 tvb, *param_offset + 8, 4, ENC_LITTLE_ENDIAN);
1195 *param_offset += param_len;
1199 mysql_dissect_exec_datetime(tvbuff_t *tvb, int *param_offset, proto_item *field_tree)
1203 param_len = tvb_get_guint8(tvb, *param_offset);
1204 proto_tree_add_item(field_tree, hf_mysql_exec_field_datetime_length,
1205 tvb, *param_offset, 1, ENC_NA);
1207 if (param_len >= 2) {
1208 proto_tree_add_item(field_tree, hf_mysql_exec_field_year,
1209 tvb, *param_offset, 2, ENC_LITTLE_ENDIAN);
1211 if (param_len >= 4) {
1212 proto_tree_add_item(field_tree, hf_mysql_exec_field_month,
1213 tvb, *param_offset + 2, 1, ENC_NA);
1214 proto_tree_add_item(field_tree, hf_mysql_exec_field_day,
1215 tvb, *param_offset + 3, 1, ENC_NA);
1217 if (param_len >= 7) {
1218 proto_tree_add_item(field_tree, hf_mysql_exec_field_hour,
1219 tvb, *param_offset + 4, 1, ENC_NA);
1220 proto_tree_add_item(field_tree, hf_mysql_exec_field_minute,
1221 tvb, *param_offset + 5, 1, ENC_NA);
1222 proto_tree_add_item(field_tree, hf_mysql_exec_field_second,
1223 tvb, *param_offset + 6, 1, ENC_NA);
1225 if (param_len >= 11) {
1226 proto_tree_add_item(field_tree, hf_mysql_exec_field_second_b,
1227 tvb, *param_offset + 7, 4, ENC_LITTLE_ENDIAN);
1229 *param_offset += param_len;
1233 mysql_dissect_exec_primitive(tvbuff_t *tvb, int *param_offset,
1234 proto_item *field_tree, const int hfindex,
1237 proto_tree_add_item(field_tree, hfindex, tvb,
1238 *param_offset, offset, ENC_LITTLE_ENDIAN);
1239 *param_offset += offset;
1243 mysql_dissect_exec_tiny(tvbuff_t *tvb, int *param_offset, proto_item *field_tree)
1245 mysql_dissect_exec_primitive(tvb, param_offset, field_tree, hf_mysql_exec_field_tiny, 1);
1249 mysql_dissect_exec_short(tvbuff_t *tvb, int *param_offset, proto_item *field_tree)
1251 mysql_dissect_exec_primitive(tvb, param_offset, field_tree, hf_mysql_exec_field_short, 2);
1255 mysql_dissect_exec_long(tvbuff_t *tvb, int *param_offset, proto_item *field_tree)
1257 mysql_dissect_exec_primitive(tvb, param_offset, field_tree, hf_mysql_exec_field_long, 4);
1261 mysql_dissect_exec_float(tvbuff_t *tvb, int *param_offset, proto_item *field_tree)
1263 mysql_dissect_exec_primitive(tvb, param_offset, field_tree, hf_mysql_exec_field_float, 4);
1267 mysql_dissect_exec_double(tvbuff_t *tvb, int *param_offset, proto_item *field_tree)
1269 mysql_dissect_exec_primitive(tvb, param_offset, field_tree, hf_mysql_exec_field_double, 8);
1273 mysql_dissect_exec_longlong(tvbuff_t *tvb, int *param_offset, proto_item *field_tree)
1275 mysql_dissect_exec_primitive(tvb, param_offset, field_tree, hf_mysql_exec_field_longlong, 8);
1279 mysql_dissect_exec_null(tvbuff_t *tvb _U_, int *param_offset _U_, proto_item *field_tree _U_)
1283 mysql_dissect_exec_param(proto_item *req_tree, tvbuff_t *tvb, int *offset,
1284 int *param_offset, guint8 param_flags,
1287 guint8 param_type, param_unsigned;
1289 proto_item *field_tree;
1290 int dissector_index = 0;
1292 tf = proto_tree_add_item(req_tree, hf_mysql_exec_param, tvb, *offset, 2, ENC_NA);
1293 field_tree = proto_item_add_subtree(tf, ett_stat);
1294 proto_tree_add_item(field_tree, hf_mysql_fld_type, tvb, *offset, 1, ENC_NA);
1295 param_type = tvb_get_guint8(tvb, *offset);
1296 *offset += 1; /* type */
1297 proto_tree_add_item(field_tree, hf_mysql_exec_unsigned, tvb, *offset, 1, ENC_NA);
1298 param_unsigned = tvb_get_guint8(tvb, *offset);
1299 *offset += 1; /* signedness */
1300 if ((param_flags & MYSQL_PARAM_FLAG_STREAMED) == MYSQL_PARAM_FLAG_STREAMED) {
1301 expert_add_info(pinfo, field_tree, &ei_mysql_streamed_param);
1304 while (mysql_exec_dissectors[dissector_index].dissector != NULL) {
1305 if (mysql_exec_dissectors[dissector_index].type == param_type &&
1306 mysql_exec_dissectors[dissector_index].unsigned_flag == param_unsigned) {
1307 mysql_exec_dissectors[dissector_index].dissector(tvb, param_offset, field_tree);
1316 mysql_dissect_request(tvbuff_t *tvb,packet_info *pinfo, int offset,
1317 proto_tree *tree, mysql_conn_data_t *conn_data, mysql_state_t current_state)
1321 proto_item *request_item, *tf = NULL, *ti;
1322 proto_item *req_tree;
1324 my_stmt_data_t *stmt_data;
1325 int stmt_pos, param_offset;
1327 if(current_state == AUTH_SWITCH_RESPONSE){
1328 return mysql_dissect_auth_switch_response(tvb, pinfo, offset, tree, conn_data);
1331 request_item = proto_tree_add_item(tree, hf_mysql_request, tvb, offset, -1, ENC_NA);
1332 req_tree = proto_item_add_subtree(request_item, ett_request);
1334 opcode = tvb_get_guint8(tvb, offset);
1335 col_append_fstr(pinfo->cinfo, COL_INFO, " %s", val_to_str_ext(opcode, &mysql_command_vals_ext, "Unknown (%u)"));
1337 proto_tree_add_item(req_tree, hf_mysql_command, tvb, offset, 1, ENC_NA);
1338 proto_item_append_text(request_item, " %s", val_to_str_ext(opcode, &mysql_command_vals_ext, "Unknown (%u)"));
1347 case MYSQL_PROCESS_INFO:
1348 mysql_set_conn_state(pinfo, conn_data, RESPONSE_TABULAR);
1353 mysql_set_conn_state(pinfo, conn_data, RESPONSE_OK);
1356 case MYSQL_STATISTICS:
1357 mysql_set_conn_state(pinfo, conn_data, RESPONSE_MESSAGE);
1361 case MYSQL_CREATE_DB:
1363 lenstr = my_tvb_strsize(tvb, offset);
1364 proto_tree_add_item(req_tree, hf_mysql_schema, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1366 mysql_set_conn_state(pinfo, conn_data, RESPONSE_OK);
1370 lenstr = my_tvb_strsize(tvb, offset);
1371 proto_tree_add_item(req_tree, hf_mysql_query, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1372 if (mysql_showquery) {
1373 col_append_fstr(pinfo->cinfo, COL_INFO, " { %s } ",
1374 tvb_format_text(tvb, offset, lenstr));
1377 mysql_set_conn_state(pinfo, conn_data, RESPONSE_TABULAR);
1380 case MYSQL_STMT_PREPARE:
1381 lenstr = my_tvb_strsize(tvb, offset);
1382 proto_tree_add_item(req_tree, hf_mysql_query, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1384 mysql_set_conn_state(pinfo, conn_data, RESPONSE_PREPARE);
1387 case MYSQL_STMT_CLOSE:
1388 proto_tree_add_item(req_tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1390 mysql_set_conn_state(pinfo, conn_data, REQUEST);
1393 case MYSQL_STMT_RESET:
1394 proto_tree_add_item(req_tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1396 mysql_set_conn_state(pinfo, conn_data, RESPONSE_OK);
1399 case MYSQL_FIELD_LIST:
1400 lenstr = my_tvb_strsize(tvb, offset);
1401 proto_tree_add_item(req_tree, hf_mysql_table_name, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1403 mysql_set_conn_state(pinfo, conn_data, RESPONSE_SHOW_FIELDS);
1406 case MYSQL_PROCESS_KILL:
1407 proto_tree_add_item(req_tree, hf_mysql_thd_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1409 mysql_set_conn_state(pinfo, conn_data, RESPONSE_OK);
1412 case MYSQL_CHANGE_USER:
1413 lenstr = tvb_strsize(tvb, offset);
1414 proto_tree_add_item(req_tree, hf_mysql_user, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1417 if (conn_data->clnt_caps & MYSQL_CAPS_SC) {
1418 lenstr = tvb_get_guint8(tvb, offset);
1421 lenstr = tvb_strsize(tvb, offset);
1423 proto_tree_add_item(req_tree, hf_mysql_passwd, tvb, offset, lenstr, ENC_NA);
1426 lenstr = my_tvb_strsize(tvb, offset);
1427 proto_tree_add_item(req_tree, hf_mysql_schema, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1430 if (tvb_reported_length_remaining(tvb, offset) > 0) {
1431 proto_tree_add_item(req_tree, hf_mysql_charset, tvb, offset, 1, ENC_NA);
1432 offset += 2; /* for charset */
1434 mysql_set_conn_state(pinfo, conn_data, RESPONSE_OK);
1436 /* optional: authentication plugin */
1437 if (conn_data->clnt_caps_ext & MYSQL_CAPS_PA)
1439 mysql_set_conn_state(pinfo, conn_data, AUTH_SWITCH_REQUEST);
1440 lenstr= my_tvb_strsize(tvb,offset);
1441 proto_tree_add_item(req_tree, hf_mysql_client_auth_plugin, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1445 /* optional: connection attributes */
1446 if (conn_data->clnt_caps_ext & MYSQL_CAPS_CA)
1448 proto_tree *connattrs_tree;
1450 guint64 connattrs_length;
1453 lenfle = tvb_get_fle(tvb, offset, &connattrs_length, NULL);
1454 tf = proto_tree_add_item(req_tree, hf_mysql_connattrs, tvb, offset, (guint32)connattrs_length, ENC_NA);
1455 connattrs_tree = proto_item_add_subtree(tf, ett_connattrs);
1456 proto_tree_add_uint64(connattrs_tree, hf_mysql_connattrs_length, tvb, offset, lenfle, connattrs_length);
1459 while (connattrs_length > 0) {
1460 length = add_connattrs_entry_to_tree(tvb, pinfo, connattrs_tree, offset);
1462 connattrs_length -= length;
1468 proto_tree_add_bitmask_with_flags(req_tree, tvb, offset,
1469 hf_mysql_refresh, ett_refresh, mysql_rfsh_flags,
1470 ENC_BIG_ENDIAN, BMT_NO_APPEND);
1472 mysql_set_conn_state(pinfo, conn_data, RESPONSE_OK);
1475 case MYSQL_SHUTDOWN:
1476 proto_tree_add_item(req_tree, hf_mysql_shutdown, tvb, offset, 1, ENC_NA);
1478 mysql_set_conn_state(pinfo, conn_data, RESPONSE_OK);
1481 case MYSQL_SET_OPTION:
1482 proto_tree_add_item(req_tree, hf_mysql_option, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1484 mysql_set_conn_state(pinfo, conn_data, RESPONSE_OK);
1487 case MYSQL_STMT_FETCH:
1488 proto_tree_add_item(req_tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1491 proto_tree_add_item(req_tree, hf_mysql_num_rows, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1493 mysql_set_conn_state(pinfo, conn_data, RESPONSE_TABULAR);
1496 case MYSQL_STMT_SEND_LONG_DATA:
1497 proto_tree_add_item(req_tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1498 stmt_id = tvb_get_letohl(tvb, offset);
1501 stmt_data = (my_stmt_data_t *)wmem_tree_lookup32(conn_data->stmts, stmt_id);
1502 if (stmt_data != NULL) {
1503 guint16 data_param = tvb_get_letohs(tvb, offset);
1504 if (stmt_data->nparam > data_param) {
1505 stmt_data->param_flags[data_param] |= MYSQL_PARAM_FLAG_STREAMED;
1509 proto_tree_add_item(req_tree, hf_mysql_param, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1513 lenstr = tvb_reported_length_remaining(tvb, offset);
1514 if (tree && lenstr > 0) {
1515 proto_tree_add_item(req_tree, hf_mysql_payload, tvb, offset, lenstr, ENC_NA);
1518 mysql_set_conn_state(pinfo, conn_data, REQUEST);
1521 case MYSQL_STMT_EXECUTE:
1522 proto_tree_add_item(req_tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1523 stmt_id = tvb_get_letohl(tvb, offset);
1526 if (conn_data->major_version >= 5) {
1527 proto_tree_add_item(req_tree, hf_mysql_exec_flags5, tvb, offset, 1, ENC_NA);
1529 proto_tree_add_item(req_tree, hf_mysql_exec_flags4, tvb, offset, 1, ENC_NA);
1533 proto_tree_add_item(req_tree, hf_mysql_exec_iter, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1536 stmt_data = (my_stmt_data_t *)wmem_tree_lookup32(conn_data->stmts, stmt_id);
1537 if (stmt_data != NULL) {
1538 if (stmt_data->nparam != 0) {
1540 offset += (stmt_data->nparam + 7) / 8; /* NULL bitmap */
1541 proto_tree_add_item(req_tree, hf_mysql_new_parameter_bound_flag, tvb, offset, 1, ENC_NA);
1542 stmt_bound = tvb_get_guint8(tvb, offset);
1544 if (stmt_bound == 1) {
1545 param_offset = offset + stmt_data->nparam * 2;
1546 for (stmt_pos = 0; stmt_pos < stmt_data->nparam; stmt_pos++) {
1547 if (!mysql_dissect_exec_param(req_tree, tvb, &offset, ¶m_offset,
1548 stmt_data->param_flags[stmt_pos], pinfo))
1551 offset = param_offset;
1555 lenstr = tvb_reported_length_remaining(tvb, offset);
1556 if (tree && lenstr > 0) {
1557 ti = proto_tree_add_item(req_tree, hf_mysql_payload, tvb, offset, lenstr, ENC_NA);
1558 expert_add_info(pinfo, ti, &ei_mysql_prepare_response_needed);
1563 /* FIXME: rest needs metadata about statement */
1565 lenstr = tvb_reported_length_remaining(tvb, offset);
1566 if (tree && lenstr > 0) {
1567 ti = proto_tree_add_item(req_tree, hf_mysql_payload, tvb, offset, lenstr, ENC_NA);
1568 expert_add_info_format(pinfo, ti, &ei_mysql_dissector_incomplete, "FIXME: execute dissector incomplete");
1572 mysql_set_conn_state(pinfo, conn_data, RESPONSE_TABULAR);
1575 case MYSQL_BINLOG_DUMP_GTID:
1576 case MYSQL_BINLOG_DUMP:
1577 proto_tree_add_item(req_tree, hf_mysql_binlog_position, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1580 proto_tree_add_item(req_tree, hf_mysql_binlog_flags, tvb, offset, 2, ENC_BIG_ENDIAN);
1583 proto_tree_add_item(req_tree, hf_mysql_binlog_server_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1586 /* binlog file name ? */
1587 lenstr = tvb_reported_length_remaining(tvb, offset);
1588 if (tree && lenstr > 0) {
1589 proto_tree_add_item(req_tree, hf_mysql_binlog_file_name, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1593 mysql_set_conn_state(pinfo, conn_data, REQUEST);
1595 /* FIXME: implement replication packets */
1596 case MYSQL_TABLE_DUMP:
1597 case MYSQL_CONNECT_OUT:
1598 case MYSQL_REGISTER_SLAVE:
1599 ti = proto_tree_add_item(req_tree, hf_mysql_payload, tvb, offset, -1, ENC_NA);
1600 expert_add_info_format(pinfo, ti, &ei_mysql_dissector_incomplete, "FIXME: implement replication packets");
1601 offset += tvb_reported_length_remaining(tvb, offset);
1602 mysql_set_conn_state(pinfo, conn_data, REQUEST);
1606 ti = proto_tree_add_item(req_tree, hf_mysql_payload, tvb, offset, -1, ENC_NA);
1607 expert_add_info(pinfo, ti, &ei_mysql_command);
1608 offset += tvb_reported_length_remaining(tvb, offset);
1609 mysql_set_conn_state(pinfo, conn_data, UNDEFINED);
1612 proto_item_set_end(request_item, tvb, offset);
1617 * Decode the header of a compressed packet
1618 * https://dev.mysql.com/doc/internals/en/compressed-packet-header.html
1621 mysql_dissect_compressed_header(tvbuff_t *tvb, int offset, proto_tree *mysql_tree)
1623 proto_tree_add_item(mysql_tree, hf_mysql_compressed_packet_length, tvb, offset, 3, ENC_LITTLE_ENDIAN);
1626 proto_tree_add_item(mysql_tree, hf_mysql_compressed_packet_number, tvb, offset, 1, ENC_NA);
1629 proto_tree_add_item(mysql_tree, hf_mysql_compressed_packet_length_uncompressed, tvb, offset, 3, ENC_LITTLE_ENDIAN);
1636 mysql_dissect_response(tvbuff_t *tvb, packet_info *pinfo, int offset,
1637 proto_tree *tree, mysql_conn_data_t *conn_data, mysql_state_t current_state)
1642 guint16 server_status = 0;
1644 response_code = tvb_get_guint8(tvb, offset);
1646 if (response_code == 0xff ) {
1647 proto_tree_add_item(tree, hf_mysql_response_code, tvb, offset, 1, ENC_NA);
1648 offset = mysql_dissect_error_packet(tvb, pinfo, offset+1, tree);
1649 mysql_set_conn_state(pinfo, conn_data, REQUEST);
1652 else if (response_code == 0xfe && tvb_reported_length_remaining(tvb, offset) < 9) {
1654 proto_tree_add_item(tree, hf_mysql_response_code, tvb, offset, 1, ENC_NA);
1655 ti = proto_tree_add_item(tree, hf_mysql_eof, tvb, offset, 1, ENC_NA);
1659 /* pre-4.1 packet ends here */
1660 if (tvb_reported_length_remaining(tvb, offset)) {
1661 proto_tree_add_item(tree, hf_mysql_num_warn, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1662 offset = mysql_dissect_server_status(tvb, offset+2, tree, &server_status);
1665 switch (current_state) {
1667 mysql_set_conn_state(pinfo, conn_data, ROW_PACKET);
1670 if (server_status & MYSQL_STAT_MU) {
1671 mysql_set_conn_state(pinfo, conn_data, RESPONSE_TABULAR);
1673 mysql_set_conn_state(pinfo, conn_data, REQUEST);
1676 case PREPARED_PARAMETERS:
1677 if (conn_data->stmt_num_fields > 0) {
1678 mysql_set_conn_state(pinfo, conn_data, PREPARED_FIELDS);
1680 mysql_set_conn_state(pinfo, conn_data, REQUEST);
1683 case PREPARED_FIELDS:
1684 mysql_set_conn_state(pinfo, conn_data, REQUEST);
1687 /* This should be an unreachable case */
1688 mysql_set_conn_state(pinfo, conn_data, REQUEST);
1689 expert_add_info(pinfo, ti, &ei_mysql_eof);
1693 else if (response_code == 0) {
1694 proto_tree_add_item(tree, hf_mysql_response_code, tvb, offset, 1, ENC_NA);
1695 if (current_state == RESPONSE_PREPARE) {
1696 offset = mysql_dissect_response_prepare(tvb, pinfo, offset, tree, conn_data);
1697 } else if (tvb_reported_length_remaining(tvb, offset+1) > tvb_get_fle(tvb, offset+1, NULL, NULL)) {
1698 offset = mysql_dissect_ok_packet(tvb, pinfo, offset+1, tree, conn_data);
1699 if (conn_data->compressed_state == MYSQL_COMPRESS_INIT) {
1700 /* This is the OK packet which follows the compressed protocol setup */
1701 conn_data->compressed_state = MYSQL_COMPRESS_ACTIVE;
1704 offset = mysql_dissect_result_header(tvb, pinfo, offset, tree, conn_data);
1709 switch (current_state) {
1710 case RESPONSE_MESSAGE:
1711 if ((lenstr = tvb_reported_length_remaining(tvb, offset))) {
1712 proto_tree_add_item(tree, hf_mysql_message, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1715 mysql_set_conn_state(pinfo, conn_data, REQUEST);
1718 case RESPONSE_TABULAR:
1719 case REQUEST: /* That shouldn't be the case; maybe two requests in a row (s. bug 15074) */
1720 offset = mysql_dissect_result_header(tvb, pinfo, offset, tree, conn_data);
1724 case RESPONSE_SHOW_FIELDS:
1725 case RESPONSE_PREPARE:
1726 case PREPARED_PARAMETERS:
1727 offset = mysql_dissect_field_packet(tvb, offset, tree, conn_data);
1731 offset = mysql_dissect_row_packet(tvb, offset, tree);
1734 case PREPARED_FIELDS:
1735 offset = mysql_dissect_field_packet(tvb, offset, tree, conn_data);
1738 case AUTH_SWITCH_REQUEST:
1739 offset = mysql_dissect_auth_switch_request(tvb, pinfo, offset, tree, conn_data);
1744 ti = proto_tree_add_item(tree, hf_mysql_payload, tvb, offset, -1, ENC_NA);
1745 expert_add_info(pinfo, ti, &ei_mysql_unknown_response);
1746 offset += tvb_reported_length_remaining(tvb, offset);
1747 mysql_set_conn_state(pinfo, conn_data, UNDEFINED);
1756 mysql_dissect_error_packet(tvbuff_t *tvb, packet_info *pinfo,
1757 int offset, proto_tree *tree)
1759 col_append_fstr(pinfo->cinfo, COL_INFO, " Error %d", tvb_get_letohs(tvb, offset));
1761 proto_tree_add_item(tree, hf_mysql_error_code, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1764 if (tvb_get_guint8(tvb, offset) == '#')
1767 proto_tree_add_item(tree, hf_mysql_sqlstate, tvb, offset, 5, ENC_ASCII|ENC_NA);
1771 proto_tree_add_item(tree, hf_mysql_error_string, tvb, offset, -1, ENC_ASCII|ENC_NA);
1772 offset += tvb_reported_length_remaining(tvb, offset);
1778 Add a session track entry to the session tracking subtree
1783 add_session_tracker_entry_to_tree(tvbuff_t *tvb, packet_info *pinfo, proto_item *tree, int offset) {
1784 guint8 data_type; /* session tracker type */
1785 guint64 length; /* complete length of session tracking entry */
1787 int orig_offset = offset, lenfle;
1788 proto_item *item, *ti;
1789 proto_tree *session_track_tree;
1791 ti = proto_tree_add_item(tree, hf_mysql_session_track, tvb, offset, 1, ENC_NA);
1792 session_track_tree = proto_item_add_subtree(ti, ett_session_track);
1794 proto_tree_add_item(session_track_tree, hf_mysql_session_track_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1795 data_type = tvb_get_guint8(tvb, offset);
1798 lenfle = tvb_get_fle(tvb, offset, &length, NULL);
1799 proto_tree_add_uint64(session_track_tree, hf_mysql_session_track_length, tvb, offset, lenfle, length);
1802 switch (data_type) {
1803 case 0: /* SESSION_SYSVARS_TRACKER */
1804 lenfle = tvb_get_fle(tvb, offset, &lenstr, NULL);
1805 proto_tree_add_uint64(session_track_tree, hf_mysql_session_track_sysvar_length, tvb, offset, lenfle, lenstr);
1808 proto_tree_add_item(session_track_tree, hf_mysql_session_track_sysvar_name, tvb, offset, (gint)lenstr, ENC_ASCII|ENC_NA);
1809 offset += (int)lenstr;
1811 lenfle = tvb_get_fle(tvb, offset, &lenstr, NULL);
1812 proto_tree_add_uint64(session_track_tree, hf_mysql_session_track_sysvar_length, tvb, offset, lenfle, lenstr);
1815 proto_tree_add_item(session_track_tree, hf_mysql_session_track_sysvar_value, tvb, offset, (gint)lenstr, ENC_ASCII|ENC_NA);
1816 offset += (int)lenstr;
1818 case 1: /* CURRENT_SCHEMA_TRACKER */
1819 lenfle = tvb_get_fle(tvb, offset, &lenstr, NULL);
1820 proto_tree_add_uint64(session_track_tree, hf_mysql_session_track_schema_length, tvb, offset, lenfle, lenstr);
1823 proto_tree_add_item(session_track_tree, hf_mysql_session_track_schema, tvb, offset, (gint)lenstr, ENC_ASCII|ENC_NA);
1824 offset += (int)lenstr;
1826 case 2: /* SESSION_STATE_CHANGE_TRACKER */
1827 proto_tree_add_item(session_track_tree, hf_mysql_session_state_change, tvb, offset, 1, ENC_ASCII|ENC_NA);
1830 default: /* unsupported types skipped */
1831 item = proto_tree_add_item(session_track_tree, hf_mysql_payload, tvb, offset, (gint)length, ENC_NA);
1832 expert_add_info_format(pinfo, item, &ei_mysql_dissector_incomplete, "FIXME: unrecognized session tracker data");
1833 offset += (int)length;
1835 proto_item_set_len(ti, offset - orig_offset);
1837 return (offset - orig_offset);
1841 mysql_dissect_ok_packet(tvbuff_t *tvb, packet_info *pinfo, int offset,
1842 proto_tree *tree, mysql_conn_data_t *conn_data)
1845 guint64 affected_rows;
1848 guint16 server_status = 0;
1850 col_append_str(pinfo->cinfo, COL_INFO, " OK" );
1852 fle = tvb_get_fle(tvb, offset, &affected_rows, NULL);
1853 proto_tree_add_uint64(tree, hf_mysql_affected_rows, tvb, offset, fle, affected_rows);
1856 fle= tvb_get_fle(tvb, offset, &insert_id, NULL);
1857 if (tree && insert_id) {
1858 proto_tree_add_uint64(tree, hf_mysql_insert_id, tvb, offset, fle, insert_id);
1862 if (tvb_reported_length_remaining(tvb, offset) > 0) {
1863 offset = mysql_dissect_server_status(tvb, offset, tree, &server_status);
1865 /* 4.1+ protocol only: 2 bytes number of warnings */
1866 if (conn_data->clnt_caps & conn_data->srv_caps & MYSQL_CAPS_CU) {
1867 proto_tree_add_item(tree, hf_mysql_num_warn, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1872 if (conn_data->clnt_caps_ext & MYSQL_CAPS_ST) {
1873 if (tvb_reported_length_remaining(tvb, offset) > 0) {
1874 guint64 session_track_length;
1876 proto_item *session_track_tree = NULL;
1879 offset += tvb_get_fle(tvb, offset, &lenstr, NULL);
1880 /* first read the optional message */
1882 proto_tree_add_item(tree, hf_mysql_message, tvb, offset, (gint)lenstr, ENC_ASCII|ENC_NA);
1883 offset += (int)lenstr;
1886 /* session state tracking */
1887 if (server_status & MYSQL_STAT_SESSION_STATE_CHANGED) {
1888 fle = tvb_get_fle(tvb, offset, &session_track_length, NULL);
1889 tf = proto_tree_add_item(tree, hf_mysql_session_track_data, tvb, offset, -1, ENC_NA);
1890 session_track_tree = proto_item_add_subtree(tf, ett_session_track_data);
1891 proto_tree_add_uint64(tf, hf_mysql_session_track_data_length, tvb, offset, fle, session_track_length);
1894 while (session_track_length > 0) {
1895 length = add_session_tracker_entry_to_tree(tvb, pinfo, session_track_tree, offset);
1897 session_track_length -= length;
1902 /* optional: message string */
1903 if (tvb_reported_length_remaining(tvb, offset) > 0) {
1904 lenstr = tvb_reported_length_remaining(tvb, offset);
1905 proto_tree_add_item(tree, hf_mysql_message, tvb, offset, (gint)lenstr, ENC_ASCII|ENC_NA);
1906 offset += (int)lenstr;
1910 mysql_set_conn_state(pinfo, conn_data, REQUEST);
1916 mysql_dissect_server_status(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *server_status)
1919 if (server_status) {
1920 *server_status = tvb_get_letohs(tvb, offset);
1922 proto_tree_add_bitmask_with_flags(tree, tvb, offset, hf_mysql_server_status, ett_stat, mysql_stat_flags, ENC_LITTLE_ENDIAN, BMT_NO_APPEND);
1931 mysql_dissect_caps(tvbuff_t *tvb, int offset, proto_tree *tree, int mysql_caps, guint16 *caps)
1934 *caps= tvb_get_letohs(tvb, offset);
1936 proto_tree_add_bitmask_with_flags(tree, tvb, offset, mysql_caps, ett_caps, mysql_caps_flags, ENC_LITTLE_ENDIAN, BMT_NO_APPEND);
1943 mysql_dissect_extcaps(tvbuff_t *tvb, int offset, proto_tree *tree, int mysql_extcaps, guint16 *ext_caps)
1946 *ext_caps= tvb_get_letohs(tvb, offset);
1948 proto_tree_add_bitmask_with_flags(tree, tvb, offset, mysql_extcaps, ett_extcaps, mysql_extcaps_flags, ENC_LITTLE_ENDIAN, BMT_NO_APPEND);
1956 mysql_dissect_result_header(tvbuff_t *tvb, packet_info *pinfo, int offset,
1957 proto_tree *tree, mysql_conn_data_t *conn_data)
1960 guint64 num_fields, extra;
1962 col_append_str(pinfo->cinfo, COL_INFO, " TABULAR" );
1964 fle = tvb_get_fle(tvb, offset, &num_fields, NULL);
1965 proto_tree_add_uint64(tree, hf_mysql_num_fields, tvb, offset, fle, num_fields);
1968 if (tvb_reported_length_remaining(tvb, offset)) {
1969 fle = tvb_get_fle(tvb, offset, &extra, NULL);
1970 proto_tree_add_uint64(tree, hf_mysql_extra, tvb, offset, fle, extra);
1975 mysql_set_conn_state(pinfo, conn_data, FIELD_PACKET);
1977 mysql_set_conn_state(pinfo, conn_data, ROW_PACKET);
1985 * Add length encoded string to tree
1988 mysql_field_add_lestring(tvbuff_t *tvb, int offset, proto_tree *tree, int field)
1993 offset += tvb_get_fle(tvb, offset, &lelen, &is_null);
1995 proto_tree_add_string(tree, field, tvb, offset, 0, "NULL");
1998 proto_tree_add_item(tree, field, tvb, offset, (int)lelen, ENC_NA);
1999 /* Prevent infinite loop due to overflow */
2000 if (offset + (int)lelen < offset) {
2001 offset = tvb_reported_length(tvb);
2004 offset += (int)lelen;
2012 mysql_dissect_field_packet(tvbuff_t *tvb, int offset, proto_tree *tree, mysql_conn_data_t *conn_data _U_)
2015 offset = mysql_field_add_lestring(tvb, offset, tree, hf_mysql_fld_catalog);
2016 offset = mysql_field_add_lestring(tvb, offset, tree, hf_mysql_fld_db);
2017 offset = mysql_field_add_lestring(tvb, offset, tree, hf_mysql_fld_table);
2018 offset = mysql_field_add_lestring(tvb, offset, tree, hf_mysql_fld_org_table);
2019 offset = mysql_field_add_lestring(tvb, offset, tree, hf_mysql_fld_name);
2020 offset = mysql_field_add_lestring(tvb, offset, tree, hf_mysql_fld_org_name);
2021 offset +=1; /* filler */
2023 proto_tree_add_item(tree, hf_mysql_fld_charsetnr, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2024 offset += 2; /* charset */
2026 proto_tree_add_item(tree, hf_mysql_fld_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2027 offset += 4; /* length */
2029 proto_tree_add_item(tree, hf_mysql_fld_type, tvb, offset, 1, ENC_NA);
2030 offset += 1; /* type */
2032 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);
2033 offset += 2; /* flags */
2035 proto_tree_add_item(tree, hf_mysql_fld_decimals, tvb, offset, 1, ENC_NA);
2036 offset += 1; /* decimals */
2038 offset += 2; /* filler */
2040 /* default (Only use for show fields) */
2041 if (tree && tvb_reported_length_remaining(tvb, offset) > 0) {
2042 offset = mysql_field_add_lestring(tvb, offset, tree, hf_mysql_fld_default);
2049 mysql_dissect_row_packet(tvbuff_t *tvb, int offset, proto_tree *tree)
2051 while (tvb_reported_length_remaining(tvb, offset) > 0) {
2052 offset = mysql_field_add_lestring(tvb, offset, tree, hf_mysql_row_text);
2060 mysql_dissect_response_prepare(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, mysql_conn_data_t *conn_data)
2062 my_stmt_data_t *stmt_data;
2066 /* 0, marker for OK packet */
2068 proto_tree_add_item(tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2069 stmt_id = tvb_get_letohl(tvb, offset);
2071 proto_tree_add_item(tree, hf_mysql_num_fields, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2072 conn_data->stmt_num_fields = tvb_get_letohs(tvb, offset);
2074 proto_tree_add_item(tree, hf_mysql_num_params, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2075 conn_data->stmt_num_params = tvb_get_letohs(tvb, offset);
2076 stmt_data = wmem_new(wmem_file_scope(), struct my_stmt_data);
2077 stmt_data->nparam = conn_data->stmt_num_params;
2078 flagsize = (int)(sizeof(guint8) * stmt_data->nparam);
2079 stmt_data->param_flags = (guint8 *)wmem_alloc(wmem_file_scope(), flagsize);
2080 memset(stmt_data->param_flags, 0, flagsize);
2081 wmem_tree_insert32(conn_data->stmts, stmt_id, stmt_data);
2085 proto_tree_add_item(tree, hf_mysql_num_warn, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2087 if (conn_data->stmt_num_params > 0)
2088 mysql_set_conn_state(pinfo, conn_data, PREPARED_PARAMETERS);
2089 else if (conn_data->stmt_num_fields > 0)
2090 mysql_set_conn_state(pinfo, conn_data, PREPARED_FIELDS);
2092 mysql_set_conn_state(pinfo, conn_data, REQUEST);
2094 return offset + tvb_reported_length_remaining(tvb, offset);
2099 mysql_dissect_auth_switch_request(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, mysql_conn_data_t *conn_data _U_)
2103 col_set_str(pinfo->cinfo, COL_INFO, "Auth Switch Request" );
2104 mysql_set_conn_state(pinfo, conn_data, AUTH_SWITCH_RESPONSE);
2106 /* Status (Always 0xfe) */
2107 proto_tree_add_item(tree, hf_mysql_auth_switch_request_status, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2111 lenstr = my_tvb_strsize(tvb, offset);
2112 proto_tree_add_item(tree, hf_mysql_auth_switch_request_name, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
2116 lenstr = my_tvb_strsize(tvb, offset);
2117 proto_tree_add_item(tree, hf_mysql_auth_switch_request_data, tvb, offset, lenstr, ENC_NA);
2120 return offset + tvb_reported_length_remaining(tvb, offset);
2124 mysql_dissect_auth_switch_response(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, mysql_conn_data_t *conn_data _U_)
2128 col_set_str(pinfo->cinfo, COL_INFO, "Auth Switch Response" );
2131 lenstr = my_tvb_strsize(tvb, offset);
2132 proto_tree_add_item(tree, hf_mysql_auth_switch_response_data, tvb, offset, lenstr, ENC_NA);
2135 return offset + tvb_reported_length_remaining(tvb, offset);
2139 get length of string in packet buffer
2144 offset current offset
2147 deliver length of string, delimited by either \0 or end of buffer
2150 length of string found, including \0 (if present)
2154 my_tvb_strsize(tvbuff_t *tvb, int offset)
2156 gint len = tvb_strnlen(tvb, offset, -1);
2158 len = tvb_reported_length_remaining(tvb, offset);
2160 len++; /* the trailing \0 */
2166 read "field length encoded" value from packet buffer
2170 tvb in packet buffer
2171 offset in offset in buffer
2172 res out where to store FLE value, may be NULL
2173 is_null out where to store ISNULL flag, may be NULL
2176 read FLE from packet buffer and store its value and ISNULL flag
2177 in caller provided variables
2183 tvb_get_fle(tvbuff_t *tvb, int offset, guint64 *res, guint8 *is_null)
2187 prefix = tvb_get_guint8(tvb, offset);
2201 *res = tvb_get_letohs(tvb, offset+1);
2205 *res = tvb_get_letohl(tvb, offset+1);
2209 *res = tvb_get_letoh64(tvb, offset+1);
2219 /* dissector helper: length of PDU */
2221 get_mysql_pdu_len(packet_info *pinfo, tvbuff_t *tvb, int offset, void *data _U_)
2223 /* Regular packet header: length (3) + sequence number (1) */
2224 conversation_t *conversation;
2225 mysql_conn_data_t *conn_data;
2226 guint len = 4 + tvb_get_letoh24(tvb, offset);
2228 conversation = find_conversation_pinfo(pinfo, 0);
2230 conn_data = (mysql_conn_data_t *)conversation_get_proto_data(conversation, proto_mysql);
2231 if (conn_data && conn_data->compressed_state == MYSQL_COMPRESS_ACTIVE &&
2232 pinfo->num > conn_data->frame_start_compressed) {
2233 /* Compressed packet header includes uncompressed packet length (3) */
2241 /* dissector main function: handle one PDU */
2243 dissect_mysql_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2245 proto_tree *mysql_tree= NULL;
2247 conversation_t *conversation;
2249 guint packet_number;
2250 gboolean is_response, is_tls = FALSE;
2251 mysql_conn_data_t *conn_data;
2253 mysql_state_t conn_state_in, conn_state_out, frame_state;
2257 struct mysql_frame_data *mysql_frame_data_p;
2259 /* get conversation, create if necessary*/
2260 conversation= find_or_create_conversation(pinfo);
2262 /* get associated state information, create if necessary */
2263 conn_data= (mysql_conn_data_t *)conversation_get_proto_data(conversation, proto_mysql);
2265 conn_data= wmem_new(wmem_file_scope(), mysql_conn_data_t);
2266 conn_data->srv_caps= 0;
2267 conn_data->clnt_caps= 0;
2268 conn_data->clnt_caps_ext= 0;
2269 conn_data->state= UNDEFINED;
2270 conn_data->stmts= wmem_tree_new(wmem_file_scope());
2272 conn_data->generation= 0;
2274 conn_data->major_version= 0;
2275 conn_data->frame_start_ssl= 0;
2276 conn_data->frame_start_compressed= 0;
2277 conn_data->compressed_state= MYSQL_COMPRESS_NONE;
2278 conversation_add_proto_data(conversation, proto_mysql, conn_data);
2281 /* Using tvb_raw_offset(tvb) allows storage of multiple "proto data" in a single frame
2282 * (when there are multiple MySQL pdus in a single frame) */
2283 mysql_frame_data_p = (struct mysql_frame_data *)p_get_proto_data(wmem_file_scope(), pinfo, proto_mysql, tvb_raw_offset(tvb));
2284 if (!mysql_frame_data_p) {
2285 /* We haven't seen this frame before. Store the state of the
2286 * conversation now so if/when we dissect the frame again
2287 * we'll start with the same state.
2289 mysql_frame_data_p = wmem_new(wmem_file_scope(), struct mysql_frame_data);
2290 mysql_frame_data_p->state = conn_data->state;
2291 p_add_proto_data(wmem_file_scope(), pinfo, proto_mysql, tvb_raw_offset(tvb), mysql_frame_data_p);
2294 if ((conn_data->frame_start_compressed) && (pinfo->num > conn_data->frame_start_compressed)) {
2295 if (conn_data->compressed_state == MYSQL_COMPRESS_ACTIVE) {
2296 offset = mysql_dissect_compressed_header(tvb, offset, tree);
2300 ti = proto_tree_add_item(tree, proto_mysql, tvb, offset, -1, ENC_NA);
2301 mysql_tree = proto_item_add_subtree(ti, ett_mysql);
2302 proto_tree_add_item(mysql_tree, hf_mysql_packet_length, tvb, offset, 3, ENC_LITTLE_ENDIAN);
2305 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MySQL");
2307 if (pinfo->destport == pinfo->match_uint) {
2313 packet_number = tvb_get_guint8(tvb, offset);
2314 proto_tree_add_item(mysql_tree, hf_mysql_packet_number, tvb, offset, 1, ENC_NA);
2318 conn_state_in= conn_data->state;
2319 frame_state = mysql_frame_data_p->state;
2320 generation= conn_data->generation;
2322 pi = proto_tree_add_debug_text(mysql_tree, "conversation: %p", conversation);
2323 PROTO_ITEM_SET_GENERATED(pi);
2324 pi = proto_tree_add_debug_text(mysql_tree, "generation: %" G_GINT64_MODIFIER "d", generation);
2325 PROTO_ITEM_SET_GENERATED(pi);
2326 pi = proto_tree_add_debug_text(mysql_tree, "conn state: %s (%u)",
2327 val_to_str(conn_state_in, state_vals, "Unknown (%u)"),
2329 PROTO_ITEM_SET_GENERATED(pi);
2330 pi = proto_tree_add_debug_text(mysql_tree, "frame state: %s (%u)",
2331 val_to_str(frame_state, state_vals, "Unknown (%u)"),
2333 PROTO_ITEM_SET_GENERATED(pi);
2337 is_tls = proto_is_frame_protocol(pinfo->layers, "tls");
2340 if (packet_number == 0 && mysql_frame_data_p->state == UNDEFINED) {
2341 col_set_str(pinfo->cinfo, COL_INFO, "Server Greeting");
2342 offset = mysql_dissect_greeting(tvb, pinfo, offset, mysql_tree, conn_data);
2344 col_set_str(pinfo->cinfo, COL_INFO, "Response");
2345 offset = mysql_dissect_response(tvb, pinfo, offset, mysql_tree, conn_data, mysql_frame_data_p->state);
2348 if (mysql_frame_data_p->state == LOGIN && (packet_number == 1 || (packet_number == 2 && is_tls))) {
2349 col_set_str(pinfo->cinfo, COL_INFO, "Login Request");
2350 offset = mysql_dissect_login(tvb, pinfo, offset, mysql_tree, conn_data);
2351 if (conn_data->srv_caps & MYSQL_CAPS_CP) {
2352 if (conn_data->clnt_caps & MYSQL_CAPS_CP) {
2353 conn_data->frame_start_compressed = pinfo->num;
2354 conn_data->compressed_state = MYSQL_COMPRESS_INIT;
2358 col_set_str(pinfo->cinfo, COL_INFO, "Request");
2359 offset = mysql_dissect_request(tvb, pinfo, offset, mysql_tree, conn_data, mysql_frame_data_p->state);
2364 conn_state_out= conn_data->state;
2365 ++(conn_data->generation);
2366 pi = proto_tree_add_debug_text(mysql_tree, "next proto state: %s (%u)",
2367 val_to_str(conn_state_out, state_vals, "Unknown (%u)"),
2369 PROTO_ITEM_SET_GENERATED(pi);
2372 /* remaining payload indicates an error */
2373 if (tvb_reported_length_remaining(tvb, offset) > 0) {
2374 ti = proto_tree_add_item(mysql_tree, hf_mysql_payload, tvb, offset, -1, ENC_NA);
2375 expert_add_info(pinfo, ti, &ei_mysql_dissector_incomplete);
2378 return tvb_reported_length(tvb);
2381 /* dissector entrypoint, handles TCP-desegmentation */
2383 dissect_mysql(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
2385 tcp_dissect_pdus(tvb, pinfo, tree, mysql_desegment, 3,
2386 get_mysql_pdu_len, dissect_mysql_pdu, data);
2388 return tvb_reported_length(tvb);
2391 /* protocol registration */
2392 void proto_register_mysql(void)
2394 static hf_register_info hf[]=
2396 { &hf_mysql_packet_length,
2397 { "Packet Length", "mysql.packet_length",
2398 FT_UINT24, BASE_DEC, NULL, 0x0,
2401 { &hf_mysql_packet_number,
2402 { "Packet Number", "mysql.packet_number",
2403 FT_UINT8, BASE_DEC, NULL, 0x0,
2404 "Packet Number (now called: Sequence ID)", HFILL }},
2406 { &hf_mysql_request,
2407 { "Request Command", "mysql.request",
2408 FT_NONE, BASE_NONE, NULL, 0x0,
2411 { &hf_mysql_command,
2412 { "Command", "mysql.command",
2413 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &mysql_command_vals_ext, 0x0,
2416 { &hf_mysql_response_code,
2417 { "Response Code", "mysql.response_code",
2418 FT_UINT8, BASE_HEX, VALS(mysql_response_code_vals), 0x0,
2421 { &hf_mysql_error_code,
2422 { "Error Code", "mysql.error_code",
2423 FT_UINT16, BASE_DEC, NULL, 0x0,
2426 { &hf_mysql_error_string,
2427 { "Error message", "mysql.error.message",
2428 FT_STRING, BASE_NONE, NULL, 0x0,
2429 "Error string in case of MySQL error message", HFILL }},
2431 { &hf_mysql_sqlstate,
2432 { "SQL state", "mysql.sqlstate",
2433 FT_STRING, BASE_NONE, NULL, 0x0,
2436 { &hf_mysql_message,
2437 { "Message", "mysql.message",
2438 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2441 { &hf_mysql_server_greeting,
2442 { "Server Greeting", "mysql.server_greeting",
2443 FT_NONE, BASE_NONE, NULL, 0x0,
2446 { &hf_mysql_protocol,
2447 { "Protocol", "mysql.protocol",
2448 FT_UINT8, BASE_DEC, NULL, 0x0,
2449 "Protocol Version", HFILL }},
2451 { &hf_mysql_version,
2452 { "Version", "mysql.version",
2453 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2454 "MySQL Version", HFILL }},
2456 { &hf_mysql_session_track,
2457 { "Session Track", "mysql.session_track",
2458 FT_NONE, BASE_NONE, NULL, 0x0,
2461 { &hf_mysql_session_track_type,
2462 { "Session tracking type", "mysql.session_track.type",
2463 FT_UINT8, BASE_DEC, VALS(mysql_session_track_type_vals), 0x0,
2466 { &hf_mysql_session_track_length,
2467 { "Session tracking length", "mysql.session_track.length",
2468 FT_UINT64, BASE_DEC, NULL, 0x0,
2471 { &hf_mysql_session_track_data,
2472 { "Session tracking data", "mysql.session_track.data",
2473 FT_NONE, BASE_NONE, NULL, 0x0,
2476 { &hf_mysql_session_track_data_length,
2477 { "Session tracking data length", "mysql.session_track.data.length",
2478 FT_UINT64, BASE_DEC, NULL, 0x0,
2481 { &hf_mysql_session_track_sysvar_length,
2482 { "System variable change Length", "mysql.session_track.sysvar.length",
2483 FT_UINT64, BASE_DEC, NULL, 0x0,
2486 { &hf_mysql_session_track_sysvar_name,
2487 { "System variable change Name", "mysql.session_track.sysvar.name",
2488 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2491 { &hf_mysql_session_track_sysvar_value,
2492 { "System variable change Value", "mysql.session_track.sysvar.value",
2493 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2496 { &hf_mysql_session_track_schema_length,
2497 { "Schema change length", "mysql.session_track.schema.length",
2498 FT_UINT64, BASE_DEC, NULL, 0x0,
2501 { &hf_mysql_session_track_schema,
2502 { "Schema change", "mysql.session_track.schema",
2503 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2506 { &hf_mysql_session_state_change,
2507 { "State change", "mysql.session_track.state_change",
2508 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2511 { &hf_mysql_caps_server,
2512 { "Server Capabilities", "mysql.caps.server",
2513 FT_UINT16, BASE_HEX, NULL, 0x0,
2514 "MySQL Capabilities", HFILL }},
2516 { &hf_mysql_caps_client,
2517 { "Client Capabilities", "mysql.caps.client",
2518 FT_UINT16, BASE_HEX, NULL, 0x0,
2519 "MySQL Capabilities", HFILL }},
2521 { &hf_mysql_cap_long_password,
2522 { "Long Password","mysql.caps.lp",
2523 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_LP,
2526 { &hf_mysql_cap_found_rows,
2527 { "Found Rows","mysql.caps.fr",
2528 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_FR,
2531 { &hf_mysql_cap_long_flag,
2532 { "Long Column Flags","mysql.caps.lf",
2533 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_LF,
2536 { &hf_mysql_cap_connect_with_db,
2537 { "Connect With Database","mysql.caps.cd",
2538 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_CD,
2541 { &hf_mysql_cap_no_schema,
2542 { "Don't Allow database.table.column","mysql.caps.ns",
2543 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_NS,
2546 { &hf_mysql_cap_compress,
2547 { "Can use compression protocol","mysql.caps.cp",
2548 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_CP,
2551 { &hf_mysql_cap_odbc,
2552 { "ODBC Client","mysql.caps.ob",
2553 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_OB,
2556 { &hf_mysql_cap_local_files,
2557 { "Can Use LOAD DATA LOCAL","mysql.caps.li",
2558 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_LI,
2561 { &hf_mysql_cap_ignore_space,
2562 { "Ignore Spaces before '('","mysql.caps.is",
2563 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_IS,
2566 { &hf_mysql_cap_change_user,
2567 { "Speaks 4.1 protocol (new flag)","mysql.caps.cu",
2568 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_CU,
2571 { &hf_mysql_cap_interactive,
2572 { "Interactive Client","mysql.caps.ia",
2573 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_IA,
2576 { &hf_mysql_cap_ssl,
2577 { "Switch to SSL after handshake","mysql.caps.sl",
2578 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_SL,
2581 { &hf_mysql_cap_ignore_sigpipe,
2582 { "Ignore sigpipes","mysql.caps.ii",
2583 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_II,
2586 { &hf_mysql_cap_transactions,
2587 { "Knows about transactions","mysql.caps.ta",
2588 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_TA,
2591 { &hf_mysql_cap_reserved,
2592 { "Speaks 4.1 protocol (old flag)","mysql.caps.rs",
2593 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_RS,
2596 { &hf_mysql_cap_secure_connect,
2597 { "Can do 4.1 authentication","mysql.caps.sc",
2598 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_SC,
2601 { &hf_mysql_extcaps_server,
2602 { "Extended Server Capabilities", "mysql.extcaps.server",
2603 FT_UINT16, BASE_HEX, NULL, 0x0,
2604 "MySQL Extended Capabilities", HFILL }},
2606 { &hf_mysql_extcaps_client,
2607 { "Extended Client Capabilities", "mysql.extcaps.client",
2608 FT_UINT16, BASE_HEX, NULL, 0x0,
2609 "MySQL Extended Capabilities", HFILL }},
2611 { &hf_mysql_cap_multi_statements,
2612 { "Multiple statements","mysql.caps.ms",
2613 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_MS,
2616 { &hf_mysql_cap_multi_results,
2617 { "Multiple results","mysql.caps.mr",
2618 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_MR,
2621 { &hf_mysql_cap_ps_multi_results,
2622 { "PS Multiple results","mysql.caps.pm",
2623 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_PM,
2626 { &hf_mysql_cap_plugin_auth,
2627 { "Plugin Auth","mysql.caps.pa",
2628 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_PA,
2631 { &hf_mysql_cap_connect_attrs,
2632 { "Connect attrs","mysql.caps.ca",
2633 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_CA,
2636 { &hf_mysql_cap_plugin_auth_lenenc_client_data,
2637 { "Plugin Auth LENENC Client Data","mysql.caps.pm",
2638 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_AL,
2641 { &hf_mysql_cap_client_can_handle_expired_passwords,
2642 { "Client can handle expired passwords","mysql.caps.ep",
2643 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_EP,
2646 { &hf_mysql_cap_session_track,
2647 { "Session variable tracking","mysql.caps.session_track",
2648 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_ST,
2651 { &hf_mysql_cap_deprecate_eof,
2652 { "Deprecate EOF","mysql.caps.deprecate_eof",
2653 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_DE,
2656 { &hf_mysql_cap_unused,
2657 { "Unused","mysql.caps.unused",
2658 FT_UINT16, BASE_HEX, NULL, MYSQL_CAPS_UNUSED,
2661 { &hf_mysql_login_request,
2662 { "Login Request", "mysql.login_request",
2663 FT_NONE, BASE_NONE, NULL, 0x0,
2666 { &hf_mysql_max_packet,
2667 { "MAX Packet", "mysql.max_packet",
2668 FT_UINT24, BASE_DEC, NULL, 0x0,
2669 "MySQL Max packet", HFILL }},
2671 { &hf_mysql_charset,
2672 { "Charset", "mysql.charset",
2673 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &mysql_collation_vals_ext, 0x0,
2674 "MySQL Charset", HFILL }},
2676 { &hf_mysql_table_name,
2677 { "Table Name", "mysql.table_name",
2678 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2682 { "Username", "mysql.user",
2683 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2684 "Login Username", HFILL }},
2687 { "Schema", "mysql.schema",
2688 FT_STRING, BASE_NONE, NULL, 0x0,
2689 "Login Schema", HFILL }},
2691 { &hf_mysql_client_auth_plugin,
2692 { "Client Auth Plugin", "mysql.client_auth_plugin",
2693 FT_STRING, BASE_NONE, NULL, 0x0,
2696 { &hf_mysql_connattrs,
2697 { "Connection Attributes", "mysql.connattrs",
2698 FT_NONE, BASE_NONE, NULL, 0x0,
2701 { &hf_mysql_connattrs_length,
2702 { "Connection Attributes length", "mysql.connattrs.length",
2703 FT_UINT64, BASE_DEC, NULL, 0x0,
2706 { &hf_mysql_connattrs_attr,
2707 { "Connection Attribute", "mysql.connattrs.attr",
2708 FT_NONE, BASE_NONE, NULL, 0x0,
2711 { &hf_mysql_connattrs_name_length,
2712 { "Connection Attribute Name Length", "mysql.connattrs.name.length",
2713 FT_UINT64, BASE_DEC, NULL, 0x0,
2716 { &hf_mysql_connattrs_name,
2717 { "Connection Attribute Name", "mysql.connattrs.name",
2718 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2721 { &hf_mysql_connattrs_value_length,
2722 { "Connection Attribute Name Length", "mysql.connattrs.name.length",
2723 FT_UINT64, BASE_DEC, NULL, 0x0,
2726 { &hf_mysql_connattrs_value,
2727 { "Connection Attribute Value", "mysql.connattrs.value",
2728 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2732 { "Salt", "mysql.salt",
2733 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2737 { "Salt", "mysql.salt2",
2738 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2741 { &hf_mysql_auth_plugin_length,
2742 { "Authentication Plugin Length", "mysql.auth_plugin.length",
2743 FT_UINT8, BASE_DEC, NULL, 0x0,
2746 { &hf_mysql_auth_plugin,
2747 { "Authentication Plugin", "mysql.auth_plugin",
2748 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2751 { &hf_mysql_thread_id,
2752 { "Thread ID", "mysql.thread_id",
2753 FT_UINT32, BASE_DEC, NULL, 0x0,
2754 "MySQL Thread ID", HFILL }},
2756 { &hf_mysql_server_language,
2757 { "Server Language", "mysql.server_language",
2758 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &mysql_collation_vals_ext, 0x0,
2759 "MySQL Charset", HFILL }},
2761 { &hf_mysql_server_status,
2762 { "Server Status", "mysql.server_status",
2763 FT_UINT16, BASE_HEX, NULL, 0x0,
2764 "MySQL Status", HFILL }},
2766 { &hf_mysql_stat_it,
2767 { "In transaction", "mysql.stat.it",
2768 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_IT,
2771 { &hf_mysql_stat_ac,
2772 { "AUTO_COMMIT", "mysql.stat.ac",
2773 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_AC,
2776 { &hf_mysql_stat_mr,
2777 { "More results", "mysql.stat.mr",
2778 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_MR,
2781 { &hf_mysql_stat_mu,
2782 { "Multi query / Unused", "mysql.stat.mu",
2783 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_MU,
2784 "Multi query / Unused with MySQL >= 5.6", HFILL }},
2786 { &hf_mysql_stat_bi,
2787 { "Bad index used", "mysql.stat.bi",
2788 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_BI,
2791 { &hf_mysql_stat_ni,
2792 { "No index used", "mysql.stat.ni",
2793 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_NI,
2796 { &hf_mysql_stat_cr,
2797 { "Cursor exists", "mysql.stat.cr",
2798 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_CR,
2801 { &hf_mysql_stat_lr,
2802 { "Last row sent", "mysql.stat.lr",
2803 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_LR,
2806 { &hf_mysql_stat_dr,
2807 { "Database dropped", "mysql.stat.dr",
2808 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_DR,
2811 { &hf_mysql_stat_bs,
2812 { "No backslash escapes", "mysql.stat.bs",
2813 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_BS,
2816 { &hf_mysql_stat_mc,
2817 { "Metadata changed", "mysql.stat.mc",
2818 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_MC,
2821 { &hf_mysql_stat_session_state_changed,
2822 { "Session state changed", "mysql.stat.session_state_changed",
2823 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_SESSION_STATE_CHANGED,
2826 { &hf_mysql_stat_query_was_slow,
2827 { "Query was slow", "mysql.stat.query_was_slow",
2828 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_QUERY_WAS_SLOW,
2831 { &hf_mysql_stat_ps_out_params,
2832 { "PS Out Params", "mysql.stat.ps_out_params",
2833 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_PS_OUT_PARAMS,
2836 { &hf_mysql_stat_trans_readonly,
2837 { "In Trans Readonly", "mysql.stat.trans_readonly",
2838 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_TRANS_READONLY,
2841 { &hf_mysql_refresh,
2842 { "Refresh Option", "mysql.refresh",
2843 FT_UINT8, BASE_HEX, NULL, 0x0,
2846 { &hf_mysql_rfsh_grants,
2847 { "reload permissions", "mysql.rfsh.grants",
2848 FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_GRANT,
2851 { &hf_mysql_rfsh_log,
2852 { "flush logfiles", "mysql.rfsh.log",
2853 FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_LOG,
2856 { &hf_mysql_rfsh_tables,
2857 { "flush tables", "mysql.rfsh.tables",
2858 FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_TABLES,
2861 { &hf_mysql_rfsh_hosts,
2862 { "flush hosts", "mysql.rfsh.hosts",
2863 FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_HOSTS,
2866 { &hf_mysql_rfsh_status,
2867 { "reset statistics", "mysql.rfsh.status",
2868 FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_STATUS,
2871 { &hf_mysql_rfsh_threads,
2872 { "empty thread cache", "mysql.rfsh.threads",
2873 FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_THREADS,
2876 { &hf_mysql_rfsh_slave,
2877 { "flush slave status", "mysql.rfsh.slave",
2878 FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_SLAVE,
2881 { &hf_mysql_rfsh_master,
2882 { "flush master status", "mysql.rfsh.master",
2883 FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_MASTER,
2887 { "Unused", "mysql.unused",
2888 FT_BYTES, BASE_NONE, NULL, 0x0,
2892 { "Password", "mysql.passwd",
2893 FT_BYTES, BASE_NONE, NULL, 0x0,
2896 { &hf_mysql_payload,
2897 { "Payload", "mysql.payload",
2898 FT_BYTES, BASE_NONE, NULL, 0x0,
2899 "Additional Payload", HFILL }},
2901 { &hf_mysql_affected_rows,
2902 { "Affected Rows", "mysql.affected_rows",
2903 FT_UINT64, BASE_DEC, NULL, 0x0,
2906 { &hf_mysql_insert_id,
2907 { "Last INSERT ID", "mysql.insert_id",
2908 FT_UINT64, BASE_DEC, NULL, 0x0,
2911 { &hf_mysql_num_warn,
2912 { "Warnings", "mysql.warnings",
2913 FT_UINT16, BASE_DEC, NULL, 0x0,
2917 { "Thread ID", "mysql.thd_id",
2918 FT_UINT32, BASE_DEC, NULL, 0x0,
2921 { &hf_mysql_stmt_id,
2922 { "Statement ID", "mysql.stmt_id",
2923 FT_UINT32, BASE_DEC, NULL, 0x0,
2927 { "Statement", "mysql.query",
2928 FT_STRING, BASE_NONE, NULL, 0x0,
2931 { &hf_mysql_shutdown,
2932 { "Shutdown Level", "mysql.shutdown",
2933 FT_UINT8, BASE_DEC, VALS(mysql_shutdown_vals), 0x0,
2937 { "Option", "mysql.option",
2938 FT_UINT16, BASE_DEC, VALS(mysql_option_vals), 0x0,
2942 { "Parameter", "mysql.param",
2943 FT_UINT16, BASE_DEC, NULL, 0x0,
2946 { &hf_mysql_num_params,
2947 { "Number of parameter", "mysql.num_params",
2948 FT_UINT16, BASE_DEC, NULL, 0x0,
2951 { &hf_mysql_num_rows,
2952 { "Rows to fetch", "mysql.num_rows",
2953 FT_UINT32, BASE_DEC, NULL, 0x0,
2956 { &hf_mysql_exec_flags4,
2957 { "Flags (unused)", "mysql.exec_flags",
2958 FT_UINT8, BASE_DEC, NULL, 0x0,
2961 { &hf_mysql_exec_flags5,
2962 { "Flags", "mysql.exec_flags",
2963 FT_UINT8, BASE_DEC, VALS(mysql_exec_flags_vals), 0x0,
2966 { &hf_mysql_new_parameter_bound_flag,
2967 { "New parameter bound flag", "mysql.new_parameter_bound_flag",
2968 FT_UINT8, BASE_DEC, VALS(mysql_new_parameter_bound_flag_vals), 0x0,
2971 { &hf_mysql_exec_iter,
2972 { "Iterations (unused)", "mysql.exec_iter",
2973 FT_UINT32, BASE_DEC, NULL, 0x0,
2976 { &hf_mysql_binlog_position,
2977 { "Binlog Position", "mysql.binlog.position",
2978 FT_UINT32, BASE_DEC, NULL, 0x0,
2979 "Position to start at", HFILL }},
2981 { &hf_mysql_binlog_flags,
2982 { "Binlog Flags", "mysql.binlog.flags",
2983 FT_UINT16, BASE_HEX, NULL, 0x0,
2984 "(currently not used; always 0)", HFILL }},
2986 { &hf_mysql_binlog_server_id,
2987 { "Binlog server id", "mysql.binlog.server_id",
2988 FT_UINT16, BASE_HEX, NULL, 0x0,
2989 "server_id of the slave", HFILL }},
2991 { &hf_mysql_binlog_file_name,
2992 { "Binlog file name", "mysql.binlog.file_name",
2993 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2997 { "EOF marker", "mysql.eof",
2998 FT_UINT8, BASE_DEC, NULL, 0x0,
3001 { &hf_mysql_num_fields,
3002 { "Number of fields", "mysql.num_fields",
3003 FT_UINT64, BASE_DEC, NULL, 0x0,
3007 { "Extra data", "mysql.extra",
3008 FT_UINT64, BASE_DEC, NULL, 0x0,
3011 { &hf_mysql_fld_catalog,
3012 { "Catalog", "mysql.field.catalog",
3013 FT_STRING, BASE_NONE, NULL, 0x0,
3014 "Field: catalog", HFILL }},
3017 { "Database", "mysql.field.db",
3018 FT_STRING, BASE_NONE, NULL, 0x0,
3019 "Field: database", HFILL }},
3021 { &hf_mysql_fld_table,
3022 { "Table", "mysql.field.table",
3023 FT_STRING, BASE_NONE, NULL, 0x0,
3024 "Field: table", HFILL }},
3026 { &hf_mysql_fld_org_table,
3027 { "Original table", "mysql.field.org_table",
3028 FT_STRING, BASE_NONE, NULL, 0x0,
3029 "Field: original table", HFILL }},
3031 { &hf_mysql_fld_name,
3032 { "Name", "mysql.field.name",
3033 FT_STRING, BASE_NONE, NULL, 0x0,
3034 "Field: name", HFILL }},
3036 { &hf_mysql_fld_org_name,
3037 { "Original name", "mysql.field.org_name",
3038 FT_STRING, BASE_NONE, NULL, 0x0,
3039 "Field: original name", HFILL }},
3041 { &hf_mysql_fld_charsetnr,
3042 { "Charset number", "mysql.field.charsetnr",
3043 FT_UINT16, BASE_DEC|BASE_EXT_STRING, &mysql_collation_vals_ext, 0x0,
3044 "Field: charset number", HFILL }},
3046 { &hf_mysql_fld_length,
3047 { "Length", "mysql.field.length",
3048 FT_UINT32, BASE_DEC, NULL, 0x0,
3049 "Field: length", HFILL }},
3051 { &hf_mysql_fld_type,
3052 { "Type", "mysql.field.type",
3053 FT_UINT8, BASE_DEC, VALS(type_constants), 0x0,
3054 "Field: type", HFILL }},
3056 { &hf_mysql_fld_flags,
3057 { "Flags", "mysql.field.flags",
3058 FT_UINT16, BASE_HEX, NULL, 0x0,
3059 "Field: flags", HFILL }},
3061 { &hf_mysql_fld_not_null,
3062 { "Not null", "mysql.field.flags.not_null",
3063 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_NOT_NULL_FLAG,
3064 "Field: flag not null", HFILL }},
3066 { &hf_mysql_fld_primary_key,
3067 { "Primary key", "mysql.field.flags.primary_key",
3068 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_PRI_KEY_FLAG,
3069 "Field: flag primary key", HFILL }},
3071 { &hf_mysql_fld_unique_key,
3072 { "Unique key", "mysql.field.flags.unique_key",
3073 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_UNIQUE_KEY_FLAG,
3074 "Field: flag unique key", HFILL }},
3076 { &hf_mysql_fld_multiple_key,
3077 { "Multiple key", "mysql.field.flags.multiple_key",
3078 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_MULTIPLE_KEY_FLAG,
3079 "Field: flag multiple key", HFILL }},
3081 { &hf_mysql_fld_blob,
3082 { "Blob", "mysql.field.flags.blob",
3083 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_BLOB_FLAG,
3084 "Field: flag blob", HFILL }},
3086 { &hf_mysql_fld_unsigned,
3087 { "Unsigned", "mysql.field.flags.unsigned",
3088 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_UNSIGNED_FLAG,
3089 "Field: flag unsigned", HFILL }},
3091 { &hf_mysql_fld_zero_fill,
3092 { "Zero fill", "mysql.field.flags.zero_fill",
3093 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_ZEROFILL_FLAG,
3094 "Field: flag zero fill", HFILL }},
3096 { &hf_mysql_fld_binary,
3097 { "Binary", "mysql.field.flags.binary",
3098 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_BINARY_FLAG,
3099 "Field: flag binary", HFILL }},
3101 { &hf_mysql_fld_enum,
3102 { "Enum", "mysql.field.flags.enum",
3103 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_ENUM_FLAG,
3104 "Field: flag enum", HFILL }},
3106 { &hf_mysql_fld_auto_increment,
3107 { "Auto increment", "mysql.field.flags.auto_increment",
3108 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_AUTO_INCREMENT_FLAG,
3109 "Field: flag auto increment", HFILL }},
3111 { &hf_mysql_fld_timestamp,
3112 { "Timestamp", "mysql.field.flags.timestamp",
3113 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_TIMESTAMP_FLAG,
3114 "Field: flag timestamp", HFILL }},
3116 { &hf_mysql_fld_set,
3117 { "Set", "mysql.field.flags.set",
3118 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_FLD_SET_FLAG,
3119 "Field: flag set", HFILL }},
3121 { &hf_mysql_fld_decimals,
3122 { "Decimals", "mysql.field.decimals",
3123 FT_UINT8, BASE_DEC, NULL, 0x0,
3124 "Field: decimals", HFILL }},
3126 { &hf_mysql_fld_default,
3127 { "Default", "mysql.field.default",
3128 FT_STRING, BASE_NONE, NULL, 0x0,
3129 "Field: default", HFILL }},
3131 { &hf_mysql_row_text,
3132 { "text", "mysql.row.text",
3133 FT_STRING, BASE_NONE, NULL, 0x0,
3134 "Field: row packet text", HFILL }},
3136 { &hf_mysql_exec_param,
3137 { "Parameter", "mysql.exec_param",
3138 FT_NONE, BASE_NONE, NULL, 0x0,
3141 { &hf_mysql_exec_unsigned,
3142 { "Unsigned", "mysql.exec.unsigned",
3143 FT_UINT8, BASE_DEC, NULL, 0x0,
3146 { &hf_mysql_exec_field_longlong,
3147 { "Value", "mysql.exec.field.longlong",
3148 FT_INT64, BASE_DEC, NULL, 0x0,
3151 { &hf_mysql_exec_field_string,
3152 { "Value", "mysql.exec.field.string",
3153 FT_UINT_STRING, BASE_NONE, NULL, 0x0,
3156 { &hf_mysql_exec_field_double,
3157 { "Value", "mysql.exec.field.double",
3158 FT_DOUBLE, BASE_NONE, NULL, 0x0,
3161 { &hf_mysql_exec_field_datetime_length,
3162 { "Length", "mysql.exec.field.datetime.length",
3163 FT_INT8, BASE_DEC, NULL, 0x0,
3166 { &hf_mysql_exec_field_year,
3167 { "Year", "mysql.exec.field.year",
3168 FT_INT16, BASE_DEC, NULL, 0x0,
3171 { &hf_mysql_exec_field_month,
3172 { "Month", "mysql.exec.field.month",
3173 FT_INT8, BASE_DEC, NULL, 0x0,
3176 { &hf_mysql_exec_field_day,
3177 { "Day", "mysql.exec.field.day",
3178 FT_INT8, BASE_DEC, NULL, 0x0,
3181 { &hf_mysql_exec_field_hour,
3182 { "Hour", "mysql.exec.field.hour",
3183 FT_INT8, BASE_DEC, NULL, 0x0,
3186 { &hf_mysql_exec_field_minute,
3187 { "Minute", "mysql.exec.field.minute",
3188 FT_INT8, BASE_DEC, NULL, 0x0,
3191 { &hf_mysql_exec_field_second,
3192 { "Second", "mysql.exec.field.second",
3193 FT_INT8, BASE_DEC, NULL, 0x0,
3196 { &hf_mysql_exec_field_second_b,
3197 { "Billionth of a second", "mysql.exec.field.secondb",
3198 FT_INT32, BASE_DEC, NULL, 0x0,
3201 { &hf_mysql_exec_field_long,
3202 { "Value", "mysql.exec.field.long",
3203 FT_INT32, BASE_DEC, NULL, 0x0,
3206 { &hf_mysql_exec_field_tiny,
3207 { "Value", "mysql.exec.field.tiny",
3208 FT_INT8, BASE_DEC, NULL, 0x0,
3211 { &hf_mysql_exec_field_short,
3212 { "Value", "mysql.exec.field.short",
3213 FT_INT16, BASE_DEC, NULL, 0x0,
3216 { &hf_mysql_exec_field_float,
3217 { "Value", "mysql.exec.field.float",
3218 FT_FLOAT, BASE_NONE, NULL, 0x0,
3221 { &hf_mysql_exec_field_time_length,
3222 { "Length", "mysql.exec.field.time.length",
3223 FT_INT8, BASE_DEC, NULL, 0x0,
3226 { &hf_mysql_exec_field_time_sign,
3227 { "Flags", "mysql.exec.field.time.sign",
3228 FT_UINT8, BASE_DEC, VALS(mysql_exec_time_sign_vals), 0x0,
3231 { &hf_mysql_exec_field_time_days,
3232 { "Days", "mysql.exec.field.time.days",
3233 FT_INT32, BASE_DEC, NULL, 0x0,
3236 { &hf_mysql_auth_switch_request_status,
3237 { "Status", "mysql.auth_switch_request.status",
3238 FT_UINT8, BASE_HEX, NULL, 0x0,
3241 { &hf_mysql_auth_switch_request_name,
3242 { "Auth Method Name", "mysql.auth_switch_request.name",
3243 FT_STRING, BASE_NONE, NULL, 0x0,
3246 { &hf_mysql_auth_switch_request_data,
3247 { "Auth Method Data", "mysql.auth_switch_request.data",
3248 FT_BYTES, BASE_NONE, NULL, 0x0,
3251 { &hf_mysql_auth_switch_response_data,
3252 { "Auth Method Data", "mysql.auth_switch_response.data",
3253 FT_BYTES, BASE_NONE, NULL, 0x0,
3256 { &hf_mysql_compressed_packet_length,
3257 { "Compressed Packet Length", "mysql.compressed_packet_length",
3258 FT_UINT24, BASE_DEC, NULL, 0x0,
3261 { &hf_mysql_compressed_packet_number,
3262 { "Compressed Packet Number", "mysql.compressed_packet_number",
3263 FT_UINT24, BASE_DEC, NULL, 0x0,
3266 { &hf_mysql_compressed_packet_length_uncompressed,
3267 { "Uncompressed Packet Length", "mysql.compressed_packet_length_uncompressed",
3268 FT_UINT24, BASE_DEC, NULL, 0x0,
3275 &ett_server_greeting,
3285 &ett_session_track_data,
3290 static ei_register_info ei[] = {
3291 { &ei_mysql_dissector_incomplete, { "mysql.dissector_incomplete", PI_UNDECODED, PI_WARN, "FIXME - dissector is incomplete", EXPFILL }},
3292 { &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 }},
3293 { &ei_mysql_prepare_response_needed, { "mysql.prepare_response_needed", PI_UNDECODED, PI_WARN, "PREPARE Response packet is needed to dissect the payload", EXPFILL }},
3294 { &ei_mysql_command, { "mysql.command.invalid", PI_PROTOCOL, PI_WARN, "Unknown/invalid command code", EXPFILL }},
3295 { &ei_mysql_eof, { "mysql.eof.wrong_state", PI_PROTOCOL, PI_WARN, "EOF Marker found while connection in wrong state.", EXPFILL }},
3296 { &ei_mysql_unknown_response, { "mysql.unknown_response", PI_UNDECODED, PI_WARN, "unknown/invalid response", EXPFILL }},
3299 module_t *mysql_module;
3300 expert_module_t* expert_mysql;
3302 proto_mysql = proto_register_protocol("MySQL Protocol", "MySQL", "mysql");
3303 proto_register_field_array(proto_mysql, hf, array_length(hf));
3304 proto_register_subtree_array(ett, array_length(ett));
3305 expert_mysql = expert_register_protocol(proto_mysql);
3306 expert_register_field_array(expert_mysql, ei, array_length(ei));
3308 mysql_module = prefs_register_protocol(proto_mysql, NULL);
3309 prefs_register_bool_preference(mysql_module, "desegment_buffers",
3310 "Reassemble MySQL buffers spanning multiple TCP segments",
3311 "Whether the MySQL dissector should reassemble MySQL buffers spanning multiple TCP segments."
3312 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
3314 prefs_register_bool_preference(mysql_module, "show_sql_query",
3315 "Show SQL Query string in INFO column",
3316 "Whether the MySQL dissector should display the SQL query string in the INFO column.",
3319 mysql_handle = register_dissector("mysql", dissect_mysql, proto_mysql);
3322 /* dissector registration */
3323 void proto_reg_handoff_mysql(void)
3325 tls_handle = find_dissector("tls");
3326 dissector_add_uint_with_preference("tcp.port", TCP_PORT_MySQL, mysql_handle);
3330 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3335 * indent-tabs-mode: t
3338 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
3339 * :indentSize=8:tabSize=8:noTabs=false: