HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-mysql.c
blob7106a4bf67f7f38114dea9fe0aa2cda5106a121d
1 /* packet-mysql.c
2 * Routines for mysql packet dissection
4 * Huagang XIE <huagang@intruvert.com>
6 * MySQL 4.1+ protocol by Axel Schwenke <axel@mysql.com>
8 * $Id$
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 */
40 #include "config.h"
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
71 /* field flags */
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
89 /* status bitfield */
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 */
113 #define MYSQL_QUIT 1
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"},
184 {0, NULL}
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"},
193 {0, NULL}
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"},
200 {0, NULL}
203 /* decoding table: exec_time_sign */
204 static const value_string mysql_exec_time_sign_vals[] = {
205 {0, "Positive"},
206 {1, "Negative"},
207 {0, NULL}
210 #if 0
211 /* charset: pre-4.1 used the term 'charset', later changed to 'collation' */
212 static const value_string mysql_charset_vals[] = {
213 {1, "big5"},
214 {2, "czech"},
215 {3, "dec8"},
216 {4, "dos" },
217 {5, "german1"},
218 {6, "hp8"},
219 {7, "koi8_ru"},
220 {8, "latin1"},
221 {9, "latin2"},
222 {9, "swe7 "},
223 {10, "usa7"},
224 {11, "ujis"},
225 {12, "sjis"},
226 {13, "cp1251"},
227 {14, "danish"},
228 {15, "hebrew"},
229 {16, "win1251"},
230 {17, "tis620"},
231 {18, "euc_kr"},
232 {19, "estonia"},
233 {20, "hungarian"},
234 {21, "koi8_ukr"},
235 {22, "win1251ukr"},
236 {23, "gb2312"},
237 {24, "greek"},
238 {25, "win1250"},
239 {26, "croat"},
240 {27, "gbk"},
241 {28, "cp1257"},
242 {29, "latin5"},
243 {0, NULL}
245 #endif
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
252 ORDER BY ID
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"},
343 {0, NULL}
347 /* allowed MYSQL_SHUTDOWN levels */
348 static const value_string mysql_shutdown_vals[] = {
349 {0, "default"},
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"},
357 {0, NULL}
361 /* allowed MYSQL_SET_OPTION values */
362 static const value_string mysql_option_vals[] = {
363 {0, "multi statements on"},
364 {1, "multi statements off"},
365 {0, NULL}
368 /* protocol id */
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;
528 /* type constants */
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" },
557 {0, NULL}
560 typedef enum mysql_state {
561 UNDEFINED,
562 LOGIN,
563 REQUEST,
564 RESPONSE_OK,
565 RESPONSE_MESSAGE,
566 RESPONSE_TABULAR,
567 RESPONSE_SHOW_FIELDS,
568 FIELD_PACKET,
569 ROW_PACKET,
570 RESPONSE_PREPARE,
571 PREPARED_PARAMETERS,
572 PREPARED_FIELDS
573 } mysql_state_t;
575 #ifdef CTDEBUG
576 static const value_string state_vals[] = {
577 {UNDEFINED, "undefined"},
578 {LOGIN, "login"},
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"},
589 {0, NULL}
591 #endif
593 typedef struct mysql_conn_data {
594 guint16 srv_caps;
595 guint16 clnt_caps;
596 guint16 clnt_caps_ext;
597 mysql_state_t state;
598 guint16 stmt_num_params;
599 guint16 stmt_num_fields;
600 wmem_tree_t* stmts;
601 #ifdef CTDEBUG
602 guint32 generation;
603 #endif
604 guint8 major_version;
605 } mysql_conn_data_t;
607 struct mysql_frame_data {
608 mysql_state_t state;
611 typedef struct my_stmt_data {
612 guint16 nparam;
613 guint8* param_flags;
614 } my_stmt_data_t;
616 typedef struct mysql_exec_dissector {
617 guint8 type;
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 },
667 { 0x00, 0, NULL },
670 static int
671 mysql_dissect_greeting(tvbuff_t *tvb, packet_info *pinfo, int offset,
672 proto_tree *tree, mysql_conn_data_t *conn_data)
674 gint protocol;
675 gint lenstr;
676 int ver_offset;
678 proto_item *tf;
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);
696 offset += 1;
698 /* version string */
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';
709 offset += lenstr;
711 /* 4 bytes little endian thread_id */
712 proto_tree_add_item(greeting_tree, hf_mysql_thread_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
713 offset += 4;
715 /* salt string */
716 lenstr = tvb_strsize(tvb,offset);
717 proto_tree_add_item(greeting_tree, hf_mysql_salt, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
718 offset += lenstr;
720 /* rest is optional */
721 if (!tvb_reported_length_remaining(tvb, offset)) return offset;
723 /* 2 bytes CAPS */
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);
736 offset += 13;
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);
742 offset += lenstr;
745 return offset;
749 static int
750 mysql_dissect_login(tvbuff_t *tvb, packet_info *pinfo, int offset,
751 proto_tree *tree, mysql_conn_data_t *conn_data)
753 gint lenstr;
755 proto_item *tf;
756 proto_item *login_tree= NULL;
758 /* after login there can be OK or DENIED */
759 conn_data->state = RESPONSE_OK;
761 if (tree) {
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);
773 offset += 4;
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);
782 offset += 3;
785 /* User name */
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);
789 offset += lenstr;
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);
797 offset += 1;
798 } else {
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);
804 offset += lenstr;
806 /* optional: initial schema */
807 if (conn_data->clnt_caps & MYSQL_CAPS_CD)
809 lenstr= my_tvb_strsize(tvb,offset);
810 if(lenstr<0){
811 return 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);
817 offset += lenstr;
820 return offset;
824 static void
825 mysql_dissect_exec_string(tvbuff_t *tvb, int *param_offset, proto_item *field_tree)
827 guint32 param_len32;
828 guint8 param_len;
830 param_len = tvb_get_guint8(tvb, *param_offset);
832 switch (param_len) {
833 case 0xfc: /* 252 - 64k chars */
834 *param_offset += 1;
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;
839 break;
840 case 0xfd: /* 64k - 16M chars */
841 *param_offset += 1;
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;
846 break;
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;
851 break;
855 static void
856 mysql_dissect_exec_time(tvbuff_t *tvb, int *param_offset, proto_item *field_tree)
858 guint8 param_len;
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);
863 *param_offset += 1;
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;
887 static void
888 mysql_dissect_exec_datetime(tvbuff_t *tvb, int *param_offset, proto_item *field_tree)
890 guint8 param_len;
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);
895 *param_offset += 1;
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;
921 static void
922 mysql_dissect_exec_primitive(tvbuff_t *tvb, int *param_offset,
923 proto_item *field_tree, const int hfindex,
924 const int offset)
926 proto_tree_add_item(field_tree, hfindex, tvb,
927 *param_offset, offset, ENC_LITTLE_ENDIAN);
928 *param_offset += offset;
931 static void
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);
937 static void
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);
943 static void
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);
949 static void
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);
955 static void
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);
961 static void
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);
967 static void
968 mysql_dissect_exec_null(tvbuff_t *tvb _U_, int *param_offset _U_, proto_item *field_tree _U_)
971 static char
972 mysql_dissect_exec_param(proto_item *req_tree, tvbuff_t *tvb, int *offset,
973 int *param_offset, guint8 param_flags,
974 packet_info *pinfo)
976 guint8 param_type, param_unsigned;
977 proto_item *tf;
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);
991 return 1;
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);
997 return 1;
999 dissector_index++;
1001 return 0;
1004 static int
1005 mysql_dissect_request(tvbuff_t *tvb,packet_info *pinfo, int offset,
1006 proto_tree *tree, mysql_conn_data_t *conn_data)
1008 gint opcode;
1009 gint lenstr;
1010 proto_item *tf = NULL, *ti;
1011 proto_item *req_tree = NULL;
1012 guint32 stmt_id;
1013 my_stmt_data_t *stmt_data;
1014 int stmt_pos, param_offset;
1016 if (tree) {
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)"));
1026 offset += 1;
1029 switch (opcode) {
1031 case MYSQL_QUIT:
1032 break;
1034 case MYSQL_PROCESS_INFO:
1035 conn_data->state = RESPONSE_TABULAR;
1036 break;
1038 case MYSQL_DEBUG:
1039 case MYSQL_PING:
1040 conn_data->state = RESPONSE_OK;
1041 break;
1043 case MYSQL_STATISTICS:
1044 conn_data->state = RESPONSE_MESSAGE;
1045 break;
1047 case MYSQL_INIT_DB:
1048 case MYSQL_CREATE_DB:
1049 case MYSQL_DROP_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);
1052 offset += lenstr;
1053 conn_data->state = RESPONSE_OK;
1054 break;
1056 case MYSQL_QUERY:
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));
1062 offset += lenstr;
1063 conn_data->state = RESPONSE_TABULAR;
1064 break;
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);
1069 offset += lenstr;
1070 conn_data->state = RESPONSE_PREPARE;
1071 break;
1073 case MYSQL_STMT_CLOSE:
1074 proto_tree_add_item(req_tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1075 offset += 4;
1076 conn_data->state = REQUEST;
1077 break;
1079 case MYSQL_STMT_RESET:
1080 proto_tree_add_item(req_tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1081 offset += 4;
1082 conn_data->state = RESPONSE_OK;
1083 break;
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);
1088 offset += lenstr;
1089 conn_data->state = RESPONSE_SHOW_FIELDS;
1090 break;
1092 case MYSQL_PROCESS_KILL:
1093 proto_tree_add_item(req_tree, hf_mysql_thd_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1094 offset += 4;
1095 conn_data->state = RESPONSE_OK;
1096 break;
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);
1101 offset += lenstr;
1103 lenstr = tvb_strsize(tvb, offset);
1104 proto_tree_add_item(req_tree, hf_mysql_passwd, tvb, offset, lenstr, ENC_NA);
1105 offset += lenstr;
1107 lenstr = my_tvb_strsize(tvb, offset);
1108 proto_tree_add_item(req_tree, hf_mysql_schema, tvb, offset, lenstr, ENC_ASCII|ENC_NA);
1109 offset += lenstr;
1111 conn_data->state= RESPONSE_OK;
1112 break;
1114 case MYSQL_REFRESH:
1116 proto_item *tff;
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);
1131 offset += 1;
1132 conn_data->state= RESPONSE_OK;
1133 break;
1135 case MYSQL_SHUTDOWN:
1136 proto_tree_add_item(req_tree, hf_mysql_shutdown, tvb, offset, 1, ENC_NA);
1137 offset += 1;
1138 conn_data->state = RESPONSE_OK;
1139 break;
1141 case MYSQL_SET_OPTION:
1142 proto_tree_add_item(req_tree, hf_mysql_option, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1143 offset += 2;
1144 conn_data->state = RESPONSE_OK;
1145 break;
1147 case MYSQL_STMT_FETCH:
1148 proto_tree_add_item(req_tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1149 offset += 4;
1151 proto_tree_add_item(req_tree, hf_mysql_num_rows, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1152 offset += 4;
1153 conn_data->state = RESPONSE_TABULAR;
1154 break;
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);
1159 offset += 4;
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);
1170 offset += 2;
1172 /* rest is data */
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);
1177 offset += lenstr;
1178 conn_data->state = REQUEST;
1179 break;
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);
1184 offset += 4;
1186 if (conn_data->major_version >= 5) {
1187 proto_tree_add_item(req_tree, hf_mysql_exec_flags5, tvb, offset, 1, ENC_NA);
1188 } else {
1189 proto_tree_add_item(req_tree, hf_mysql_exec_flags4, tvb, offset, 1, ENC_NA);
1191 offset += 1;
1193 proto_tree_add_item(req_tree, hf_mysql_exec_iter, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1194 offset += 4;
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) {
1199 guint8 stmt_bound;
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);
1203 offset += 1;
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, &param_offset,
1208 stmt_data->param_flags[stmt_pos], pinfo))
1209 break;
1211 offset = param_offset;
1214 } else {
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);
1220 offset += lenstr;
1222 #if 0
1223 /* FIXME: rest needs metadata about statement */
1224 #else
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");
1230 offset += lenstr;
1231 #endif
1232 conn_data->state= RESPONSE_TABULAR;
1233 break;
1235 case MYSQL_BINLOG_DUMP:
1236 proto_tree_add_item(req_tree, hf_mysql_binlog_position, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1237 offset += 4;
1239 proto_tree_add_item(req_tree, hf_mysql_binlog_flags, tvb, offset, 2, ENC_NA);
1240 offset += 2;
1242 proto_tree_add_item(req_tree, hf_mysql_binlog_server_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1243 offset += 4;
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);
1250 offset += lenstr;
1252 conn_data->state = REQUEST;
1253 break;
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;
1262 break;
1264 default:
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;
1271 return offset;
1275 static int
1276 mysql_dissect_response(tvbuff_t *tvb, packet_info *pinfo, int offset,
1277 proto_tree *tree, mysql_conn_data_t *conn_data)
1279 gint response_code;
1280 gint lenstr;
1281 gint server_status = 0;
1282 proto_item *ti;
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);
1295 offset += 1;
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;
1309 } else {
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;
1315 } else {
1316 conn_data->state= REQUEST;
1318 } else if (conn_data->state == PREPARED_FIELDS) {
1319 conn_data->state= REQUEST;
1320 } else {
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);
1332 } else {
1333 offset = mysql_dissect_result_header(tvb, pinfo, offset, tree, conn_data);
1337 else {
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);
1342 offset += lenstr;
1344 conn_data->state = REQUEST;
1345 break;
1347 case RESPONSE_TABULAR:
1348 offset = mysql_dissect_result_header(tvb, pinfo, offset, tree, conn_data);
1349 break;
1351 case FIELD_PACKET:
1352 case RESPONSE_SHOW_FIELDS:
1353 case RESPONSE_PREPARE:
1354 case PREPARED_PARAMETERS:
1355 offset = mysql_dissect_field_packet(tvb, offset, tree, conn_data);
1356 break;
1358 case ROW_PACKET:
1359 offset = mysql_dissect_row_packet(tvb, offset, tree);
1360 break;
1362 case PREPARED_FIELDS:
1363 offset = mysql_dissect_field_packet(tvb, offset, tree, conn_data);
1364 break;
1366 default:
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;
1374 return offset;
1378 static int
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);
1385 offset += 2;
1387 if (tvb_get_guint8(tvb, offset) == '#')
1389 offset += 1;
1390 proto_tree_add_item(tree, hf_mysql_sqlstate, tvb, offset, 5, ENC_ASCII|ENC_NA);
1391 offset += 5;
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);
1397 return offset;
1401 static int
1402 mysql_dissect_ok_packet(tvbuff_t *tvb, packet_info *pinfo, int offset,
1403 proto_tree *tree, mysql_conn_data_t *conn_data)
1405 gint lenstr;
1406 guint64 affected_rows;
1407 guint64 insert_id;
1408 int fle;
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);
1414 offset += fle;
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);
1420 offset += fle;
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);
1428 offset += 2;
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);
1436 offset += lenstr;
1439 conn_data->state = REQUEST;
1440 return offset;
1444 static int
1445 mysql_dissect_server_status(tvbuff_t *tvb, int offset, proto_tree *tree)
1447 proto_item *tf;
1448 proto_item *stat_tree;
1450 if (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);
1464 offset += 2;
1466 return offset;
1470 static int
1471 mysql_dissect_caps_server(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *caps)
1473 proto_item *tf;
1474 proto_item *cap_tree;
1476 *caps= tvb_get_letohs(tvb, offset);
1478 if (tree) {
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);
1499 offset += 2;
1500 return offset;
1503 static int
1504 mysql_dissect_caps_client(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *caps)
1506 proto_item *tf;
1507 proto_item *cap_tree;
1509 *caps= tvb_get_letohs(tvb, offset);
1511 if (tree) {
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);
1532 offset += 2;
1533 return offset;
1535 static int
1536 mysql_dissect_ext_caps_client(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *ext_caps)
1538 proto_item *tf;
1539 proto_item *extcap_tree;
1540 *ext_caps= tvb_get_letohs(tvb, offset);
1541 if (tree) {
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);
1548 offset += 2;
1549 return offset;
1553 static int
1554 mysql_dissect_result_header(tvbuff_t *tvb, packet_info *pinfo, int offset,
1555 proto_tree *tree, mysql_conn_data_t *conn_data)
1557 gint fle;
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);
1564 offset += fle;
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);
1569 offset += fle;
1572 if (num_fields) {
1573 conn_data->state = FIELD_PACKET;
1574 } else {
1575 conn_data->state = ROW_PACKET;
1578 return offset;
1583 * Add length encoded string to tree
1585 static int
1586 mysql_field_add_lestring(tvbuff_t *tvb, int offset, proto_tree *tree, int field)
1588 guint64 lelen;
1589 guint8 is_null;
1591 offset += tvb_get_fle(tvb, offset, &lelen, &is_null);
1592 if(is_null)
1593 proto_tree_add_string(tree, field, tvb, offset, 4, "NULL");
1594 else
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);
1601 else {
1602 offset += (int)lelen;
1605 return offset;
1609 static int
1610 mysql_dissect_field_packet(tvbuff_t *tvb, int offset, proto_tree *tree, mysql_conn_data_t *conn_data _U_)
1612 proto_item *tf;
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);
1657 return offset;
1661 static int
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);
1668 return offset;
1672 static int
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;
1676 guint32 stmt_id;
1677 int flagsize;
1679 /* 0, marker for OK packet */
1680 offset += 1;
1681 proto_tree_add_item(tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1682 stmt_id = tvb_get_letohl(tvb, offset);
1683 offset += 4;
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);
1686 offset += 2;
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);
1695 offset += 2;
1696 /* Filler */
1697 offset += 1;
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;
1704 else
1705 conn_data->state = REQUEST;
1707 return offset + tvb_reported_length_remaining(tvb, offset);
1713 get length of string in packet buffer
1715 SYNOPSIS
1716 my_tvb_strsize()
1717 tvb packet buffer
1718 offset current offset
1720 DESCRIPTION
1721 deliver length of string, delimited by either \0 or end of buffer
1723 RETURN VALUE
1724 length of string found, including \0 (if present)
1727 static gint
1728 my_tvb_strsize(tvbuff_t *tvb, int offset)
1730 gint len = tvb_strnlen(tvb, offset, -1);
1731 if (len == -1) {
1732 len = tvb_reported_length_remaining(tvb, offset);
1733 } else {
1734 len++; /* the trailing \0 */
1736 return len;
1741 read "field length encoded" value from packet buffer
1743 SYNOPSIS
1744 tvb_get_fle()
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
1750 DESCRIPTION
1751 read FLE from packet buffer and store its value and ISNULL flag
1752 in caller provided variables
1754 RETURN VALUE
1755 length of FLE
1757 static int
1758 tvb_get_fle(tvbuff_t *tvb, int offset, guint64 *res, guint8 *is_null)
1760 guint8 prefix;
1762 prefix = tvb_get_guint8(tvb, offset);
1764 if (is_null)
1765 *is_null = 0;
1767 switch (prefix) {
1768 case 251:
1769 if (res)
1770 *res = 0;
1771 if (is_null)
1772 *is_null = 1;
1773 break;
1774 case 252:
1775 if (res)
1776 *res = tvb_get_letohs(tvb, offset+1);
1777 return 3;
1778 case 253:
1779 if (res)
1780 *res = tvb_get_letohl(tvb, offset+1);
1781 return 5;
1782 case 254:
1783 if (res)
1784 *res = tvb_get_letoh64(tvb, offset+1);
1785 return 9;
1786 default:
1787 if (res)
1788 *res = prefix;
1791 return 1;
1794 /* dissector helper: length of PDU */
1795 static guint
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 */
1803 static int
1804 dissect_mysql_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1806 proto_tree *mysql_tree= NULL;
1807 proto_item *ti;
1808 conversation_t *conversation;
1809 int offset = 0;
1810 guint packet_number;
1811 gboolean is_response;
1812 mysql_conn_data_t *conn_data;
1813 #ifdef CTDEBUG
1814 mysql_state_t conn_state_in, conn_state_out, frame_state;
1815 guint64 generation;
1816 proto_item *pi;
1817 #endif
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);
1825 if (!conn_data) {
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());
1832 #ifdef CTDEBUG
1833 conn_data->generation= 0;
1834 #endif
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;
1868 if (tree) {
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);
1873 offset+= 3;
1875 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MySQL");
1877 if (pinfo->destport == pinfo->match_uint) {
1878 is_response= FALSE;
1879 } else {
1880 is_response= TRUE;
1883 packet_number = tvb_get_guint8(tvb, offset);
1884 proto_tree_add_item(mysql_tree, hf_mysql_packet_number, tvb, offset, 1, ENC_NA);
1885 offset += 1;
1887 #ifdef CTDEBUG
1888 conn_state_in= conn_data->state;
1889 frame_state = mysql_frame_data_p->state;
1890 generation= conn_data->generation;
1891 if (tree) {
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)"),
1898 conn_state_in);
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)"),
1902 frame_state);
1903 PROTO_ITEM_SET_GENERATED(pi);
1905 #endif
1907 if (is_response) {
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);
1911 } else {
1912 col_set_str(pinfo->cinfo, COL_INFO, "Response");
1913 offset = mysql_dissect_response(tvb, pinfo, offset, mysql_tree, conn_data);
1915 } else {
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);
1919 } else {
1920 col_set_str(pinfo->cinfo, COL_INFO, "Request");
1921 offset = mysql_dissect_request(tvb, pinfo, offset, mysql_tree, conn_data);
1925 #ifdef CTDEBUG
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)"),
1930 conn_state_out);
1931 PROTO_ITEM_SET_GENERATED(pi);
1932 #endif
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 */
1944 static int
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,
1960 NULL, HFILL }},
1962 { &hf_mysql_packet_number,
1963 { "Packet Number", "mysql.packet_number",
1964 FT_UINT8, BASE_DEC, NULL, 0x0,
1965 NULL, HFILL }},
1967 { &hf_mysql_request,
1968 { "Request Command", "mysql.request",
1969 FT_NONE, BASE_NONE, NULL, 0x0,
1970 NULL, HFILL }},
1972 { &hf_mysql_command,
1973 { "Command", "mysql.command",
1974 FT_UINT8, BASE_DEC, VALS(mysql_command_vals), 0x0,
1975 NULL, HFILL }},
1977 { &hf_mysql_error_code,
1978 { "Error Code", "mysql.error_code",
1979 FT_UINT16, BASE_DEC, NULL, 0x0,
1980 NULL, HFILL }},
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,
1990 NULL, HFILL }},
1992 { &hf_mysql_message,
1993 { "Message", "mysql.message",
1994 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1995 NULL, HFILL }},
1997 { &hf_mysql_server_greeting,
1998 { "Server Greeting", "mysql.server_greeting",
1999 FT_NONE, BASE_NONE, NULL, 0x0,
2000 NULL, HFILL }},
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,
2025 NULL, HFILL }},
2027 { &hf_mysql_cap_found_rows,
2028 { "Found Rows","mysql.caps.fr",
2029 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_FR,
2030 NULL, HFILL }},
2032 { &hf_mysql_cap_long_flag,
2033 { "Long Column Flags","mysql.caps.lf",
2034 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_LF,
2035 NULL, HFILL }},
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,
2040 NULL, HFILL }},
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,
2045 NULL, HFILL }},
2047 { &hf_mysql_cap_compress,
2048 { "Can use compression protocol","mysql.caps.cp",
2049 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_CP,
2050 NULL, HFILL }},
2052 { &hf_mysql_cap_odbc,
2053 { "ODBC Client","mysql.caps.ob",
2054 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_OB,
2055 NULL, HFILL }},
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,
2060 NULL, HFILL }},
2062 { &hf_mysql_cap_ignore_space,
2063 { "Ignore Spaces before '('","mysql.caps.is",
2064 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_IS,
2065 NULL, HFILL }},
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,
2070 NULL, HFILL }},
2072 { &hf_mysql_cap_interactive,
2073 { "Interactive Client","mysql.caps.ia",
2074 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_IA,
2075 NULL, HFILL }},
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,
2080 NULL, HFILL }},
2082 { &hf_mysql_cap_ignore_sigpipe,
2083 { "Ignore sigpipes","mysql.caps.ii",
2084 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_II,
2085 NULL, HFILL }},
2087 { &hf_mysql_cap_transactions,
2088 { "Knows about transactions","mysql.caps.ta",
2089 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_TA,
2090 NULL, HFILL }},
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,
2095 NULL, HFILL }},
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,
2100 NULL, HFILL }},
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,
2110 NULL, HFILL }},
2112 { &hf_mysql_cap_multi_results,
2113 { "Supports multiple results","mysql.caps.mr",
2114 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_MR,
2115 NULL, HFILL }},
2117 { &hf_mysql_login_request,
2118 { "Login Request", "mysql.login_request",
2119 FT_NONE, BASE_NONE, NULL, 0x0,
2120 NULL, HFILL }},
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,
2135 NULL, HFILL }},
2137 { &hf_mysql_user,
2138 { "Username", "mysql.user",
2139 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2140 "Login Username", HFILL }},
2142 { &hf_mysql_schema,
2143 { "Schema", "mysql.schema",
2144 FT_STRING, BASE_NONE, NULL, 0x0,
2145 "Login Schema", HFILL }},
2147 { &hf_mysql_salt,
2148 { "Salt", "mysql.salt",
2149 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2150 NULL, HFILL }},
2152 { &hf_mysql_salt2,
2153 { "Salt", "mysql.salt2",
2154 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2155 NULL, HFILL }},
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,
2175 NULL, HFILL }},
2177 { &hf_mysql_stat_ac,
2178 { "AUTO_COMMIT", "mysql.stat.ac",
2179 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_AC,
2180 NULL, HFILL }},
2182 { &hf_mysql_stat_mr,
2183 { "More results", "mysql.stat.mr",
2184 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_MR,
2185 NULL, HFILL }},
2187 { &hf_mysql_stat_mu,
2188 { "Multi query - more resultsets", "mysql.stat.mu",
2189 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_MU,
2190 NULL, HFILL }},
2192 { &hf_mysql_stat_bi,
2193 { "Bad index used", "mysql.stat.bi",
2194 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_BI,
2195 NULL, HFILL }},
2197 { &hf_mysql_stat_ni,
2198 { "No index used", "mysql.stat.ni",
2199 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_NI,
2200 NULL, HFILL }},
2202 { &hf_mysql_stat_cr,
2203 { "Cursor exists", "mysql.stat.cr",
2204 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_CR,
2205 NULL, HFILL }},
2207 { &hf_mysql_stat_lr,
2208 { "Last row sebd", "mysql.stat.lr",
2209 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_LR,
2210 NULL, HFILL }},
2212 { &hf_mysql_stat_dr,
2213 { "database dropped", "mysql.stat.dr",
2214 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_DR,
2215 NULL, HFILL }},
2217 { &hf_mysql_stat_bs,
2218 { "No backslash escapes", "mysql.stat.bs",
2219 FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_STAT_BS,
2220 NULL, HFILL }},
2222 { &hf_mysql_refresh,
2223 { "Refresh Option", "mysql.refresh",
2224 FT_UINT8, BASE_HEX, NULL, 0x0,
2225 NULL, HFILL }},
2227 { &hf_mysql_rfsh_grants,
2228 { "reload permissions", "mysql.rfsh.grants",
2229 FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_GRANT,
2230 NULL, HFILL }},
2232 { &hf_mysql_rfsh_log,
2233 { "flush logfiles", "mysql.rfsh.log",
2234 FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_LOG,
2235 NULL, HFILL }},
2237 { &hf_mysql_rfsh_tables,
2238 { "flush tables", "mysql.rfsh.tables",
2239 FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_TABLES,
2240 NULL, HFILL }},
2242 { &hf_mysql_rfsh_hosts,
2243 { "flush hosts", "mysql.rfsh.hosts",
2244 FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_HOSTS,
2245 NULL, HFILL }},
2247 { &hf_mysql_rfsh_status,
2248 { "reset statistics", "mysql.rfsh.status",
2249 FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_STATUS,
2250 NULL, HFILL }},
2252 { &hf_mysql_rfsh_threads,
2253 { "empty thread cache", "mysql.rfsh.threads",
2254 FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_THREADS,
2255 NULL, HFILL }},
2257 { &hf_mysql_rfsh_slave,
2258 { "flush slave status", "mysql.rfsh.slave",
2259 FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_SLAVE,
2260 NULL, HFILL }},
2262 { &hf_mysql_rfsh_master,
2263 { "flush master status", "mysql.rfsh.master",
2264 FT_BOOLEAN, 8, TFS(&tfs_set_notset), MYSQL_RFSH_MASTER,
2265 NULL, HFILL }},
2267 { &hf_mysql_unused,
2268 { "Unused", "mysql.unused",
2269 FT_STRING, BASE_NONE, NULL, 0x0,
2270 NULL, HFILL }},
2272 { &hf_mysql_passwd,
2273 { "Password", "mysql.passwd",
2274 FT_BYTES, BASE_NONE, NULL, 0x0,
2275 NULL, HFILL }},
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,
2285 NULL, HFILL }},
2287 { &hf_mysql_insert_id,
2288 { "Last INSERT ID", "mysql.insert_id",
2289 FT_UINT64, BASE_DEC, NULL, 0x0,
2290 NULL, HFILL }},
2292 { &hf_mysql_num_warn,
2293 { "Warnings", "mysql.warnings",
2294 FT_UINT16, BASE_DEC, NULL, 0x0,
2295 NULL, HFILL }},
2297 { &hf_mysql_thd_id,
2298 { "Thread ID", "mysql.thd_id",
2299 FT_UINT32, BASE_DEC, NULL, 0x0,
2300 NULL, HFILL }},
2302 { &hf_mysql_stmt_id,
2303 { "Statement ID", "mysql.stmt_id",
2304 FT_UINT32, BASE_DEC, NULL, 0x0,
2305 NULL, HFILL }},
2307 { &hf_mysql_query,
2308 { "Statement", "mysql.query",
2309 FT_STRING, BASE_NONE, NULL, 0x0,
2310 NULL, HFILL }},
2312 { &hf_mysql_shutdown,
2313 { "Shutdown Level", "mysql.shutdown",
2314 FT_UINT8, BASE_DEC, VALS(mysql_shutdown_vals), 0x0,
2315 NULL, HFILL }},
2317 { &hf_mysql_option,
2318 { "Option", "mysql.option",
2319 FT_UINT16, BASE_DEC, VALS(mysql_option_vals), 0x0,
2320 NULL, HFILL }},
2322 { &hf_mysql_param,
2323 { "Parameter", "mysql.param",
2324 FT_UINT16, BASE_DEC, NULL, 0x0,
2325 NULL, HFILL }},
2327 { &hf_mysql_num_params,
2328 { "Number of parameter", "mysql.num_params",
2329 FT_UINT16, BASE_DEC, NULL, 0x0,
2330 NULL, HFILL }},
2332 { &hf_mysql_num_rows,
2333 { "Rows to fetch", "mysql.num_rows",
2334 FT_UINT32, BASE_DEC, NULL, 0x0,
2335 NULL, HFILL }},
2337 { &hf_mysql_exec_flags4,
2338 { "Flags (unused)", "mysql.exec_flags",
2339 FT_UINT8, BASE_DEC, NULL, 0x0,
2340 NULL, HFILL }},
2342 { &hf_mysql_exec_flags5,
2343 { "Flags", "mysql.exec_flags",
2344 FT_UINT8, BASE_DEC, VALS(mysql_exec_flags_vals), 0x0,
2345 NULL, HFILL }},
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,
2350 NULL, HFILL }},
2352 { &hf_mysql_exec_iter,
2353 { "Iterations (unused)", "mysql.exec_iter",
2354 FT_UINT32, BASE_DEC, NULL, 0x0,
2355 NULL, HFILL }},
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,
2375 NULL, HFILL }},
2377 { &hf_mysql_eof,
2378 { "EOF marker", "mysql.eof",
2379 FT_UINT8, BASE_DEC, NULL, 0x0,
2380 NULL, HFILL }},
2382 { &hf_mysql_num_fields,
2383 { "Number of fields", "mysql.num_fields",
2384 FT_UINT64, BASE_DEC, NULL, 0x0,
2385 NULL, HFILL }},
2387 { &hf_mysql_extra,
2388 { "Extra data", "mysql.extra",
2389 FT_UINT64, BASE_DEC, NULL, 0x0,
2390 NULL, HFILL }},
2392 { &hf_mysql_fld_catalog,
2393 { "Catalog", "mysql.field.catalog",
2394 FT_STRING, BASE_NONE, NULL, 0x0,
2395 "Field: catalog", HFILL }},
2397 { &hf_mysql_fld_db,
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,
2520 NULL, HFILL }},
2522 { &hf_mysql_exec_unsigned,
2523 { "Unsigned", "mysql.exec.unsigned",
2524 FT_UINT8, BASE_DEC, NULL, 0x0,
2525 NULL, HFILL }},
2527 { &hf_mysql_exec_field_longlong,
2528 { "Value", "mysql.exec.field.longlong",
2529 FT_INT64, BASE_DEC, NULL, 0x0,
2530 NULL, HFILL }},
2532 { &hf_mysql_exec_field_string,
2533 { "Value", "mysql.exec.field.string",
2534 FT_UINT_STRING, BASE_NONE, NULL, 0x0,
2535 NULL, HFILL }},
2537 { &hf_mysql_exec_field_double,
2538 { "Value", "mysql.exec.field.double",
2539 FT_DOUBLE, BASE_NONE, NULL, 0x0,
2540 NULL, HFILL }},
2542 { &hf_mysql_exec_field_datetime_length,
2543 { "Length", "mysql.exec.field.datetime.length",
2544 FT_INT8, BASE_DEC, NULL, 0x0,
2545 NULL, HFILL }},
2547 { &hf_mysql_exec_field_year,
2548 { "Year", "mysql.exec.field.year",
2549 FT_INT16, BASE_DEC, NULL, 0x0,
2550 NULL, HFILL }},
2552 { &hf_mysql_exec_field_month,
2553 { "Month", "mysql.exec.field.month",
2554 FT_INT8, BASE_DEC, NULL, 0x0,
2555 NULL, HFILL }},
2557 { &hf_mysql_exec_field_day,
2558 { "Day", "mysql.exec.field.day",
2559 FT_INT8, BASE_DEC, NULL, 0x0,
2560 NULL, HFILL }},
2562 { &hf_mysql_exec_field_hour,
2563 { "Hour", "mysql.exec.field.hour",
2564 FT_INT8, BASE_DEC, NULL, 0x0,
2565 NULL, HFILL }},
2567 { &hf_mysql_exec_field_minute,
2568 { "Minute", "mysql.exec.field.minute",
2569 FT_INT8, BASE_DEC, NULL, 0x0,
2570 NULL, HFILL }},
2572 { &hf_mysql_exec_field_second,
2573 { "Second", "mysql.exec.field.second",
2574 FT_INT8, BASE_DEC, NULL, 0x0,
2575 NULL, HFILL }},
2577 { &hf_mysql_exec_field_second_b,
2578 { "Billionth of a second", "mysql.exec.field.secondb",
2579 FT_INT32, BASE_DEC, NULL, 0x0,
2580 NULL, HFILL }},
2582 { &hf_mysql_exec_field_long,
2583 { "Value", "mysql.exec.field.long",
2584 FT_INT32, BASE_DEC, NULL, 0x0,
2585 NULL, HFILL }},
2587 { &hf_mysql_exec_field_tiny,
2588 { "Value", "mysql.exec.field.tiny",
2589 FT_INT8, BASE_DEC, NULL, 0x0,
2590 NULL, HFILL }},
2592 { &hf_mysql_exec_field_short,
2593 { "Value", "mysql.exec.field.short",
2594 FT_INT16, BASE_DEC, NULL, 0x0,
2595 NULL, HFILL }},
2597 { &hf_mysql_exec_field_float,
2598 { "Value", "mysql.exec.field.float",
2599 FT_FLOAT, BASE_NONE, NULL, 0x0,
2600 NULL, HFILL }},
2602 { &hf_mysql_exec_field_time_length,
2603 { "Length", "mysql.exec.field.time.length",
2604 FT_INT8, BASE_DEC, NULL, 0x0,
2605 NULL, HFILL }},
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,
2610 NULL, HFILL }},
2612 { &hf_mysql_exec_field_time_days,
2613 { "Days", "mysql.exec.field.time.days",
2614 FT_INT32, BASE_DEC, NULL, 0x0,
2615 NULL, HFILL }},
2618 static gint *ett[]=
2620 &ett_mysql,
2621 &ett_server_greeting,
2622 &ett_login_request,
2623 &ett_caps,
2624 &ett_extcaps,
2625 &ett_stat,
2626 &ett_request,
2627 &ett_refresh,
2628 &ett_field_flags,
2629 &ett_exec_param
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.",
2655 &mysql_desegment);
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.",
2659 &mysql_showquery);
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
2675 * Local variables:
2676 * c-basic-offset: 8
2677 * tab-width: 8
2678 * indent-tabs-mode: t
2679 * End:
2681 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2682 * :indentSize=8:tabSize=8:noTabs=false: