2 * Routines for mysql packet dissection
4 * Huagang XIE <huagang@intruvert.com>
6 * MySQL 4.1+ protocol by Axel Schwenke <axel@mysql.com>
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * Copied from packet-tftp.c
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 * the protocol spec at
32 * http://public.logicacmg.com/~redferni/mysql/MySQL-Protocol.html
33 * http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol
34 * and MySQL source code
37 /* create extra output for conversation tracking */
38 /* #define CTDEBUG 1 */
42 #include <epan/packet.h>
43 #include <epan/conversation.h>
44 #include <epan/wmem/wmem.h>
46 #include <epan/dissectors/packet-tcp.h>
47 #include <epan/prefs.h>
48 #include <epan/expert.h>
50 /* port for protocol registration */
51 #define TCP_PORT_MySQL 3306
53 /* client/server capabilities */
54 #define MYSQL_CAPS_LP 0x0001
55 #define MYSQL_CAPS_FR 0x0002
56 #define MYSQL_CAPS_LF 0x0004
57 #define MYSQL_CAPS_CD 0x0008
58 #define MYSQL_CAPS_NS 0x0010
59 #define MYSQL_CAPS_CP 0x0020
60 #define MYSQL_CAPS_OB 0x0040
61 #define MYSQL_CAPS_LI 0x0080
62 #define MYSQL_CAPS_IS 0x0100
63 #define MYSQL_CAPS_CU 0x0200
64 #define MYSQL_CAPS_IA 0x0400
65 #define MYSQL_CAPS_SL 0x0800
66 #define MYSQL_CAPS_II 0x1000
67 #define MYSQL_CAPS_TA 0x2000
68 #define MYSQL_CAPS_RS 0x4000
69 #define MYSQL_CAPS_SC 0x8000
72 #define MYSQL_FLD_NOT_NULL_FLAG 0x0001
73 #define MYSQL_FLD_PRI_KEY_FLAG 0x0002
74 #define MYSQL_FLD_UNIQUE_KEY_FLAG 0x0004
75 #define MYSQL_FLD_MULTIPLE_KEY_FLAG 0x0008
76 #define MYSQL_FLD_BLOB_FLAG 0x0010
77 #define MYSQL_FLD_UNSIGNED_FLAG 0x0020
78 #define MYSQL_FLD_ZEROFILL_FLAG 0x0040
79 #define MYSQL_FLD_BINARY_FLAG 0x0080
80 #define MYSQL_FLD_ENUM_FLAG 0x0100
81 #define MYSQL_FLD_AUTO_INCREMENT_FLAG 0x0200
82 #define MYSQL_FLD_TIMESTAMP_FLAG 0x0400
83 #define MYSQL_FLD_SET_FLAG 0x0800
85 /* extended capabilities: 4.1+ client only */
86 #define MYSQL_CAPS_MS 0x0001
87 #define MYSQL_CAPS_MR 0x0002
90 #define MYSQL_STAT_IT 0x0001
91 #define MYSQL_STAT_AC 0x0002
92 #define MYSQL_STAT_MR 0x0004
93 #define MYSQL_STAT_MU 0x0008
94 #define MYSQL_STAT_BI 0x0010
95 #define MYSQL_STAT_NI 0x0020
96 #define MYSQL_STAT_CR 0x0040
97 #define MYSQL_STAT_LR 0x0080
98 #define MYSQL_STAT_DR 0x0100
99 #define MYSQL_STAT_BS 0x0200
101 /* bitfield for MYSQL_REFRESH */
102 #define MYSQL_RFSH_GRANT 1 /* Refresh grant tables */
103 #define MYSQL_RFSH_LOG 2 /* Start on new log file */
104 #define MYSQL_RFSH_TABLES 4 /* close all tables */
105 #define MYSQL_RFSH_HOSTS 8 /* Flush host cache */
106 #define MYSQL_RFSH_STATUS 16 /* Flush status variables */
107 #define MYSQL_RFSH_THREADS 32 /* Flush thread cache */
108 #define MYSQL_RFSH_SLAVE 64 /* Reset master info and restart slave thread */
109 #define MYSQL_RFSH_MASTER 128 /* Remove all bin logs in the index and truncate the index */
111 /* MySQL command codes */
112 #define MYSQL_SLEEP 0 /* not from client */
114 #define MYSQL_INIT_DB 2
115 #define MYSQL_QUERY 3
116 #define MYSQL_FIELD_LIST 4
117 #define MYSQL_CREATE_DB 5
118 #define MYSQL_DROP_DB 6
119 #define MYSQL_REFRESH 7
120 #define MYSQL_SHUTDOWN 8
121 #define MYSQL_STATISTICS 9
122 #define MYSQL_PROCESS_INFO 10
123 #define MYSQL_CONNECT 11 /* not from client */
124 #define MYSQL_PROCESS_KILL 12
125 #define MYSQL_DEBUG 13
126 #define MYSQL_PING 14
127 #define MYSQL_TIME 15 /* not from client */
128 #define MYSQL_DELAY_INSERT 16 /* not from client */
129 #define MYSQL_CHANGE_USER 17
130 #define MYSQL_BINLOG_DUMP 18 /* replication */
131 #define MYSQL_TABLE_DUMP 19 /* replication */
132 #define MYSQL_CONNECT_OUT 20 /* replication */
133 #define MYSQL_REGISTER_SLAVE 21 /* replication */
134 #define MYSQL_STMT_PREPARE 22
135 #define MYSQL_STMT_EXECUTE 23
136 #define MYSQL_STMT_SEND_LONG_DATA 24
137 #define MYSQL_STMT_CLOSE 25
138 #define MYSQL_STMT_RESET 26
139 #define MYSQL_SET_OPTION 27
140 #define MYSQL_STMT_FETCH 28
142 /* MySQL cursor types */
144 #define MYSQL_CURSOR_TYPE_NO_CURSOR 0
145 #define MYSQL_CURSOR_TYPE_READ_ONLY 1
146 #define MYSQL_CURSOR_TYPE_FOR_UPDATE 2
147 #define MYSQL_CURSOR_TYPE_SCROLLABLE 4
149 /* MySQL parameter flags -- used internally by the dissector */
151 #define MYSQL_PARAM_FLAG_STREAMED 0x01
153 /* decoding table: command */
154 static const value_string mysql_command_vals
[] = {
155 {MYSQL_SLEEP
, "SLEEP"},
156 {MYSQL_QUIT
, "Quit"},
157 {MYSQL_INIT_DB
, "Use Database"},
158 {MYSQL_QUERY
, "Query"},
159 {MYSQL_FIELD_LIST
, "Show Fields"},
160 {MYSQL_CREATE_DB
, "Create Database"},
161 {MYSQL_DROP_DB
, "Drop Database"},
162 {MYSQL_REFRESH
, "Refresh"},
163 {MYSQL_SHUTDOWN
, "Shutdown"},
164 {MYSQL_STATISTICS
, "Statistics"},
165 {MYSQL_PROCESS_INFO
, "Process List"},
166 {MYSQL_CONNECT
, "Connect"},
167 {MYSQL_PROCESS_KILL
, "Kill Server Thread"},
168 {MYSQL_DEBUG
, "Dump Debuginfo"},
169 {MYSQL_PING
, "Ping"},
170 {MYSQL_TIME
, "Time"},
171 {MYSQL_DELAY_INSERT
, "Insert Delayed"},
172 {MYSQL_CHANGE_USER
, "Change User"},
173 {MYSQL_BINLOG_DUMP
, "Send Binlog"},
174 {MYSQL_TABLE_DUMP
, "Send Table"},
175 {MYSQL_CONNECT_OUT
, "Slave Connect"},
176 {MYSQL_REGISTER_SLAVE
, "Register Slave"},
177 {MYSQL_STMT_PREPARE
, "Prepare Statement"},
178 {MYSQL_STMT_EXECUTE
, "Execute Statement"},
179 {MYSQL_STMT_SEND_LONG_DATA
, "Send BLOB"},
180 {MYSQL_STMT_CLOSE
, "Close Statement"},
181 {MYSQL_STMT_RESET
, "Reset Statement"},
182 {MYSQL_SET_OPTION
, "Set Option"},
183 {MYSQL_STMT_FETCH
, "Fetch Data"},
187 /* decoding table: exec_flags */
188 static const value_string mysql_exec_flags_vals
[] = {
189 {MYSQL_CURSOR_TYPE_NO_CURSOR
, "Defaults"},
190 {MYSQL_CURSOR_TYPE_READ_ONLY
, "Read-only cursor"},
191 {MYSQL_CURSOR_TYPE_FOR_UPDATE
, "Cursor for update"},
192 {MYSQL_CURSOR_TYPE_SCROLLABLE
, "Scrollable cursor"},
196 /* decoding table: new_parameter_bound_flag */
197 static const value_string mysql_new_parameter_bound_flag_vals
[] = {
198 {0, "Subsequent call"},
199 {1, "First call or rebound"},
203 /* decoding table: exec_time_sign */
204 static const value_string mysql_exec_time_sign_vals
[] = {
211 /* charset: pre-4.1 used the term 'charset', later changed to 'collation' */
212 static const value_string mysql_charset_vals
[] = {
248 /* collation codes may change over time, recreate with the following SQL
250 SELECT CONCAT(' {', ID, ',"', CHARACTER_SET_NAME, ' COLLATE ', COLLATION_NAME, '"},')
251 FROM INFORMATION_SCHEMA.COLLATIONS
253 INTO OUTFILE '/tmp/mysql-collations';
256 static const value_string mysql_collation_vals
[] = {
257 {3, "dec8 COLLATE dec8_swedish_ci"},
258 {4, "cp850 COLLATE cp850_general_ci"},
259 {5, "latin1 COLLATE latin1_german1_ci"},
260 {6, "hp8 COLLATE hp8_english_ci"},
261 {7, "koi8r COLLATE koi8r_general_ci"},
262 {8, "latin1 COLLATE latin1_swedish_ci"},
263 {9, "latin2 COLLATE latin2_general_ci"},
264 {10, "swe7 COLLATE swe7_swedish_ci"},
265 {11, "ascii COLLATE ascii_general_ci"},
266 {14, "cp1251 COLLATE cp1251_bulgarian_ci"},
267 {15, "latin1 COLLATE latin1_danish_ci"},
268 {16, "hebrew COLLATE hebrew_general_ci"},
269 {20, "latin7 COLLATE latin7_estonian_cs"},
270 {21, "latin2 COLLATE latin2_hungarian_ci"},
271 {22, "koi8u COLLATE koi8u_general_ci"},
272 {23, "cp1251 COLLATE cp1251_ukrainian_ci"},
273 {25, "greek COLLATE greek_general_ci"},
274 {26, "cp1250 COLLATE cp1250_general_ci"},
275 {27, "latin2 COLLATE latin2_croatian_ci"},
276 {29, "cp1257 COLLATE cp1257_lithuanian_ci"},
277 {30, "latin5 COLLATE latin5_turkish_ci"},
278 {31, "latin1 COLLATE latin1_german2_ci"},
279 {32, "armscii8 COLLATE armscii8_general_ci"},
280 {33, "utf8 COLLATE utf8_general_ci"},
281 {36, "cp866 COLLATE cp866_general_ci"},
282 {37, "keybcs2 COLLATE keybcs2_general_ci"},
283 {38, "macce COLLATE macce_general_ci"},
284 {39, "macroman COLLATE macroman_general_ci"},
285 {40, "cp852 COLLATE cp852_general_ci"},
286 {41, "latin7 COLLATE latin7_general_ci"},
287 {42, "latin7 COLLATE latin7_general_cs"},
288 {43, "macce COLLATE macce_bin"},
289 {44, "cp1250 COLLATE cp1250_croatian_ci"},
290 {47, "latin1 COLLATE latin1_bin"},
291 {48, "latin1 COLLATE latin1_general_ci"},
292 {49, "latin1 COLLATE latin1_general_cs"},
293 {50, "cp1251 COLLATE cp1251_bin"},
294 {51, "cp1251 COLLATE cp1251_general_ci"},
295 {52, "cp1251 COLLATE cp1251_general_cs"},
296 {53, "macroman COLLATE macroman_bin"},
297 {57, "cp1256 COLLATE cp1256_general_ci"},
298 {58, "cp1257 COLLATE cp1257_bin"},
299 {59, "cp1257 COLLATE cp1257_general_ci"},
300 {63, "binary COLLATE binary"},
301 {64, "armscii8 COLLATE armscii8_bin"},
302 {65, "ascii COLLATE ascii_bin"},
303 {66, "cp1250 COLLATE cp1250_bin"},
304 {67, "cp1256 COLLATE cp1256_bin"},
305 {68, "cp866 COLLATE cp866_bin"},
306 {69, "dec8 COLLATE dec8_bin"},
307 {70, "greek COLLATE greek_bin"},
308 {71, "hebrew COLLATE hebrew_bin"},
309 {72, "hp8 COLLATE hp8_bin"},
310 {73, "keybcs2 COLLATE keybcs2_bin"},
311 {74, "koi8r COLLATE koi8r_bin"},
312 {75, "koi8u COLLATE koi8u_bin"},
313 {77, "latin2 COLLATE latin2_bin"},
314 {78, "latin5 COLLATE latin5_bin"},
315 {79, "latin7 COLLATE latin7_bin"},
316 {80, "cp850 COLLATE cp850_bin"},
317 {81, "cp852 COLLATE cp852_bin"},
318 {82, "swe7 COLLATE swe7_bin"},
319 {83, "utf8 COLLATE utf8_bin"},
320 {92, "geostd8 COLLATE geostd8_general_ci"},
321 {93, "geostd8 COLLATE geostd8_bin"},
322 {94, "latin1 COLLATE latin1_spanish_ci"},
323 {99, "cp1250 COLLATE cp1250_polish_ci"},
324 {192, "utf8 COLLATE utf8_unicode_ci"},
325 {193, "utf8 COLLATE utf8_icelandic_ci"},
326 {194, "utf8 COLLATE utf8_latvian_ci"},
327 {195, "utf8 COLLATE utf8_romanian_ci"},
328 {196, "utf8 COLLATE utf8_slovenian_ci"},
329 {197, "utf8 COLLATE utf8_polish_ci"},
330 {198, "utf8 COLLATE utf8_estonian_ci"},
331 {199, "utf8 COLLATE utf8_spanish_ci"},
332 {200, "utf8 COLLATE utf8_swedish_ci"},
333 {201, "utf8 COLLATE utf8_turkish_ci"},
334 {202, "utf8 COLLATE utf8_czech_ci"},
335 {203, "utf8 COLLATE utf8_danish_ci"},
336 {204, "utf8 COLLATE utf8_lithuanian_ci"},
337 {205, "utf8 COLLATE utf8_slovak_ci"},
338 {206, "utf8 COLLATE utf8_spanish2_ci"},
339 {207, "utf8 COLLATE utf8_roman_ci"},
340 {208, "utf8 COLLATE utf8_persian_ci"},
341 {209, "utf8 COLLATE utf8_esperanto_ci"},
342 {210, "utf8 COLLATE utf8_hungarian_ci"},
347 /* allowed MYSQL_SHUTDOWN levels */
348 static const value_string mysql_shutdown_vals
[] = {
350 {1, "wait for connections to finish"},
351 {2, "wait for transactions to finish"},
352 {8, "wait for updates to finish"},
353 {16, "wait flush all buffers"},
354 {17, "wait flush critical buffers"},
355 {254, "kill running queries"},
356 {255, "kill connections"},
361 /* allowed MYSQL_SET_OPTION values */
362 static const value_string mysql_option_vals
[] = {
363 {0, "multi statements on"},
364 {1, "multi statements off"},
369 static int proto_mysql
= -1;
371 /* dissector configuration */
372 static gboolean mysql_desegment
= TRUE
;
373 static gboolean mysql_showquery
= FALSE
;
375 /* expand-the-tree flags */
376 static gint ett_mysql
= -1;
377 static gint ett_server_greeting
= -1;
378 static gint ett_login_request
= -1;
379 static gint ett_caps
= -1;
380 static gint ett_extcaps
= -1;
381 static gint ett_stat
= -1;
382 static gint ett_request
= -1;
383 static gint ett_refresh
= -1;
384 static gint ett_field_flags
= -1;
385 static gint ett_exec_param
= -1;
387 /* protocol fields */
388 static int hf_mysql_caps_server
= -1;
389 static int hf_mysql_caps_client
= -1;
390 static int hf_mysql_cap_long_password
= -1;
391 static int hf_mysql_cap_found_rows
= -1;
392 static int hf_mysql_cap_long_flag
= -1;
393 static int hf_mysql_cap_connect_with_db
= -1;
394 static int hf_mysql_cap_no_schema
= -1;
395 static int hf_mysql_cap_compress
= -1;
396 static int hf_mysql_cap_odbc
= -1;
397 static int hf_mysql_cap_local_files
= -1;
398 static int hf_mysql_cap_ignore_space
= -1;
399 static int hf_mysql_cap_change_user
= -1;
400 static int hf_mysql_cap_interactive
= -1;
401 static int hf_mysql_cap_ssl
= -1;
402 static int hf_mysql_cap_ignore_sigpipe
= -1;
403 static int hf_mysql_cap_transactions
= -1;
404 static int hf_mysql_cap_reserved
= -1;
405 static int hf_mysql_cap_secure_connect
= -1;
406 static int hf_mysql_extcaps_client
= -1;
407 static int hf_mysql_cap_multi_statements
= -1;
408 static int hf_mysql_cap_multi_results
= -1;
409 static int hf_mysql_server_language
= -1;
410 static int hf_mysql_server_status
= -1;
411 static int hf_mysql_stat_it
= -1;
412 static int hf_mysql_stat_ac
= -1;
413 static int hf_mysql_stat_mr
= -1;
414 static int hf_mysql_stat_mu
= -1;
415 static int hf_mysql_stat_bi
= -1;
416 static int hf_mysql_stat_ni
= -1;
417 static int hf_mysql_stat_cr
= -1;
418 static int hf_mysql_stat_lr
= -1;
419 static int hf_mysql_stat_dr
= -1;
420 static int hf_mysql_stat_bs
= -1;
421 static int hf_mysql_refresh
= -1;
422 static int hf_mysql_rfsh_grants
= -1;
423 static int hf_mysql_rfsh_log
= -1;
424 static int hf_mysql_rfsh_tables
= -1;
425 static int hf_mysql_rfsh_hosts
= -1;
426 static int hf_mysql_rfsh_status
= -1;
427 static int hf_mysql_rfsh_threads
= -1;
428 static int hf_mysql_rfsh_slave
= -1;
429 static int hf_mysql_rfsh_master
= -1;
430 static int hf_mysql_packet_length
= -1;
431 static int hf_mysql_packet_number
= -1;
432 static int hf_mysql_request
= -1;
433 static int hf_mysql_command
= -1;
434 static int hf_mysql_error_code
= -1;
435 static int hf_mysql_error_string
= -1;
436 static int hf_mysql_sqlstate
= -1;
437 static int hf_mysql_message
= -1;
438 static int hf_mysql_payload
= -1;
439 static int hf_mysql_server_greeting
= -1;
440 static int hf_mysql_protocol
= -1;
441 static int hf_mysql_version
= -1;
442 static int hf_mysql_login_request
= -1;
443 static int hf_mysql_max_packet
= -1;
444 static int hf_mysql_user
= -1;
445 static int hf_mysql_table_name
= -1;
446 static int hf_mysql_schema
= -1;
447 static int hf_mysql_thread_id
= -1;
448 static int hf_mysql_salt
= -1;
449 static int hf_mysql_salt2
= -1;
450 static int hf_mysql_charset
= -1;
451 static int hf_mysql_passwd
= -1;
452 static int hf_mysql_unused
= -1;
453 static int hf_mysql_affected_rows
= -1;
454 static int hf_mysql_insert_id
= -1;
455 static int hf_mysql_num_warn
= -1;
456 static int hf_mysql_thd_id
= -1;
457 static int hf_mysql_stmt_id
= -1;
458 static int hf_mysql_query
= -1;
459 static int hf_mysql_shutdown
= -1;
460 static int hf_mysql_option
= -1;
461 static int hf_mysql_num_rows
= -1;
462 static int hf_mysql_param
= -1;
463 static int hf_mysql_num_params
= -1;
464 static int hf_mysql_exec_flags4
= -1;
465 static int hf_mysql_exec_flags5
= -1;
466 static int hf_mysql_exec_iter
= -1;
467 static int hf_mysql_binlog_position
= -1;
468 static int hf_mysql_binlog_flags
= -1;
469 static int hf_mysql_binlog_server_id
= -1;
470 static int hf_mysql_binlog_file_name
= -1;
471 static int hf_mysql_eof
= -1;
472 static int hf_mysql_num_fields
= -1;
473 static int hf_mysql_extra
= -1;
474 static int hf_mysql_fld_catalog
= -1;
475 static int hf_mysql_fld_db
= -1;
476 static int hf_mysql_fld_table
= -1;
477 static int hf_mysql_fld_org_table
= -1;
478 static int hf_mysql_fld_name
= -1;
479 static int hf_mysql_fld_org_name
= -1;
480 static int hf_mysql_fld_charsetnr
= -1;
481 static int hf_mysql_fld_length
= -1;
482 static int hf_mysql_fld_type
= -1;
483 static int hf_mysql_fld_flags
= -1;
484 static int hf_mysql_fld_not_null
= -1;
485 static int hf_mysql_fld_primary_key
= -1;
486 static int hf_mysql_fld_unique_key
= -1;
487 static int hf_mysql_fld_multiple_key
= -1;
488 static int hf_mysql_fld_blob
= -1;
489 static int hf_mysql_fld_unsigned
= -1;
490 static int hf_mysql_fld_zero_fill
= -1;
491 static int hf_mysql_fld_binary
= -1;
492 static int hf_mysql_fld_enum
= -1;
493 static int hf_mysql_fld_auto_increment
= -1;
494 static int hf_mysql_fld_timestamp
= -1;
495 static int hf_mysql_fld_set
= -1;
496 static int hf_mysql_fld_decimals
= -1;
497 static int hf_mysql_fld_default
= -1;
498 static int hf_mysql_row_text
= -1;
499 static int hf_mysql_new_parameter_bound_flag
= -1;
500 static int hf_mysql_exec_param
= -1;
501 static int hf_mysql_exec_unsigned
= -1;
502 static int hf_mysql_exec_field_longlong
= -1;
503 static int hf_mysql_exec_field_string
= -1;
504 static int hf_mysql_exec_field_double
= -1;
505 static int hf_mysql_exec_field_datetime_length
= -1;
506 static int hf_mysql_exec_field_year
= -1;
507 static int hf_mysql_exec_field_month
= -1;
508 static int hf_mysql_exec_field_day
= -1;
509 static int hf_mysql_exec_field_hour
= -1;
510 static int hf_mysql_exec_field_minute
= -1;
511 static int hf_mysql_exec_field_second
= -1;
512 static int hf_mysql_exec_field_second_b
= -1;
513 static int hf_mysql_exec_field_long
= -1;
514 static int hf_mysql_exec_field_tiny
= -1;
515 static int hf_mysql_exec_field_short
= -1;
516 static int hf_mysql_exec_field_float
= -1;
517 static int hf_mysql_exec_field_time_length
= -1;
518 static int hf_mysql_exec_field_time_sign
= -1;
519 static int hf_mysql_exec_field_time_days
= -1;
521 static expert_field ei_mysql_eof
= EI_INIT
;
522 static expert_field ei_mysql_dissector_incomplete
= EI_INIT
;
523 static expert_field ei_mysql_streamed_param
= EI_INIT
;
524 static expert_field ei_mysql_prepare_response_needed
= EI_INIT
;
525 static expert_field ei_mysql_unknown_response
= EI_INIT
;
526 static expert_field ei_mysql_command
= EI_INIT
;
529 static const value_string type_constants
[] = {
530 {0x00, "FIELD_TYPE_DECIMAL" },
531 {0x01, "FIELD_TYPE_TINY" },
532 {0x02, "FIELD_TYPE_SHORT" },
533 {0x03, "FIELD_TYPE_LONG" },
534 {0x04, "FIELD_TYPE_FLOAT" },
535 {0x05, "FIELD_TYPE_DOUBLE" },
536 {0x06, "FIELD_TYPE_NULL" },
537 {0x07, "FIELD_TYPE_TIMESTAMP" },
538 {0x08, "FIELD_TYPE_LONGLONG" },
539 {0x09, "FIELD_TYPE_INT24" },
540 {0x0a, "FIELD_TYPE_DATE" },
541 {0x0b, "FIELD_TYPE_TIME" },
542 {0x0c, "FIELD_TYPE_DATETIME" },
543 {0x0d, "FIELD_TYPE_YEAR" },
544 {0x0e, "FIELD_TYPE_NEWDATE" },
545 {0x0f, "FIELD_TYPE_VARCHAR" },
546 {0x10, "FIELD_TYPE_BIT" },
547 {0xf6, "FIELD_TYPE_NEWDECIMAL" },
548 {0xf7, "FIELD_TYPE_ENUM" },
549 {0xf8, "FIELD_TYPE_SET" },
550 {0xf9, "FIELD_TYPE_TINY_BLOB" },
551 {0xfa, "FIELD_TYPE_MEDIUM_BLOB"},
552 {0xfb, "FIELD_TYPE_LONG_BLOB" },
553 {0xfc, "FIELD_TYPE_BLOB" },
554 {0xfd, "FIELD_TYPE_VAR_STRING" },
555 {0xfe, "FIELD_TYPE_STRING" },
556 {0xff, "FIELD_TYPE_GEOMETRY" },
560 typedef enum mysql_state
{
567 RESPONSE_SHOW_FIELDS
,
576 static const value_string state_vals
[] = {
577 {UNDEFINED
, "undefined"},
579 {REQUEST
, "request"},
580 {RESPONSE_OK
, "response OK"},
581 {RESPONSE_MESSAGE
, "response message"},
582 {RESPONSE_TABULAR
, "tabular response"},
583 {RESPONSE_SHOW_FIELDS
, "response to SHOW FIELDS"},
584 {FIELD_PACKET
, "field packet"},
585 {ROW_PACKET
, "row packet"},
586 {RESPONSE_PREPARE
, "response to PREPARE"},
587 {RESPONSE_PARAMETERS
, "parameters in response to PREPARE"},
588 {RESPONSE_FIELDS
, "fields in response to PREPARE"},
593 typedef struct mysql_conn_data
{
596 guint16 clnt_caps_ext
;
598 guint16 stmt_num_params
;
599 guint16 stmt_num_fields
;
604 guint8 major_version
;
607 struct mysql_frame_data
{
611 typedef struct my_stmt_data
{
616 typedef struct mysql_exec_dissector
{
618 guint8 unsigned_flag
;
619 void (*dissector
)(tvbuff_t
*tvb
, int *param_offset
, proto_item
*field_tree
);
620 } mysql_exec_dissector_t
;
622 /* function prototypes */
623 static int mysql_dissect_error_packet(tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, proto_tree
*tree
);
624 static int mysql_dissect_ok_packet(tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, proto_tree
*tree
, mysql_conn_data_t
*conn_data
);
625 static int mysql_dissect_server_status(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
);
626 static int mysql_dissect_caps_server(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
, guint16
*caps
);
627 static int mysql_dissect_caps_client(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
, guint16
*caps
);
628 static int mysql_dissect_ext_caps_client(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
, guint16
*caps
);
629 static int mysql_dissect_result_header(tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, proto_tree
*tree
, mysql_conn_data_t
*conn_data
);
630 static int mysql_dissect_field_packet(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
, mysql_conn_data_t
*conn_data
);
631 static int mysql_dissect_row_packet(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
);
632 static int mysql_dissect_response_prepare(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
, mysql_conn_data_t
*conn_data
);
633 static void mysql_dissect_exec_string(tvbuff_t
*tvb
, int *param_offset
, proto_item
*field_tree
);
634 static void mysql_dissect_exec_datetime(tvbuff_t
*tvb
, int *param_offset
, proto_item
*field_tree
);
635 static void mysql_dissect_exec_tiny(tvbuff_t
*tvb
, int *param_offset
, proto_item
*field_tree
);
636 static void mysql_dissect_exec_short(tvbuff_t
*tvb
, int *param_offset
, proto_item
*field_tree
);
637 static void mysql_dissect_exec_long(tvbuff_t
*tvb
, int *param_offset
, proto_item
*field_tree
);
638 static void mysql_dissect_exec_float(tvbuff_t
*tvb
, int *param_offset
, proto_item
*field_tree
);
639 static void mysql_dissect_exec_double(tvbuff_t
*tvb
, int *param_offset
, proto_item
*field_tree
);
640 static void mysql_dissect_exec_longlong(tvbuff_t
*tvb
, int *param_offset
, proto_item
*field_tree
);
641 static void mysql_dissect_exec_null(tvbuff_t
*tvb
, int *param_offset
, proto_item
*field_tree
);
642 static char mysql_dissect_exec_param(proto_item
*req_tree
, tvbuff_t
*tvb
, int *offset
,
643 int *param_offset
, guint8 param_flags
, packet_info
*pinfo
);
644 static void mysql_dissect_exec_primitive(tvbuff_t
*tvb
, int *param_offset
,
645 proto_item
*field_tree
, const int hfindex
, const int offset
);
646 static void mysql_dissect_exec_time(tvbuff_t
*tvb
, int *param_offset
, proto_item
*field_tree
);
648 static gint
my_tvb_strsize(tvbuff_t
*tvb
, int offset
);
649 static int tvb_get_fle(tvbuff_t
*tvb
, int offset
, guint64
*res
, guint8
*is_null
);
651 static const mysql_exec_dissector_t mysql_exec_dissectors
[] = {
652 { 0x01, 0, mysql_dissect_exec_tiny
},
653 { 0x02, 0, mysql_dissect_exec_short
},
654 { 0x03, 0, mysql_dissect_exec_long
},
655 { 0x04, 0, mysql_dissect_exec_float
},
656 { 0x05, 0, mysql_dissect_exec_double
},
657 { 0x06, 0, mysql_dissect_exec_null
},
658 { 0x07, 0, mysql_dissect_exec_datetime
},
659 { 0x08, 0, mysql_dissect_exec_longlong
},
660 { 0x0a, 0, mysql_dissect_exec_datetime
},
661 { 0x0b, 0, mysql_dissect_exec_time
},
662 { 0x0c, 0, mysql_dissect_exec_datetime
},
663 { 0xf6, 0, mysql_dissect_exec_string
},
664 { 0xfc, 0, mysql_dissect_exec_string
},
665 { 0xfd, 0, mysql_dissect_exec_string
},
666 { 0xfe, 0, mysql_dissect_exec_string
},
671 mysql_dissect_greeting(tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
,
672 proto_tree
*tree
, mysql_conn_data_t
*conn_data
)
679 proto_item
*greeting_tree
= NULL
;
681 protocol
= tvb_get_guint8(tvb
, offset
);
683 if (protocol
== 0xff) {
684 return mysql_dissect_error_packet(tvb
, pinfo
, offset
+1, tree
);
687 conn_data
->state
= LOGIN
;
689 tf
= proto_tree_add_item(tree
, hf_mysql_server_greeting
, tvb
, offset
, -1, ENC_NA
);
690 greeting_tree
= proto_item_add_subtree(tf
, ett_server_greeting
);
692 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " proto=%d", protocol
) ;
694 proto_tree_add_item(greeting_tree
, hf_mysql_protocol
, tvb
, offset
, 1, ENC_NA
);
699 lenstr
= tvb_strsize(tvb
,offset
);
700 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " version=%s", tvb_get_string(wmem_packet_scope(), tvb
, offset
, lenstr
));
702 proto_tree_add_item(greeting_tree
, hf_mysql_version
, tvb
, offset
, lenstr
, ENC_ASCII
|ENC_NA
);
703 conn_data
->major_version
= 0;
704 for (ver_offset
= 0; ver_offset
< lenstr
; ver_offset
++) {
705 guint8 ver_char
= tvb_get_guint8(tvb
, offset
+ ver_offset
);
706 if (ver_char
== '.') break;
707 conn_data
->major_version
= conn_data
->major_version
* 10 + ver_char
- '0';
711 /* 4 bytes little endian thread_id */
712 proto_tree_add_item(greeting_tree
, hf_mysql_thread_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
716 lenstr
= tvb_strsize(tvb
,offset
);
717 proto_tree_add_item(greeting_tree
, hf_mysql_salt
, tvb
, offset
, lenstr
, ENC_ASCII
|ENC_NA
);
720 /* rest is optional */
721 if (!tvb_reported_length_remaining(tvb
, offset
)) return offset
;
724 offset
= mysql_dissect_caps_server(tvb
, offset
, greeting_tree
, &conn_data
->srv_caps
);
726 /* rest is optional */
727 if (!tvb_reported_length_remaining(tvb
, offset
)) return offset
;
729 proto_tree_add_item(greeting_tree
, hf_mysql_server_language
, tvb
, offset
, 1, ENC_NA
);
730 offset
+= 1; /* for charset */
732 offset
= mysql_dissect_server_status(tvb
, offset
, greeting_tree
);
734 /* 13 bytes unused */
735 proto_tree_add_item(greeting_tree
, hf_mysql_unused
, tvb
, offset
, 13, ENC_ASCII
|ENC_NA
);
738 /* 4.1+ server: rest of salt */
739 if (tvb_reported_length_remaining(tvb
, offset
)) {
740 lenstr
= tvb_strsize(tvb
,offset
);
741 proto_tree_add_item(greeting_tree
, hf_mysql_salt2
, tvb
, offset
, lenstr
, ENC_ASCII
|ENC_NA
);
750 mysql_dissect_login(tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
,
751 proto_tree
*tree
, mysql_conn_data_t
*conn_data
)
756 proto_item
*login_tree
= NULL
;
758 /* after login there can be OK or DENIED */
759 conn_data
->state
= RESPONSE_OK
;
762 tf
= proto_tree_add_item(tree
, hf_mysql_login_request
, tvb
, offset
, -1, ENC_NA
);
763 login_tree
= proto_item_add_subtree(tf
, ett_login_request
);
766 offset
= mysql_dissect_caps_client(tvb
, offset
, login_tree
, &conn_data
->clnt_caps
);
768 if (conn_data
->clnt_caps
& MYSQL_CAPS_CU
) /* 4.1 protocol */
770 offset
= mysql_dissect_ext_caps_client(tvb
, offset
, login_tree
, &conn_data
->clnt_caps_ext
);
772 proto_tree_add_item(login_tree
, hf_mysql_max_packet
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
775 proto_tree_add_item(login_tree
, hf_mysql_charset
, tvb
, offset
, 1, ENC_NA
);
776 offset
+= 1; /* for charset */
778 offset
+= 23; /* filler bytes */
780 } else { /* pre-4.1 */
781 proto_tree_add_item(login_tree
, hf_mysql_max_packet
, tvb
, offset
, 3, ENC_LITTLE_ENDIAN
);
786 lenstr
= my_tvb_strsize(tvb
, offset
);
787 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " user=%s", tvb_get_string(wmem_packet_scope(), tvb
, offset
, lenstr
));
788 proto_tree_add_item(login_tree
, hf_mysql_user
, tvb
, offset
, lenstr
, ENC_ASCII
|ENC_NA
);
791 /* rest is optional */
792 if (!tvb_reported_length_remaining(tvb
, offset
)) return offset
;
794 /* password: asciiz or length+ascii */
795 if (conn_data
->clnt_caps
& MYSQL_CAPS_SC
) {
796 lenstr
= tvb_get_guint8(tvb
, offset
);
799 lenstr
= my_tvb_strsize(tvb
, offset
);
801 if (tree
&& lenstr
> 1) {
802 proto_tree_add_item(login_tree
, hf_mysql_passwd
, tvb
, offset
, lenstr
, ENC_NA
);
806 /* optional: initial schema */
807 if (conn_data
->clnt_caps
& MYSQL_CAPS_CD
)
809 lenstr
= my_tvb_strsize(tvb
,offset
);
814 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " db=%s", tvb_get_string(wmem_packet_scope(), tvb
, offset
, lenstr
));
816 proto_tree_add_item(login_tree
, hf_mysql_schema
, tvb
, offset
, lenstr
, ENC_ASCII
|ENC_NA
);
825 mysql_dissect_exec_string(tvbuff_t
*tvb
, int *param_offset
, proto_item
*field_tree
)
830 param_len
= tvb_get_guint8(tvb
, *param_offset
);
833 case 0xfc: /* 252 - 64k chars */
835 param_len32
= tvb_get_letohs(tvb
, *param_offset
);
836 proto_tree_add_item(field_tree
, hf_mysql_exec_field_string
,
837 tvb
, *param_offset
, 2, ENC_ASCII
| ENC_LITTLE_ENDIAN
);
838 *param_offset
+= param_len32
+ 2;
840 case 0xfd: /* 64k - 16M chars */
842 param_len32
= tvb_get_letoh24(tvb
, *param_offset
);
843 proto_tree_add_item(field_tree
, hf_mysql_exec_field_string
,
844 tvb
, *param_offset
, 3, ENC_ASCII
| ENC_LITTLE_ENDIAN
);
845 *param_offset
+= param_len32
+ 3;
847 default: /* < 252 chars */
848 proto_tree_add_item(field_tree
, hf_mysql_exec_field_string
,
849 tvb
, *param_offset
, 1, ENC_ASCII
| ENC_NA
);
850 *param_offset
+= param_len
+ 1;
856 mysql_dissect_exec_time(tvbuff_t
*tvb
, int *param_offset
, proto_item
*field_tree
)
860 param_len
= tvb_get_guint8(tvb
, *param_offset
);
861 proto_tree_add_item(field_tree
, hf_mysql_exec_field_time_length
,
862 tvb
, *param_offset
, 1, ENC_NA
);
864 if (param_len
>= 1) {
865 proto_tree_add_item(field_tree
, hf_mysql_exec_field_time_sign
,
866 tvb
, *param_offset
, 1, ENC_NA
);
868 if (param_len
>= 5) {
869 proto_tree_add_item(field_tree
, hf_mysql_exec_field_time_days
,
870 tvb
, *param_offset
+ 1, 4, ENC_LITTLE_ENDIAN
);
872 if (param_len
>= 8) {
873 proto_tree_add_item(field_tree
, hf_mysql_exec_field_hour
,
874 tvb
, *param_offset
+ 5, 1, ENC_NA
);
875 proto_tree_add_item(field_tree
, hf_mysql_exec_field_minute
,
876 tvb
, *param_offset
+ 6, 1, ENC_NA
);
877 proto_tree_add_item(field_tree
, hf_mysql_exec_field_second
,
878 tvb
, *param_offset
+ 7, 1, ENC_NA
);
880 if (param_len
>= 12) {
881 proto_tree_add_item(field_tree
, hf_mysql_exec_field_second_b
,
882 tvb
, *param_offset
+ 8, 4, ENC_LITTLE_ENDIAN
);
884 *param_offset
+= param_len
;
888 mysql_dissect_exec_datetime(tvbuff_t
*tvb
, int *param_offset
, proto_item
*field_tree
)
892 param_len
= tvb_get_guint8(tvb
, *param_offset
);
893 proto_tree_add_item(field_tree
, hf_mysql_exec_field_datetime_length
,
894 tvb
, *param_offset
, 1, ENC_NA
);
896 if (param_len
>= 2) {
897 proto_tree_add_item(field_tree
, hf_mysql_exec_field_year
,
898 tvb
, *param_offset
, 2, ENC_LITTLE_ENDIAN
);
900 if (param_len
>= 4) {
901 proto_tree_add_item(field_tree
, hf_mysql_exec_field_month
,
902 tvb
, *param_offset
+ 2, 1, ENC_NA
);
903 proto_tree_add_item(field_tree
, hf_mysql_exec_field_day
,
904 tvb
, *param_offset
+ 3, 1, ENC_NA
);
906 if (param_len
>= 7) {
907 proto_tree_add_item(field_tree
, hf_mysql_exec_field_hour
,
908 tvb
, *param_offset
+ 4, 1, ENC_NA
);
909 proto_tree_add_item(field_tree
, hf_mysql_exec_field_minute
,
910 tvb
, *param_offset
+ 5, 1, ENC_NA
);
911 proto_tree_add_item(field_tree
, hf_mysql_exec_field_second
,
912 tvb
, *param_offset
+ 6, 1, ENC_NA
);
914 if (param_len
>= 11) {
915 proto_tree_add_item(field_tree
, hf_mysql_exec_field_second_b
,
916 tvb
, *param_offset
+ 7, 4, ENC_LITTLE_ENDIAN
);
918 *param_offset
+= param_len
;
922 mysql_dissect_exec_primitive(tvbuff_t
*tvb
, int *param_offset
,
923 proto_item
*field_tree
, const int hfindex
,
926 proto_tree_add_item(field_tree
, hfindex
, tvb
,
927 *param_offset
, offset
, ENC_LITTLE_ENDIAN
);
928 *param_offset
+= offset
;
932 mysql_dissect_exec_tiny(tvbuff_t
*tvb
, int *param_offset
, proto_item
*field_tree
)
934 mysql_dissect_exec_primitive(tvb
, param_offset
, field_tree
, hf_mysql_exec_field_tiny
, 1);
938 mysql_dissect_exec_short(tvbuff_t
*tvb
, int *param_offset
, proto_item
*field_tree
)
940 mysql_dissect_exec_primitive(tvb
, param_offset
, field_tree
, hf_mysql_exec_field_short
, 2);
944 mysql_dissect_exec_long(tvbuff_t
*tvb
, int *param_offset
, proto_item
*field_tree
)
946 mysql_dissect_exec_primitive(tvb
, param_offset
, field_tree
, hf_mysql_exec_field_long
, 4);
950 mysql_dissect_exec_float(tvbuff_t
*tvb
, int *param_offset
, proto_item
*field_tree
)
952 mysql_dissect_exec_primitive(tvb
, param_offset
, field_tree
, hf_mysql_exec_field_float
, 4);
956 mysql_dissect_exec_double(tvbuff_t
*tvb
, int *param_offset
, proto_item
*field_tree
)
958 mysql_dissect_exec_primitive(tvb
, param_offset
, field_tree
, hf_mysql_exec_field_double
, 8);
962 mysql_dissect_exec_longlong(tvbuff_t
*tvb
, int *param_offset
, proto_item
*field_tree
)
964 mysql_dissect_exec_primitive(tvb
, param_offset
, field_tree
, hf_mysql_exec_field_longlong
, 8);
968 mysql_dissect_exec_null(tvbuff_t
*tvb _U_
, int *param_offset _U_
, proto_item
*field_tree _U_
)
972 mysql_dissect_exec_param(proto_item
*req_tree
, tvbuff_t
*tvb
, int *offset
,
973 int *param_offset
, guint8 param_flags
,
976 guint8 param_type
, param_unsigned
;
978 proto_item
*field_tree
;
979 int dissector_index
= 0;
981 tf
= proto_tree_add_item(req_tree
, hf_mysql_exec_param
, tvb
, *offset
, 2, ENC_NA
);
982 field_tree
= proto_item_add_subtree(tf
, ett_stat
);
983 proto_tree_add_item(field_tree
, hf_mysql_fld_type
, tvb
, *offset
, 1, ENC_NA
);
984 param_type
= tvb_get_guint8(tvb
, *offset
);
985 *offset
+= 1; /* type */
986 proto_tree_add_item(field_tree
, hf_mysql_exec_unsigned
, tvb
, *offset
, 1, ENC_NA
);
987 param_unsigned
= tvb_get_guint8(tvb
, *offset
);
988 *offset
+= 1; /* signedness */
989 if ((param_flags
& MYSQL_PARAM_FLAG_STREAMED
) == MYSQL_PARAM_FLAG_STREAMED
) {
990 expert_add_info(pinfo
, field_tree
, &ei_mysql_streamed_param
);
993 while (mysql_exec_dissectors
[dissector_index
].dissector
!= NULL
) {
994 if (mysql_exec_dissectors
[dissector_index
].type
== param_type
&&
995 mysql_exec_dissectors
[dissector_index
].unsigned_flag
== param_unsigned
) {
996 mysql_exec_dissectors
[dissector_index
].dissector(tvb
, param_offset
, field_tree
);
1005 mysql_dissect_request(tvbuff_t
*tvb
,packet_info
*pinfo
, int offset
,
1006 proto_tree
*tree
, mysql_conn_data_t
*conn_data
)
1010 proto_item
*tf
= NULL
, *ti
;
1011 proto_item
*req_tree
= NULL
;
1013 my_stmt_data_t
*stmt_data
;
1014 int stmt_pos
, param_offset
;
1017 tf
= proto_tree_add_item(tree
, hf_mysql_request
, tvb
, offset
, 1, ENC_NA
);
1018 req_tree
= proto_item_add_subtree(tf
, ett_request
);
1021 opcode
= tvb_get_guint8(tvb
, offset
);
1022 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " %s", val_to_str(opcode
, mysql_command_vals
, "Unknown (%u)"));
1024 proto_tree_add_item(req_tree
, hf_mysql_command
, tvb
, offset
, 1, ENC_NA
);
1025 proto_item_append_text(tf
, " %s", val_to_str(opcode
, mysql_command_vals
, "Unknown (%u)"));
1034 case MYSQL_PROCESS_INFO
:
1035 conn_data
->state
= RESPONSE_TABULAR
;
1040 conn_data
->state
= RESPONSE_OK
;
1043 case MYSQL_STATISTICS
:
1044 conn_data
->state
= RESPONSE_MESSAGE
;
1048 case MYSQL_CREATE_DB
:
1050 lenstr
= my_tvb_strsize(tvb
, offset
);
1051 proto_tree_add_item(req_tree
, hf_mysql_schema
, tvb
, offset
, lenstr
, ENC_ASCII
|ENC_NA
);
1053 conn_data
->state
= RESPONSE_OK
;
1057 lenstr
= my_tvb_strsize(tvb
, offset
);
1058 proto_tree_add_item(req_tree
, hf_mysql_query
, tvb
, offset
, lenstr
, ENC_ASCII
|ENC_NA
);
1059 if (mysql_showquery
) {
1060 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " { %s } ", tvb_get_string(wmem_packet_scope(), tvb
, offset
, lenstr
));
1063 conn_data
->state
= RESPONSE_TABULAR
;
1066 case MYSQL_STMT_PREPARE
:
1067 lenstr
= my_tvb_strsize(tvb
, offset
);
1068 proto_tree_add_item(req_tree
, hf_mysql_query
, tvb
, offset
, lenstr
, ENC_ASCII
|ENC_NA
);
1070 conn_data
->state
= RESPONSE_PREPARE
;
1073 case MYSQL_STMT_CLOSE
:
1074 proto_tree_add_item(req_tree
, hf_mysql_stmt_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1076 conn_data
->state
= REQUEST
;
1079 case MYSQL_STMT_RESET
:
1080 proto_tree_add_item(req_tree
, hf_mysql_stmt_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1082 conn_data
->state
= RESPONSE_OK
;
1085 case MYSQL_FIELD_LIST
:
1086 lenstr
= my_tvb_strsize(tvb
, offset
);
1087 proto_tree_add_item(req_tree
, hf_mysql_table_name
, tvb
, offset
, lenstr
, ENC_ASCII
|ENC_NA
);
1089 conn_data
->state
= RESPONSE_SHOW_FIELDS
;
1092 case MYSQL_PROCESS_KILL
:
1093 proto_tree_add_item(req_tree
, hf_mysql_thd_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1095 conn_data
->state
= RESPONSE_OK
;
1098 case MYSQL_CHANGE_USER
:
1099 lenstr
= tvb_strsize(tvb
, offset
);
1100 proto_tree_add_item(req_tree
, hf_mysql_user
, tvb
, offset
, lenstr
, ENC_ASCII
|ENC_NA
);
1103 lenstr
= tvb_strsize(tvb
, offset
);
1104 proto_tree_add_item(req_tree
, hf_mysql_passwd
, tvb
, offset
, lenstr
, ENC_NA
);
1107 lenstr
= my_tvb_strsize(tvb
, offset
);
1108 proto_tree_add_item(req_tree
, hf_mysql_schema
, tvb
, offset
, lenstr
, ENC_ASCII
|ENC_NA
);
1111 conn_data
->state
= RESPONSE_OK
;
1117 proto_item
*rfsh_tree
;
1119 tff
= proto_tree_add_item(req_tree
, hf_mysql_refresh
, tvb
, offset
, 1, ENC_NA
);
1120 rfsh_tree
= proto_item_add_subtree(tff
, ett_refresh
);
1121 proto_tree_add_item(rfsh_tree
, hf_mysql_rfsh_grants
, tvb
, offset
, 1, ENC_NA
);
1122 proto_tree_add_item(rfsh_tree
, hf_mysql_rfsh_log
, tvb
, offset
, 1, ENC_NA
);
1123 proto_tree_add_item(rfsh_tree
, hf_mysql_rfsh_tables
, tvb
, offset
, 1, ENC_NA
);
1124 proto_tree_add_item(rfsh_tree
, hf_mysql_rfsh_hosts
, tvb
, offset
, 1, ENC_NA
);
1125 proto_tree_add_item(rfsh_tree
, hf_mysql_rfsh_status
, tvb
, offset
, 1, ENC_NA
);
1126 proto_tree_add_item(rfsh_tree
, hf_mysql_rfsh_threads
, tvb
, offset
, 1, ENC_NA
);
1127 proto_tree_add_item(rfsh_tree
, hf_mysql_rfsh_slave
, tvb
, offset
, 1, ENC_NA
);
1128 proto_tree_add_item(rfsh_tree
, hf_mysql_rfsh_master
, tvb
, offset
, 1, ENC_NA
);
1132 conn_data
->state
= RESPONSE_OK
;
1135 case MYSQL_SHUTDOWN
:
1136 proto_tree_add_item(req_tree
, hf_mysql_shutdown
, tvb
, offset
, 1, ENC_NA
);
1138 conn_data
->state
= RESPONSE_OK
;
1141 case MYSQL_SET_OPTION
:
1142 proto_tree_add_item(req_tree
, hf_mysql_option
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1144 conn_data
->state
= RESPONSE_OK
;
1147 case MYSQL_STMT_FETCH
:
1148 proto_tree_add_item(req_tree
, hf_mysql_stmt_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1151 proto_tree_add_item(req_tree
, hf_mysql_num_rows
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1153 conn_data
->state
= RESPONSE_TABULAR
;
1156 case MYSQL_STMT_SEND_LONG_DATA
:
1157 proto_tree_add_item(req_tree
, hf_mysql_stmt_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1158 stmt_id
= tvb_get_letohl(tvb
, offset
);
1161 stmt_data
= (my_stmt_data_t
*)wmem_tree_lookup32(conn_data
->stmts
, stmt_id
);
1162 if (stmt_data
!= NULL
) {
1163 guint16 data_param
= tvb_get_letohs(tvb
, offset
);
1164 if (stmt_data
->nparam
> data_param
) {
1165 stmt_data
->param_flags
[data_param
] |= MYSQL_PARAM_FLAG_STREAMED
;
1169 proto_tree_add_item(req_tree
, hf_mysql_param
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1173 lenstr
= tvb_reported_length_remaining(tvb
, offset
);
1174 if (tree
&& lenstr
> 0) {
1175 proto_tree_add_item(req_tree
, hf_mysql_payload
, tvb
, offset
, lenstr
, ENC_NA
);
1178 conn_data
->state
= REQUEST
;
1181 case MYSQL_STMT_EXECUTE
:
1182 proto_tree_add_item(req_tree
, hf_mysql_stmt_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1183 stmt_id
= tvb_get_letohl(tvb
, offset
);
1186 if (conn_data
->major_version
>= 5) {
1187 proto_tree_add_item(req_tree
, hf_mysql_exec_flags5
, tvb
, offset
, 1, ENC_NA
);
1189 proto_tree_add_item(req_tree
, hf_mysql_exec_flags4
, tvb
, offset
, 1, ENC_NA
);
1193 proto_tree_add_item(req_tree
, hf_mysql_exec_iter
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1196 stmt_data
= (my_stmt_data_t
*)wmem_tree_lookup32(conn_data
->stmts
, stmt_id
);
1197 if (stmt_data
!= NULL
) {
1198 if (stmt_data
->nparam
!= 0) {
1200 offset
+= (stmt_data
->nparam
+ 7) / 8; /* NULL bitmap */
1201 proto_tree_add_item(req_tree
, hf_mysql_new_parameter_bound_flag
, tvb
, offset
, 1, ENC_NA
);
1202 stmt_bound
= tvb_get_guint8(tvb
, offset
);
1204 if (stmt_bound
== 1) {
1205 param_offset
= offset
+ stmt_data
->nparam
* 2;
1206 for (stmt_pos
= 0; stmt_pos
< stmt_data
->nparam
; stmt_pos
++) {
1207 if (!mysql_dissect_exec_param(req_tree
, tvb
, &offset
, ¶m_offset
,
1208 stmt_data
->param_flags
[stmt_pos
], pinfo
))
1211 offset
= param_offset
;
1215 lenstr
= tvb_reported_length_remaining(tvb
, offset
);
1216 if (tree
&& lenstr
> 0) {
1217 ti
= proto_tree_add_item(req_tree
, hf_mysql_payload
, tvb
, offset
, lenstr
, ENC_NA
);
1218 expert_add_info(pinfo
, ti
, &ei_mysql_prepare_response_needed
);
1223 /* FIXME: rest needs metadata about statement */
1225 lenstr
= tvb_reported_length_remaining(tvb
, offset
);
1226 if (tree
&& lenstr
> 0) {
1227 ti
= proto_tree_add_item(req_tree
, hf_mysql_payload
, tvb
, offset
, lenstr
, ENC_NA
);
1228 expert_add_info_format(pinfo
, ti
, &ei_mysql_dissector_incomplete
, "FIXME: execute dissector incomplete");
1232 conn_data
->state
= RESPONSE_TABULAR
;
1235 case MYSQL_BINLOG_DUMP
:
1236 proto_tree_add_item(req_tree
, hf_mysql_binlog_position
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1239 proto_tree_add_item(req_tree
, hf_mysql_binlog_flags
, tvb
, offset
, 2, ENC_NA
);
1242 proto_tree_add_item(req_tree
, hf_mysql_binlog_server_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1245 /* binlog file name ? */
1246 lenstr
= tvb_reported_length_remaining(tvb
, offset
);
1247 if (tree
&& lenstr
> 0) {
1248 proto_tree_add_item(req_tree
, hf_mysql_binlog_file_name
, tvb
, offset
, lenstr
, ENC_ASCII
|ENC_NA
);
1252 conn_data
->state
= REQUEST
;
1254 /* FIXME: implement replication packets */
1255 case MYSQL_TABLE_DUMP
:
1256 case MYSQL_CONNECT_OUT
:
1257 case MYSQL_REGISTER_SLAVE
:
1258 ti
= proto_tree_add_item(req_tree
, hf_mysql_payload
, tvb
, offset
, -1, ENC_NA
);
1259 expert_add_info_format(pinfo
, ti
, &ei_mysql_dissector_incomplete
, "FIXME: implement replication packets");
1260 offset
+= tvb_reported_length_remaining(tvb
, offset
);
1261 conn_data
->state
= REQUEST
;
1265 ti
= proto_tree_add_item(req_tree
, hf_mysql_payload
, tvb
, offset
, -1, ENC_NA
);
1266 expert_add_info(pinfo
, ti
, &ei_mysql_command
);
1267 offset
+= tvb_reported_length_remaining(tvb
, offset
);
1268 conn_data
->state
= UNDEFINED
;
1276 mysql_dissect_response(tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
,
1277 proto_tree
*tree
, mysql_conn_data_t
*conn_data
)
1281 gint server_status
= 0;
1284 response_code
= tvb_get_guint8(tvb
, offset
);
1286 if (response_code
== 0xff ) {
1287 offset
= mysql_dissect_error_packet(tvb
, pinfo
, offset
+1, tree
);
1288 conn_data
->state
= REQUEST
;
1291 else if (response_code
== 0xfe && tvb_reported_length_remaining(tvb
, offset
) < 9) {
1293 ti
= proto_tree_add_item(tree
, hf_mysql_eof
, tvb
, offset
, 1, ENC_NA
);
1297 /* pre-4.1 packet ends here */
1298 if (tvb_reported_length_remaining(tvb
, offset
)) {
1299 proto_tree_add_item(tree
, hf_mysql_num_warn
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1300 server_status
= tvb_get_letohs(tvb
, offset
+2);
1301 offset
= mysql_dissect_server_status(tvb
, offset
+2, tree
);
1304 if (conn_data
->state
== FIELD_PACKET
) {
1305 conn_data
->state
= ROW_PACKET
;
1306 } else if (conn_data
->state
== ROW_PACKET
) {
1307 if (server_status
& MYSQL_STAT_MU
) {
1308 conn_data
->state
= RESPONSE_TABULAR
;
1310 conn_data
->state
= REQUEST
;
1312 } else if (conn_data
->state
== PREPARED_PARAMETERS
) {
1313 if (conn_data
->stmt_num_fields
> 0) {
1314 conn_data
->state
= PREPARED_FIELDS
;
1316 conn_data
->state
= REQUEST
;
1318 } else if (conn_data
->state
== PREPARED_FIELDS
) {
1319 conn_data
->state
= REQUEST
;
1321 /* This should be an unreachable case */
1322 conn_data
->state
= REQUEST
;
1323 expert_add_info(pinfo
, ti
, &ei_mysql_eof
);
1327 else if (response_code
== 0) {
1328 if (conn_data
->state
== RESPONSE_PREPARE
) {
1329 offset
= mysql_dissect_response_prepare(tvb
, offset
, tree
, conn_data
);
1330 } else if (tvb_reported_length_remaining(tvb
, offset
+1) > tvb_get_fle(tvb
, offset
+1, NULL
, NULL
)) {
1331 offset
= mysql_dissect_ok_packet(tvb
, pinfo
, offset
+1, tree
, conn_data
);
1333 offset
= mysql_dissect_result_header(tvb
, pinfo
, offset
, tree
, conn_data
);
1338 switch (conn_data
->state
) {
1339 case RESPONSE_MESSAGE
:
1340 if ((lenstr
= tvb_reported_length_remaining(tvb
, offset
))) {
1341 proto_tree_add_item(tree
, hf_mysql_message
, tvb
, offset
, lenstr
, ENC_ASCII
|ENC_NA
);
1344 conn_data
->state
= REQUEST
;
1347 case RESPONSE_TABULAR
:
1348 offset
= mysql_dissect_result_header(tvb
, pinfo
, offset
, tree
, conn_data
);
1352 case RESPONSE_SHOW_FIELDS
:
1353 case RESPONSE_PREPARE
:
1354 case PREPARED_PARAMETERS
:
1355 offset
= mysql_dissect_field_packet(tvb
, offset
, tree
, conn_data
);
1359 offset
= mysql_dissect_row_packet(tvb
, offset
, tree
);
1362 case PREPARED_FIELDS
:
1363 offset
= mysql_dissect_field_packet(tvb
, offset
, tree
, conn_data
);
1367 ti
= proto_tree_add_item(tree
, hf_mysql_payload
, tvb
, offset
, -1, ENC_NA
);
1368 expert_add_info(pinfo
, ti
, &ei_mysql_unknown_response
);
1369 offset
+= tvb_reported_length_remaining(tvb
, offset
);
1370 conn_data
->state
= UNDEFINED
;
1379 mysql_dissect_error_packet(tvbuff_t
*tvb
, packet_info
*pinfo
,
1380 int offset
, proto_tree
*tree
)
1382 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " Error %d", tvb_get_letohs(tvb
, offset
));
1384 proto_tree_add_item(tree
, hf_mysql_error_code
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1387 if (tvb_get_guint8(tvb
, offset
) == '#')
1390 proto_tree_add_item(tree
, hf_mysql_sqlstate
, tvb
, offset
, 5, ENC_ASCII
|ENC_NA
);
1394 proto_tree_add_item(tree
, hf_mysql_error_string
, tvb
, offset
, -1, ENC_ASCII
|ENC_NA
);
1395 offset
+= tvb_reported_length_remaining(tvb
, offset
);
1402 mysql_dissect_ok_packet(tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
,
1403 proto_tree
*tree
, mysql_conn_data_t
*conn_data
)
1406 guint64 affected_rows
;
1410 col_append_str(pinfo
->cinfo
, COL_INFO
, " OK" );
1412 fle
= tvb_get_fle(tvb
, offset
, &affected_rows
, NULL
);
1413 proto_tree_add_uint64(tree
, hf_mysql_affected_rows
, tvb
, offset
, fle
, affected_rows
);
1416 fle
= tvb_get_fle(tvb
, offset
, &insert_id
, NULL
);
1417 if (tree
&& insert_id
) {
1418 proto_tree_add_uint64(tree
, hf_mysql_insert_id
, tvb
, offset
, fle
, insert_id
);
1422 if (tvb_reported_length_remaining(tvb
, offset
) > 0) {
1423 offset
= mysql_dissect_server_status(tvb
, offset
, tree
);
1425 /* 4.1+ protocol only: 2 bytes number of warnings */
1426 if (conn_data
->clnt_caps
& conn_data
->srv_caps
& MYSQL_CAPS_CU
) {
1427 proto_tree_add_item(tree
, hf_mysql_num_warn
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1432 /* optional: message string */
1433 if (tvb_reported_length_remaining(tvb
, offset
) > 0) {
1434 lenstr
= tvb_reported_length_remaining(tvb
, offset
);
1435 proto_tree_add_item(tree
, hf_mysql_message
, tvb
, offset
, lenstr
, ENC_ASCII
|ENC_NA
);
1439 conn_data
->state
= REQUEST
;
1445 mysql_dissect_server_status(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
)
1448 proto_item
*stat_tree
;
1451 tf
= proto_tree_add_item(tree
, hf_mysql_server_status
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1452 stat_tree
= proto_item_add_subtree(tf
, ett_stat
);
1453 proto_tree_add_item(stat_tree
, hf_mysql_stat_it
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1454 proto_tree_add_item(stat_tree
, hf_mysql_stat_ac
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1455 proto_tree_add_item(stat_tree
, hf_mysql_stat_mr
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1456 proto_tree_add_item(stat_tree
, hf_mysql_stat_mu
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1457 proto_tree_add_item(stat_tree
, hf_mysql_stat_bi
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1458 proto_tree_add_item(stat_tree
, hf_mysql_stat_ni
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1459 proto_tree_add_item(stat_tree
, hf_mysql_stat_cr
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1460 proto_tree_add_item(stat_tree
, hf_mysql_stat_lr
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1461 proto_tree_add_item(stat_tree
, hf_mysql_stat_dr
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1462 proto_tree_add_item(stat_tree
, hf_mysql_stat_bs
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1471 mysql_dissect_caps_server(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
, guint16
*caps
)
1474 proto_item
*cap_tree
;
1476 *caps
= tvb_get_letohs(tvb
, offset
);
1479 tf
= proto_tree_add_item(tree
, hf_mysql_caps_server
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1480 cap_tree
= proto_item_add_subtree(tf
, ett_caps
);
1481 proto_tree_add_item(cap_tree
, hf_mysql_cap_long_password
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1482 proto_tree_add_item(cap_tree
, hf_mysql_cap_found_rows
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1483 proto_tree_add_item(cap_tree
, hf_mysql_cap_long_flag
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1484 proto_tree_add_item(cap_tree
, hf_mysql_cap_connect_with_db
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1485 proto_tree_add_item(cap_tree
, hf_mysql_cap_no_schema
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1486 proto_tree_add_item(cap_tree
, hf_mysql_cap_compress
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1487 proto_tree_add_item(cap_tree
, hf_mysql_cap_odbc
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1488 proto_tree_add_item(cap_tree
, hf_mysql_cap_local_files
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1489 proto_tree_add_item(cap_tree
, hf_mysql_cap_ignore_space
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1490 proto_tree_add_item(cap_tree
, hf_mysql_cap_change_user
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1491 proto_tree_add_item(cap_tree
, hf_mysql_cap_interactive
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1492 proto_tree_add_item(cap_tree
, hf_mysql_cap_ssl
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1493 proto_tree_add_item(cap_tree
, hf_mysql_cap_ignore_sigpipe
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1494 proto_tree_add_item(cap_tree
, hf_mysql_cap_transactions
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1495 proto_tree_add_item(cap_tree
, hf_mysql_cap_reserved
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1496 proto_tree_add_item(cap_tree
, hf_mysql_cap_secure_connect
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1504 mysql_dissect_caps_client(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
, guint16
*caps
)
1507 proto_item
*cap_tree
;
1509 *caps
= tvb_get_letohs(tvb
, offset
);
1512 tf
= proto_tree_add_item(tree
, hf_mysql_caps_client
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1513 cap_tree
= proto_item_add_subtree(tf
, ett_caps
);
1514 proto_tree_add_item(cap_tree
, hf_mysql_cap_long_password
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1515 proto_tree_add_item(cap_tree
, hf_mysql_cap_found_rows
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1516 proto_tree_add_item(cap_tree
, hf_mysql_cap_long_flag
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1517 proto_tree_add_item(cap_tree
, hf_mysql_cap_connect_with_db
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1518 proto_tree_add_item(cap_tree
, hf_mysql_cap_no_schema
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1519 proto_tree_add_item(cap_tree
, hf_mysql_cap_compress
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1520 proto_tree_add_item(cap_tree
, hf_mysql_cap_odbc
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1521 proto_tree_add_item(cap_tree
, hf_mysql_cap_local_files
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1522 proto_tree_add_item(cap_tree
, hf_mysql_cap_ignore_space
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1523 proto_tree_add_item(cap_tree
, hf_mysql_cap_change_user
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1524 proto_tree_add_item(cap_tree
, hf_mysql_cap_interactive
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1525 proto_tree_add_item(cap_tree
, hf_mysql_cap_ssl
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1526 proto_tree_add_item(cap_tree
, hf_mysql_cap_ignore_sigpipe
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1527 proto_tree_add_item(cap_tree
, hf_mysql_cap_transactions
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1528 proto_tree_add_item(cap_tree
, hf_mysql_cap_reserved
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1529 proto_tree_add_item(cap_tree
, hf_mysql_cap_secure_connect
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1536 mysql_dissect_ext_caps_client(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
, guint16
*ext_caps
)
1539 proto_item
*extcap_tree
;
1540 *ext_caps
= tvb_get_letohs(tvb
, offset
);
1542 tf
= proto_tree_add_item(tree
, hf_mysql_extcaps_client
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1543 extcap_tree
= proto_item_add_subtree(tf
, ett_extcaps
);
1544 proto_tree_add_item(extcap_tree
, hf_mysql_cap_multi_statements
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1545 proto_tree_add_item(extcap_tree
, hf_mysql_cap_multi_results
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1554 mysql_dissect_result_header(tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
,
1555 proto_tree
*tree
, mysql_conn_data_t
*conn_data
)
1558 guint64 num_fields
, extra
;
1560 col_append_str(pinfo
->cinfo
, COL_INFO
, " TABULAR" );
1562 fle
= tvb_get_fle(tvb
, offset
, &num_fields
, NULL
);
1563 proto_tree_add_uint64(tree
, hf_mysql_num_fields
, tvb
, offset
, fle
, num_fields
);
1566 if (tvb_reported_length_remaining(tvb
, offset
)) {
1567 fle
= tvb_get_fle(tvb
, offset
, &extra
, NULL
);
1568 proto_tree_add_uint64(tree
, hf_mysql_extra
, tvb
, offset
, fle
, extra
);
1573 conn_data
->state
= FIELD_PACKET
;
1575 conn_data
->state
= ROW_PACKET
;
1583 * Add length encoded string to tree
1586 mysql_field_add_lestring(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
, int field
)
1591 offset
+= tvb_get_fle(tvb
, offset
, &lelen
, &is_null
);
1593 proto_tree_add_string(tree
, field
, tvb
, offset
, 4, "NULL");
1596 proto_tree_add_item(tree
, field
, tvb
, offset
, (int)lelen
, ENC_NA
);
1597 /* Prevent infinite loop due to overflow */
1598 if (offset
+ (int)lelen
< offset
) {
1599 offset
= tvb_reported_length(tvb
);
1602 offset
+= (int)lelen
;
1610 mysql_dissect_field_packet(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
, mysql_conn_data_t
*conn_data _U_
)
1613 proto_item
*flags_tree
;
1615 offset
= mysql_field_add_lestring(tvb
, offset
, tree
, hf_mysql_fld_catalog
);
1616 offset
= mysql_field_add_lestring(tvb
, offset
, tree
, hf_mysql_fld_db
);
1617 offset
= mysql_field_add_lestring(tvb
, offset
, tree
, hf_mysql_fld_table
);
1618 offset
= mysql_field_add_lestring(tvb
, offset
, tree
, hf_mysql_fld_org_table
);
1619 offset
= mysql_field_add_lestring(tvb
, offset
, tree
, hf_mysql_fld_name
);
1620 offset
= mysql_field_add_lestring(tvb
, offset
, tree
, hf_mysql_fld_org_name
);
1621 offset
+=1; /* filler */
1623 proto_tree_add_item(tree
, hf_mysql_fld_charsetnr
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1624 offset
+= 2; /* charset */
1626 proto_tree_add_item(tree
, hf_mysql_fld_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1627 offset
+= 4; /* length */
1629 proto_tree_add_item(tree
, hf_mysql_fld_type
, tvb
, offset
, 1, ENC_NA
);
1630 offset
+= 1; /* type */
1632 tf
= proto_tree_add_item(tree
, hf_mysql_fld_flags
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1633 flags_tree
= proto_item_add_subtree(tf
, ett_field_flags
);
1634 proto_tree_add_item(flags_tree
, hf_mysql_fld_not_null
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1635 proto_tree_add_item(flags_tree
, hf_mysql_fld_primary_key
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1636 proto_tree_add_item(flags_tree
, hf_mysql_fld_unique_key
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1637 proto_tree_add_item(flags_tree
, hf_mysql_fld_multiple_key
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1638 proto_tree_add_item(flags_tree
, hf_mysql_fld_blob
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1639 proto_tree_add_item(flags_tree
, hf_mysql_fld_unsigned
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1640 proto_tree_add_item(flags_tree
, hf_mysql_fld_zero_fill
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1641 proto_tree_add_item(flags_tree
, hf_mysql_fld_binary
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1642 proto_tree_add_item(flags_tree
, hf_mysql_fld_enum
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1643 proto_tree_add_item(flags_tree
, hf_mysql_fld_auto_increment
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1644 proto_tree_add_item(flags_tree
, hf_mysql_fld_timestamp
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1645 proto_tree_add_item(flags_tree
, hf_mysql_fld_set
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1646 offset
+= 2; /* flags */
1648 proto_tree_add_item(tree
, hf_mysql_fld_decimals
, tvb
, offset
, 1, ENC_NA
);
1649 offset
+= 1; /* decimals */
1651 offset
+= 2; /* filler */
1653 /* default (Only use for show fields) */
1654 if (tree
&& tvb_reported_length_remaining(tvb
, offset
) > 0) {
1655 offset
= mysql_field_add_lestring(tvb
, offset
, tree
, hf_mysql_fld_default
);
1662 mysql_dissect_row_packet(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
)
1664 while (tvb_reported_length_remaining(tvb
, offset
) > 0) {
1665 offset
= mysql_field_add_lestring(tvb
, offset
, tree
, hf_mysql_row_text
);
1673 mysql_dissect_response_prepare(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
, mysql_conn_data_t
*conn_data
)
1675 my_stmt_data_t
*stmt_data
;
1679 /* 0, marker for OK packet */
1681 proto_tree_add_item(tree
, hf_mysql_stmt_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1682 stmt_id
= tvb_get_letohl(tvb
, offset
);
1684 proto_tree_add_item(tree
, hf_mysql_num_fields
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1685 conn_data
->stmt_num_fields
= tvb_get_letohs(tvb
, offset
);
1687 proto_tree_add_item(tree
, hf_mysql_num_params
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1688 conn_data
->stmt_num_params
= tvb_get_letohs(tvb
, offset
);
1689 stmt_data
= wmem_new(wmem_file_scope(), struct my_stmt_data
);
1690 stmt_data
->nparam
= conn_data
->stmt_num_params
;
1691 flagsize
= (int)(sizeof(guint8
) * stmt_data
->nparam
);
1692 stmt_data
->param_flags
= (guint8
*)wmem_alloc(wmem_file_scope(), flagsize
);
1693 memset(stmt_data
->param_flags
, 0, flagsize
);
1694 wmem_tree_insert32(conn_data
->stmts
, stmt_id
, stmt_data
);
1698 proto_tree_add_item(tree
, hf_mysql_num_warn
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1700 if (conn_data
->stmt_num_params
> 0)
1701 conn_data
->state
= PREPARED_PARAMETERS
;
1702 else if (conn_data
->stmt_num_fields
> 0)
1703 conn_data
->state
= PREPARED_FIELDS
;
1705 conn_data
->state
= REQUEST
;
1707 return offset
+ tvb_reported_length_remaining(tvb
, offset
);
1713 get length of string in packet buffer
1718 offset current offset
1721 deliver length of string, delimited by either \0 or end of buffer
1724 length of string found, including \0 (if present)
1728 my_tvb_strsize(tvbuff_t
*tvb
, int offset
)
1730 gint len
= tvb_strnlen(tvb
, offset
, -1);
1732 len
= tvb_reported_length_remaining(tvb
, offset
);
1734 len
++; /* the trailing \0 */
1741 read "field length encoded" value from packet buffer
1745 tvb in packet buffer
1746 offset in offset in buffer
1747 res out where to store FLE value, may be NULL
1748 is_null out where to store ISNULL flag, may be NULL
1751 read FLE from packet buffer and store its value and ISNULL flag
1752 in caller provided variables
1758 tvb_get_fle(tvbuff_t
*tvb
, int offset
, guint64
*res
, guint8
*is_null
)
1762 prefix
= tvb_get_guint8(tvb
, offset
);
1776 *res
= tvb_get_letohs(tvb
, offset
+1);
1780 *res
= tvb_get_letohl(tvb
, offset
+1);
1784 *res
= tvb_get_letoh64(tvb
, offset
+1);
1794 /* dissector helper: length of PDU */
1796 get_mysql_pdu_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
, int offset
)
1798 guint plen
= tvb_get_letoh24(tvb
, offset
);
1799 return plen
+ 4; /* add length field + packet number */
1802 /* dissector main function: handle one PDU */
1804 dissect_mysql_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
1806 proto_tree
*mysql_tree
= NULL
;
1808 conversation_t
*conversation
;
1810 guint packet_number
;
1811 gboolean is_response
;
1812 mysql_conn_data_t
*conn_data
;
1814 mysql_state_t conn_state_in
, conn_state_out
, frame_state
;
1818 struct mysql_frame_data
*mysql_frame_data_p
;
1820 /* get conversation, create if necessary*/
1821 conversation
= find_or_create_conversation(pinfo
);
1823 /* get associated state information, create if necessary */
1824 conn_data
= (mysql_conn_data_t
*)conversation_get_proto_data(conversation
, proto_mysql
);
1826 conn_data
= wmem_new(wmem_file_scope(), mysql_conn_data_t
);
1827 conn_data
->srv_caps
= 0;
1828 conn_data
->clnt_caps
= 0;
1829 conn_data
->clnt_caps_ext
= 0;
1830 conn_data
->state
= UNDEFINED
;
1831 conn_data
->stmts
= wmem_tree_new(wmem_file_scope());
1833 conn_data
->generation
= 0;
1835 conn_data
->major_version
= 0;
1836 conversation_add_proto_data(conversation
, proto_mysql
, conn_data
);
1839 mysql_frame_data_p
= (struct mysql_frame_data
*)p_get_proto_data(pinfo
->fd
, proto_mysql
, 0);
1840 if (!mysql_frame_data_p
) {
1841 /* We haven't seen this frame before. Store the state of the
1842 * conversation now so if/when we dissect the frame again
1843 * we'll start with the same state.
1845 mysql_frame_data_p
= wmem_new(wmem_file_scope(), struct mysql_frame_data
);
1846 mysql_frame_data_p
->state
= conn_data
->state
;
1847 p_add_proto_data(pinfo
->fd
, proto_mysql
, 0, mysql_frame_data_p
);
1849 } else if (conn_data
->state
!= FIELD_PACKET
&& conn_data
->state
!= ROW_PACKET
) {
1850 /* We have seen this frame before. Set the connection state
1851 * to whatever state it had the first time we saw this frame
1852 * (e.g., based on whatever frames came before it).
1853 * The state may change as we dissect this packet.
1854 * XXX: I think the logic of the above else if test is as follows:
1855 * During the first (sequential) dissection pass thru the capture
1856 * file the conversation connection state as of the beginning of each frame
1857 * is saved in the connection_state for that frame.
1858 * Any state changes *within* a mysql "message" (ie: query/response/etc)
1859 * while processing mysql PDUS (aka "packets") in that message must be preserved.
1860 * It appears that FIELD_PACKET & ROW_PACKET are the only two
1861 * state changes which can occur within a mysql message which affect
1862 * subsequent processing within the message.
1863 * Question: Does this logic work OK for a reassembled message ?
1865 conn_data
->state
= mysql_frame_data_p
->state
;
1869 ti
= proto_tree_add_item(tree
, proto_mysql
, tvb
, offset
, -1, ENC_NA
);
1870 mysql_tree
= proto_item_add_subtree(ti
, ett_mysql
);
1871 proto_tree_add_item(mysql_tree
, hf_mysql_packet_length
, tvb
, offset
, 3, ENC_LITTLE_ENDIAN
);
1875 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "MySQL");
1877 if (pinfo
->destport
== pinfo
->match_uint
) {
1883 packet_number
= tvb_get_guint8(tvb
, offset
);
1884 proto_tree_add_item(mysql_tree
, hf_mysql_packet_number
, tvb
, offset
, 1, ENC_NA
);
1888 conn_state_in
= conn_data
->state
;
1889 frame_state
= mysql_frame_data_p
->state
;
1890 generation
= conn_data
->generation
;
1892 pi
= proto_tree_add_text(mysql_tree
, tvb
, offset
, 0, "conversation: %p", conversation
);
1893 PROTO_ITEM_SET_GENERATED(pi
);
1894 pi
= proto_tree_add_text(mysql_tree
, tvb
, offset
, 0, "generation: %" G_GINT64_MODIFIER
"d", generation
);
1895 PROTO_ITEM_SET_GENERATED(pi
);
1896 pi
= proto_tree_add_text(mysql_tree
, tvb
, offset
, 0, "conn state: %s (%u)",
1897 val_to_str(conn_state_in
, state_vals
, "Unknown (%u)"),
1899 PROTO_ITEM_SET_GENERATED(pi
);
1900 pi
= proto_tree_add_text(mysql_tree
, tvb
, offset
, 0, "frame state: %s (%u)",
1901 val_to_str(frame_state
, state_vals
, "Unknown (%u)"),
1903 PROTO_ITEM_SET_GENERATED(pi
);
1908 if (packet_number
== 0) {
1909 col_set_str(pinfo
->cinfo
, COL_INFO
, "Server Greeting");
1910 offset
= mysql_dissect_greeting(tvb
, pinfo
, offset
, mysql_tree
, conn_data
);
1912 col_set_str(pinfo
->cinfo
, COL_INFO
, "Response");
1913 offset
= mysql_dissect_response(tvb
, pinfo
, offset
, mysql_tree
, conn_data
);
1916 if (packet_number
== 1) {
1917 col_set_str(pinfo
->cinfo
, COL_INFO
, "Login Request");
1918 offset
= mysql_dissect_login(tvb
, pinfo
, offset
, mysql_tree
, conn_data
);
1920 col_set_str(pinfo
->cinfo
, COL_INFO
, "Request");
1921 offset
= mysql_dissect_request(tvb
, pinfo
, offset
, mysql_tree
, conn_data
);
1926 conn_state_out
= conn_data
->state
;
1927 ++(conn_data
->generation
);
1928 pi
= proto_tree_add_text(mysql_tree
, tvb
, offset
, 0, "next proto state: %s (%u)",
1929 val_to_str(conn_state_out
, state_vals
, "Unknown (%u)"),
1931 PROTO_ITEM_SET_GENERATED(pi
);
1934 /* remaining payload indicates an error */
1935 if (tree
&& tvb_reported_length_remaining(tvb
, offset
) > 0) {
1936 ti
= proto_tree_add_item(mysql_tree
, hf_mysql_payload
, tvb
, offset
, -1, ENC_NA
);
1937 expert_add_info(pinfo
, ti
, &ei_mysql_dissector_incomplete
);
1940 return tvb_length(tvb
);
1943 /* dissector entrypoint, handles TCP-desegmentation */
1945 dissect_mysql(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
1947 tcp_dissect_pdus(tvb
, pinfo
, tree
, mysql_desegment
, 3,
1948 get_mysql_pdu_len
, dissect_mysql_pdu
, data
);
1949 return tvb_length(tvb
);
1952 /* protocol registration */
1953 void proto_register_mysql(void)
1955 static hf_register_info hf
[]=
1957 { &hf_mysql_packet_length
,
1958 { "Packet Length", "mysql.packet_length",
1959 FT_UINT24
, BASE_DEC
, NULL
, 0x0,
1962 { &hf_mysql_packet_number
,
1963 { "Packet Number", "mysql.packet_number",
1964 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1967 { &hf_mysql_request
,
1968 { "Request Command", "mysql.request",
1969 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1972 { &hf_mysql_command
,
1973 { "Command", "mysql.command",
1974 FT_UINT8
, BASE_DEC
, VALS(mysql_command_vals
), 0x0,
1977 { &hf_mysql_error_code
,
1978 { "Error Code", "mysql.error_code",
1979 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1982 { &hf_mysql_error_string
,
1983 { "Error message", "mysql.error.message",
1984 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1985 "Error string in case of MySQL error message", HFILL
}},
1987 { &hf_mysql_sqlstate
,
1988 { "SQL state", "mysql.sqlstate",
1989 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1992 { &hf_mysql_message
,
1993 { "Message", "mysql.message",
1994 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
1997 { &hf_mysql_server_greeting
,
1998 { "Server Greeting", "mysql.server_greeting",
1999 FT_NONE
, BASE_NONE
, NULL
, 0x0,
2002 { &hf_mysql_protocol
,
2003 { "Protocol", "mysql.protocol",
2004 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2005 "Protocol Version", HFILL
}},
2007 { &hf_mysql_version
,
2008 { "Version", "mysql.version",
2009 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
2010 "MySQL Version", HFILL
}},
2012 { &hf_mysql_caps_server
,
2013 { "Server Capabilities", "mysql.caps.server",
2014 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
2015 "MySQL Capabilities", HFILL
}},
2017 { &hf_mysql_caps_client
,
2018 { "Client Capabilities", "mysql.caps.client",
2019 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
2020 "MySQL Capabilities", HFILL
}},
2022 { &hf_mysql_cap_long_password
,
2023 { "Long Password","mysql.caps.lp",
2024 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_CAPS_LP
,
2027 { &hf_mysql_cap_found_rows
,
2028 { "Found Rows","mysql.caps.fr",
2029 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_CAPS_FR
,
2032 { &hf_mysql_cap_long_flag
,
2033 { "Long Column Flags","mysql.caps.lf",
2034 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_CAPS_LF
,
2037 { &hf_mysql_cap_connect_with_db
,
2038 { "Connect With Database","mysql.caps.cd",
2039 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_CAPS_CD
,
2042 { &hf_mysql_cap_no_schema
,
2043 { "Don't Allow database.table.column","mysql.caps.ns",
2044 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_CAPS_NS
,
2047 { &hf_mysql_cap_compress
,
2048 { "Can use compression protocol","mysql.caps.cp",
2049 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_CAPS_CP
,
2052 { &hf_mysql_cap_odbc
,
2053 { "ODBC Client","mysql.caps.ob",
2054 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_CAPS_OB
,
2057 { &hf_mysql_cap_local_files
,
2058 { "Can Use LOAD DATA LOCAL","mysql.caps.li",
2059 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_CAPS_LI
,
2062 { &hf_mysql_cap_ignore_space
,
2063 { "Ignore Spaces before '('","mysql.caps.is",
2064 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_CAPS_IS
,
2067 { &hf_mysql_cap_change_user
,
2068 { "Speaks 4.1 protocol (new flag)","mysql.caps.cu",
2069 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_CAPS_CU
,
2072 { &hf_mysql_cap_interactive
,
2073 { "Interactive Client","mysql.caps.ia",
2074 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_CAPS_IA
,
2077 { &hf_mysql_cap_ssl
,
2078 { "Switch to SSL after handshake","mysql.caps.sl",
2079 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_CAPS_SL
,
2082 { &hf_mysql_cap_ignore_sigpipe
,
2083 { "Ignore sigpipes","mysql.caps.ii",
2084 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_CAPS_II
,
2087 { &hf_mysql_cap_transactions
,
2088 { "Knows about transactions","mysql.caps.ta",
2089 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_CAPS_TA
,
2092 { &hf_mysql_cap_reserved
,
2093 { "Speaks 4.1 protocol (old flag)","mysql.caps.rs",
2094 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_CAPS_RS
,
2097 { &hf_mysql_cap_secure_connect
,
2098 { "Can do 4.1 authentication","mysql.caps.sc",
2099 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_CAPS_SC
,
2102 { &hf_mysql_extcaps_client
,
2103 { "Extended Client Capabilities", "mysql.extcaps.client",
2104 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
2105 "MySQL Extended Capabilities", HFILL
}},
2107 { &hf_mysql_cap_multi_statements
,
2108 { "Supports multiple statements","mysql.caps.ms",
2109 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_CAPS_MS
,
2112 { &hf_mysql_cap_multi_results
,
2113 { "Supports multiple results","mysql.caps.mr",
2114 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_CAPS_MR
,
2117 { &hf_mysql_login_request
,
2118 { "Login Request", "mysql.login_request",
2119 FT_NONE
, BASE_NONE
, NULL
, 0x0,
2122 { &hf_mysql_max_packet
,
2123 { "MAX Packet", "mysql.max_packet",
2124 FT_UINT24
, BASE_DEC
, NULL
, 0x0,
2125 "MySQL Max packet", HFILL
}},
2127 { &hf_mysql_charset
,
2128 { "Charset", "mysql.charset",
2129 FT_UINT8
, BASE_DEC
, VALS(mysql_collation_vals
), 0x0,
2130 "MySQL Charset", HFILL
}},
2132 { &hf_mysql_table_name
,
2133 { "Table Name", "mysql.table_name",
2134 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
2138 { "Username", "mysql.user",
2139 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
2140 "Login Username", HFILL
}},
2143 { "Schema", "mysql.schema",
2144 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2145 "Login Schema", HFILL
}},
2148 { "Salt", "mysql.salt",
2149 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
2153 { "Salt", "mysql.salt2",
2154 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
2157 { &hf_mysql_thread_id
,
2158 { "Thread ID", "mysql.thread_id",
2159 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2160 "MySQL Thread ID", HFILL
}},
2162 { &hf_mysql_server_language
,
2163 { "Server Language", "mysql.server_language",
2164 FT_UINT8
, BASE_DEC
, VALS(mysql_collation_vals
), 0x0,
2165 "MySQL Charset", HFILL
}},
2167 { &hf_mysql_server_status
,
2168 { "Server Status", "mysql.server_status",
2169 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
2170 "MySQL Status", HFILL
}},
2172 { &hf_mysql_stat_it
,
2173 { "In transaction", "mysql.stat.it",
2174 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_STAT_IT
,
2177 { &hf_mysql_stat_ac
,
2178 { "AUTO_COMMIT", "mysql.stat.ac",
2179 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_STAT_AC
,
2182 { &hf_mysql_stat_mr
,
2183 { "More results", "mysql.stat.mr",
2184 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_STAT_MR
,
2187 { &hf_mysql_stat_mu
,
2188 { "Multi query - more resultsets", "mysql.stat.mu",
2189 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_STAT_MU
,
2192 { &hf_mysql_stat_bi
,
2193 { "Bad index used", "mysql.stat.bi",
2194 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_STAT_BI
,
2197 { &hf_mysql_stat_ni
,
2198 { "No index used", "mysql.stat.ni",
2199 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_STAT_NI
,
2202 { &hf_mysql_stat_cr
,
2203 { "Cursor exists", "mysql.stat.cr",
2204 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_STAT_CR
,
2207 { &hf_mysql_stat_lr
,
2208 { "Last row sebd", "mysql.stat.lr",
2209 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_STAT_LR
,
2212 { &hf_mysql_stat_dr
,
2213 { "database dropped", "mysql.stat.dr",
2214 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_STAT_DR
,
2217 { &hf_mysql_stat_bs
,
2218 { "No backslash escapes", "mysql.stat.bs",
2219 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_STAT_BS
,
2222 { &hf_mysql_refresh
,
2223 { "Refresh Option", "mysql.refresh",
2224 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2227 { &hf_mysql_rfsh_grants
,
2228 { "reload permissions", "mysql.rfsh.grants",
2229 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), MYSQL_RFSH_GRANT
,
2232 { &hf_mysql_rfsh_log
,
2233 { "flush logfiles", "mysql.rfsh.log",
2234 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), MYSQL_RFSH_LOG
,
2237 { &hf_mysql_rfsh_tables
,
2238 { "flush tables", "mysql.rfsh.tables",
2239 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), MYSQL_RFSH_TABLES
,
2242 { &hf_mysql_rfsh_hosts
,
2243 { "flush hosts", "mysql.rfsh.hosts",
2244 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), MYSQL_RFSH_HOSTS
,
2247 { &hf_mysql_rfsh_status
,
2248 { "reset statistics", "mysql.rfsh.status",
2249 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), MYSQL_RFSH_STATUS
,
2252 { &hf_mysql_rfsh_threads
,
2253 { "empty thread cache", "mysql.rfsh.threads",
2254 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), MYSQL_RFSH_THREADS
,
2257 { &hf_mysql_rfsh_slave
,
2258 { "flush slave status", "mysql.rfsh.slave",
2259 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), MYSQL_RFSH_SLAVE
,
2262 { &hf_mysql_rfsh_master
,
2263 { "flush master status", "mysql.rfsh.master",
2264 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), MYSQL_RFSH_MASTER
,
2268 { "Unused", "mysql.unused",
2269 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2273 { "Password", "mysql.passwd",
2274 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
2277 { &hf_mysql_payload
,
2278 { "Payload", "mysql.payload",
2279 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
2280 "Additional Payload", HFILL
}},
2282 { &hf_mysql_affected_rows
,
2283 { "Affected Rows", "mysql.affected_rows",
2284 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
2287 { &hf_mysql_insert_id
,
2288 { "Last INSERT ID", "mysql.insert_id",
2289 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
2292 { &hf_mysql_num_warn
,
2293 { "Warnings", "mysql.warnings",
2294 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2298 { "Thread ID", "mysql.thd_id",
2299 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2302 { &hf_mysql_stmt_id
,
2303 { "Statement ID", "mysql.stmt_id",
2304 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2308 { "Statement", "mysql.query",
2309 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2312 { &hf_mysql_shutdown
,
2313 { "Shutdown Level", "mysql.shutdown",
2314 FT_UINT8
, BASE_DEC
, VALS(mysql_shutdown_vals
), 0x0,
2318 { "Option", "mysql.option",
2319 FT_UINT16
, BASE_DEC
, VALS(mysql_option_vals
), 0x0,
2323 { "Parameter", "mysql.param",
2324 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2327 { &hf_mysql_num_params
,
2328 { "Number of parameter", "mysql.num_params",
2329 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2332 { &hf_mysql_num_rows
,
2333 { "Rows to fetch", "mysql.num_rows",
2334 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2337 { &hf_mysql_exec_flags4
,
2338 { "Flags (unused)", "mysql.exec_flags",
2339 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2342 { &hf_mysql_exec_flags5
,
2343 { "Flags", "mysql.exec_flags",
2344 FT_UINT8
, BASE_DEC
, VALS(mysql_exec_flags_vals
), 0x0,
2347 { &hf_mysql_new_parameter_bound_flag
,
2348 { "New parameter bound flag", "mysql.new_parameter_bound_flag",
2349 FT_UINT8
, BASE_DEC
, VALS(mysql_new_parameter_bound_flag_vals
), 0x0,
2352 { &hf_mysql_exec_iter
,
2353 { "Iterations (unused)", "mysql.exec_iter",
2354 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2357 { &hf_mysql_binlog_position
,
2358 { "Binlog Position", "mysql.binlog.position",
2359 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2360 "Position to start at", HFILL
}},
2362 { &hf_mysql_binlog_flags
,
2363 { "Binlog Flags", "mysql.binlog.flags",
2364 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
2365 "(currently not used; always 0)", HFILL
}},
2367 { &hf_mysql_binlog_server_id
,
2368 { "Binlog server id", "mysql.binlog.server_id",
2369 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
2370 "server_id of the slave", HFILL
}},
2372 { &hf_mysql_binlog_file_name
,
2373 { "Binlog file name", "mysql.binlog.file_name",
2374 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
2378 { "EOF marker", "mysql.eof",
2379 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2382 { &hf_mysql_num_fields
,
2383 { "Number of fields", "mysql.num_fields",
2384 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
2388 { "Extra data", "mysql.extra",
2389 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
2392 { &hf_mysql_fld_catalog
,
2393 { "Catalog", "mysql.field.catalog",
2394 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2395 "Field: catalog", HFILL
}},
2398 { "Database", "mysql.field.db",
2399 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2400 "Field: database", HFILL
}},
2402 { &hf_mysql_fld_table
,
2403 { "Table", "mysql.field.table",
2404 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2405 "Field: table", HFILL
}},
2407 { &hf_mysql_fld_org_table
,
2408 { "Original table", "mysql.field.org_table",
2409 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2410 "Field: original table", HFILL
}},
2412 { &hf_mysql_fld_name
,
2413 { "Name", "mysql.field.name",
2414 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2415 "Field: name", HFILL
}},
2417 { &hf_mysql_fld_org_name
,
2418 { "Original name", "mysql.field.org_name",
2419 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2420 "Field: original name", HFILL
}},
2422 { &hf_mysql_fld_charsetnr
,
2423 { "Charset number", "mysql.field.charsetnr",
2424 FT_UINT16
, BASE_DEC
, VALS(mysql_collation_vals
), 0x0,
2425 "Field: charset number", HFILL
}},
2427 { &hf_mysql_fld_length
,
2428 { "Length", "mysql.field.length",
2429 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2430 "Field: length", HFILL
}},
2432 { &hf_mysql_fld_type
,
2433 { "Type", "mysql.field.type",
2434 FT_UINT8
, BASE_DEC
, VALS(type_constants
), 0x0,
2435 "Field: type", HFILL
}},
2437 { &hf_mysql_fld_flags
,
2438 { "Flags", "mysql.field.flags",
2439 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
2440 "Field: flags", HFILL
}},
2442 { &hf_mysql_fld_not_null
,
2443 { "Not null", "mysql.field.flags.not_null",
2444 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_FLD_NOT_NULL_FLAG
,
2445 "Field: flag not null", HFILL
}},
2447 { &hf_mysql_fld_primary_key
,
2448 { "Primary key", "mysql.field.flags.primary_key",
2449 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_FLD_PRI_KEY_FLAG
,
2450 "Field: flag primary key", HFILL
}},
2452 { &hf_mysql_fld_unique_key
,
2453 { "Unique key", "mysql.field.flags.unique_key",
2454 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_FLD_UNIQUE_KEY_FLAG
,
2455 "Field: flag unique key", HFILL
}},
2457 { &hf_mysql_fld_multiple_key
,
2458 { "Multiple key", "mysql.field.flags.multiple_key",
2459 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_FLD_MULTIPLE_KEY_FLAG
,
2460 "Field: flag multiple key", HFILL
}},
2462 { &hf_mysql_fld_blob
,
2463 { "Blob", "mysql.field.flags.blob",
2464 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_FLD_BLOB_FLAG
,
2465 "Field: flag blob", HFILL
}},
2467 { &hf_mysql_fld_unsigned
,
2468 { "Unsigned", "mysql.field.flags.unsigned",
2469 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_FLD_UNSIGNED_FLAG
,
2470 "Field: flag unsigned", HFILL
}},
2472 { &hf_mysql_fld_zero_fill
,
2473 { "Zero fill", "mysql.field.flags.zero_fill",
2474 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_FLD_ZEROFILL_FLAG
,
2475 "Field: flag zero fill", HFILL
}},
2477 { &hf_mysql_fld_binary
,
2478 { "Binary", "mysql.field.flags.binary",
2479 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_FLD_BINARY_FLAG
,
2480 "Field: flag binary", HFILL
}},
2482 { &hf_mysql_fld_enum
,
2483 { "Enum", "mysql.field.flags.enum",
2484 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_FLD_ENUM_FLAG
,
2485 "Field: flag enum", HFILL
}},
2487 { &hf_mysql_fld_auto_increment
,
2488 { "Auto increment", "mysql.field.flags.auto_increment",
2489 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_FLD_AUTO_INCREMENT_FLAG
,
2490 "Field: flag auto increment", HFILL
}},
2492 { &hf_mysql_fld_timestamp
,
2493 { "Timestamp", "mysql.field.flags.timestamp",
2494 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_FLD_TIMESTAMP_FLAG
,
2495 "Field: flag timestamp", HFILL
}},
2497 { &hf_mysql_fld_set
,
2498 { "Set", "mysql.field.flags.set",
2499 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), MYSQL_FLD_SET_FLAG
,
2500 "Field: flag set", HFILL
}},
2502 { &hf_mysql_fld_decimals
,
2503 { "Decimals", "mysql.field.decimals",
2504 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2505 "Field: decimals", HFILL
}},
2507 { &hf_mysql_fld_default
,
2508 { "Default", "mysql.field.default",
2509 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2510 "Field: default", HFILL
}},
2512 { &hf_mysql_row_text
,
2513 { "text", "mysql.row.text",
2514 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2515 "Field: row packet text", HFILL
}},
2517 { &hf_mysql_exec_param
,
2518 { "Parameter", "mysql.exec_param",
2519 FT_NONE
, BASE_NONE
, NULL
, 0x0,
2522 { &hf_mysql_exec_unsigned
,
2523 { "Unsigned", "mysql.exec.unsigned",
2524 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2527 { &hf_mysql_exec_field_longlong
,
2528 { "Value", "mysql.exec.field.longlong",
2529 FT_INT64
, BASE_DEC
, NULL
, 0x0,
2532 { &hf_mysql_exec_field_string
,
2533 { "Value", "mysql.exec.field.string",
2534 FT_UINT_STRING
, BASE_NONE
, NULL
, 0x0,
2537 { &hf_mysql_exec_field_double
,
2538 { "Value", "mysql.exec.field.double",
2539 FT_DOUBLE
, BASE_NONE
, NULL
, 0x0,
2542 { &hf_mysql_exec_field_datetime_length
,
2543 { "Length", "mysql.exec.field.datetime.length",
2544 FT_INT8
, BASE_DEC
, NULL
, 0x0,
2547 { &hf_mysql_exec_field_year
,
2548 { "Year", "mysql.exec.field.year",
2549 FT_INT16
, BASE_DEC
, NULL
, 0x0,
2552 { &hf_mysql_exec_field_month
,
2553 { "Month", "mysql.exec.field.month",
2554 FT_INT8
, BASE_DEC
, NULL
, 0x0,
2557 { &hf_mysql_exec_field_day
,
2558 { "Day", "mysql.exec.field.day",
2559 FT_INT8
, BASE_DEC
, NULL
, 0x0,
2562 { &hf_mysql_exec_field_hour
,
2563 { "Hour", "mysql.exec.field.hour",
2564 FT_INT8
, BASE_DEC
, NULL
, 0x0,
2567 { &hf_mysql_exec_field_minute
,
2568 { "Minute", "mysql.exec.field.minute",
2569 FT_INT8
, BASE_DEC
, NULL
, 0x0,
2572 { &hf_mysql_exec_field_second
,
2573 { "Second", "mysql.exec.field.second",
2574 FT_INT8
, BASE_DEC
, NULL
, 0x0,
2577 { &hf_mysql_exec_field_second_b
,
2578 { "Billionth of a second", "mysql.exec.field.secondb",
2579 FT_INT32
, BASE_DEC
, NULL
, 0x0,
2582 { &hf_mysql_exec_field_long
,
2583 { "Value", "mysql.exec.field.long",
2584 FT_INT32
, BASE_DEC
, NULL
, 0x0,
2587 { &hf_mysql_exec_field_tiny
,
2588 { "Value", "mysql.exec.field.tiny",
2589 FT_INT8
, BASE_DEC
, NULL
, 0x0,
2592 { &hf_mysql_exec_field_short
,
2593 { "Value", "mysql.exec.field.short",
2594 FT_INT16
, BASE_DEC
, NULL
, 0x0,
2597 { &hf_mysql_exec_field_float
,
2598 { "Value", "mysql.exec.field.float",
2599 FT_FLOAT
, BASE_NONE
, NULL
, 0x0,
2602 { &hf_mysql_exec_field_time_length
,
2603 { "Length", "mysql.exec.field.time.length",
2604 FT_INT8
, BASE_DEC
, NULL
, 0x0,
2607 { &hf_mysql_exec_field_time_sign
,
2608 { "Flags", "mysql.exec.field.time.sign",
2609 FT_UINT8
, BASE_DEC
, VALS(mysql_exec_time_sign_vals
), 0x0,
2612 { &hf_mysql_exec_field_time_days
,
2613 { "Days", "mysql.exec.field.time.days",
2614 FT_INT32
, BASE_DEC
, NULL
, 0x0,
2621 &ett_server_greeting
,
2632 static ei_register_info ei
[] = {
2633 { &ei_mysql_dissector_incomplete
, { "mysql.dissector_incomplete", PI_UNDECODED
, PI_WARN
, "FIXME - dissector is incomplete", EXPFILL
}},
2634 { &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
}},
2635 { &ei_mysql_prepare_response_needed
, { "mysql.prepare_response_needed", PI_UNDECODED
, PI_WARN
, "PREPARE Response packet is needed to dissect the payload", EXPFILL
}},
2636 { &ei_mysql_command
, { "mysql.command.invalid", PI_PROTOCOL
, PI_WARN
, "Unknown/invalid command code", EXPFILL
}},
2637 { &ei_mysql_eof
, { "mysql.eof.wrong_state", PI_PROTOCOL
, PI_WARN
, "EOF Marker found while connection in wrong state.", EXPFILL
}},
2638 { &ei_mysql_unknown_response
, { "mysql.unknown_response", PI_UNDECODED
, PI_WARN
, "unknown/invalid response", EXPFILL
}},
2641 module_t
*mysql_module
;
2642 expert_module_t
* expert_mysql
;
2644 proto_mysql
= proto_register_protocol("MySQL Protocol", "MySQL", "mysql");
2645 proto_register_field_array(proto_mysql
, hf
, array_length(hf
));
2646 proto_register_subtree_array(ett
, array_length(ett
));
2647 expert_mysql
= expert_register_protocol(proto_mysql
);
2648 expert_register_field_array(expert_mysql
, ei
, array_length(ei
));
2650 mysql_module
= prefs_register_protocol(proto_mysql
, NULL
);
2651 prefs_register_bool_preference(mysql_module
, "desegment_buffers",
2652 "Reassemble MySQL buffers spanning multiple TCP segments",
2653 "Whether the MySQL dissector should reassemble MySQL buffers spanning multiple TCP segments."
2654 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2656 prefs_register_bool_preference(mysql_module
, "show_sql_query",
2657 "Show SQL Query string in INFO column",
2658 "Whether the MySQL dissector should display the SQL query string in the INFO column.",
2661 new_register_dissector("mysql", dissect_mysql_pdu
, proto_mysql
);
2664 /* dissector registration */
2665 void proto_reg_handoff_mysql(void)
2667 dissector_handle_t mysql_handle
;
2668 mysql_handle
= new_create_dissector_handle(dissect_mysql
, proto_mysql
);
2669 dissector_add_uint("tcp.port", TCP_PORT_MySQL
, mysql_handle
);
2673 * Editor modelines - http://www.wireshark.org/tools/modelines.html
2678 * indent-tabs-mode: t
2681 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2682 * :indentSize=8:tabSize=8:noTabs=false: