aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-mysql.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-mysql.c')
-rw-r--r--epan/dissectors/packet-mysql.c819
1 files changed, 819 insertions, 0 deletions
diff --git a/epan/dissectors/packet-mysql.c b/epan/dissectors/packet-mysql.c
new file mode 100644
index 0000000000..bda5bf6fb3
--- /dev/null
+++ b/epan/dissectors/packet-mysql.c
@@ -0,0 +1,819 @@
+/* packet-mysql.c
+ * Routines for mysql packet dissection
+ *
+ * Huagang XIE <huagang@intruvert.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tftp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * the protocol spec at
+ * http://public.logicacmg.com/~redferni/mysql/MySQL-Protocol.html
+ * and MySQL source code
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+
+#include "packet-tcp.h"
+#include "reassemble.h"
+#include "prefs.h"
+
+/* Capabilities */
+#define MYSQL_CAPS_LP 0x0001
+#define MYSQL_CAPS_FR 0x0002
+#define MYSQL_CAPS_LF 0x0004
+#define MYSQL_CAPS_CD 0x0008
+#define MYSQL_CAPS_NS 0x0010
+#define MYSQL_CAPS_CP 0x0020
+#define MYSQL_CAPS_OB 0x0040
+#define MYSQL_CAPS_LI 0x0080
+#define MYSQL_CAPS_IS 0x0100
+#define MYSQL_CAPS_CU 0x0200
+#define MYSQL_CAPS_IA 0x0400
+#define MYSQL_CAPS_SL 0x0800
+#define MYSQL_CAPS_II 0x1000
+#define MYSQL_CAPS_TA 0x2000
+
+static int proto_mysql = -1;
+static int hf_mysql_packet_length= -1;
+static int hf_mysql_packet_number= -1;
+static int hf_mysql_opcode= -1;
+static int hf_mysql_response_code= -1;
+static int hf_mysql_error_code= -1;
+static int hf_mysql_payload= -1;
+static int hf_mysql_protocol= -1;
+static int hf_mysql_caps= -1;
+static int hf_mysql_cap_long_password= -1;
+static int hf_mysql_cap_found_rows= -1;
+static int hf_mysql_cap_long_flag= -1;
+static int hf_mysql_cap_connect_with_db= -1;
+static int hf_mysql_cap_no_schema= -1;
+static int hf_mysql_cap_compress= -1;
+static int hf_mysql_cap_odbc= -1;
+static int hf_mysql_cap_local_files= -1;
+static int hf_mysql_cap_ignore_space= -1;
+static int hf_mysql_cap_change_user= -1;
+static int hf_mysql_cap_interactive= -1;
+static int hf_mysql_cap_ssl= -1;
+static int hf_mysql_cap_ignore_sigpipe= -1;
+static int hf_mysql_cap_transactions= -1;
+static int hf_mysql_version = -1;
+static int hf_mysql_max_packet= -1;
+static int hf_mysql_user= -1;
+static int hf_mysql_password= -1;
+static int hf_mysql_thread_id = -1;
+static int hf_mysql_salt= -1;
+static int hf_mysql_charset= -1;
+static int hf_mysql_status= -1;
+static int hf_mysql_unused= -1;
+static int hf_mysql_parameter= -1;
+
+static gint ett_mysql = -1;
+static gint ett_server_greeting = -1;
+static gint ett_caps = -1;
+static gint ett_request = -1;
+
+static gboolean mysql_desegment = TRUE;
+
+#define TCP_PORT_MySQL 3306
+
+#define MySQL_SLEEP 0
+#define MySQL_QUIT 1
+#define MySQL_INIT_DB 2
+#define MySQL_QUERY 3
+#define MySQL_FIELD_LIST 4
+#define MySQL_CREATE_DB 5
+#define MySQL_DROP_DB 6
+#define MySQL_REFRESH 7
+#define MySQL_SHUTDOWN 8
+#define MySQL_STATISTICS 9
+#define MySQL_PROCESS_INFO 10
+#define MySQL_CONNECT 11
+#define MySQL_PROCESS_KILL 12
+#define MySQL_DEBUG 13
+#define MySQL_PING 14
+#define MySQL_TIME 15
+#define MySQL_DELAY_INSERT 16
+#define MySQL_CHANGE_USER 17
+#define MySQL_BINLOG_DUMP 18
+#define MySQL_TABLE_DUMP 19
+#define MySQL_CONNECT_OUT 20
+
+
+static const value_string mysql_opcode_vals[] = {
+ { MySQL_SLEEP, "SLEEP" },
+ { MySQL_QUIT, "Quit" },
+ { MySQL_INIT_DB, "Init Database" },
+ { MySQL_QUERY, "Query" },
+ { MySQL_FIELD_LIST, "Field List" },
+ { MySQL_CREATE_DB, "Create Database" },
+ { MySQL_DROP_DB , "Drop Database" },
+ { MySQL_REFRESH , "Refresh" },
+ { MySQL_SHUTDOWN , "Shutdown" },
+ { MySQL_STATISTICS , "Statistics" },
+ { MySQL_PROCESS_INFO , "Process Info" },
+ { MySQL_CONNECT , "Connect" },
+ { MySQL_PROCESS_KILL , "Process Kill" },
+ { MySQL_DEBUG , "Debug" },
+ { MySQL_PING , "Ping" },
+ { MySQL_TIME , "Time" },
+ { MySQL_DELAY_INSERT , "Delay Insert" },
+ { MySQL_CHANGE_USER , "Change User" },
+ { MySQL_BINLOG_DUMP , "Binlog Dump" },
+ { MySQL_TABLE_DUMP, "Table Dump" },
+ { MySQL_CONNECT_OUT, "Table Connect Out" },
+ { 0, NULL }
+};
+
+static const value_string mysql_status_vals[] = {
+ {1, "IN_TRANS" },
+ {2, "AUTOCOMMIT"},
+ { 0, NULL }
+};
+static const value_string mysql_charset_vals[] = {
+ {1, "big5"},
+ {2, "czech"},
+ {3,"dec8"},
+ {4, "dos" },
+ {5,"german1"},
+ {6,"hp8"},
+ {7,"koi8_ru"},
+ {8,"latin1"},
+ {9,"latin2"},
+ {9,"swe7 "},
+ {10,"usa7"},
+ {11,"ujis"},
+ {12,"sjis"},
+ {13,"cp1251"},
+ {14,"danish"},
+ {15,"hebrew"},
+ {16,"win1251"},
+ {17,"tis620"},
+ {18,"euc_kr"},
+ {19,"estonia"},
+ {20,"hungarian"},
+ {21,"koi8_ukr"},
+ {22,"win1251ukr"},
+ {23,"gb2312"},
+ {24,"greek"},
+ {25,"win1250"},
+ {26,"croat"},
+ {27,"gbk"},
+ {28,"cp1257"},
+ {29,"latin5"},
+ {0,NULL}
+};
+#if 0
+static const value_string mysql_error_code_vals[] = {
+ { 0, "Not defined" },
+ { 1, "File not found" },
+ { 2, "Access violation" },
+ { 3, "Disk full or allocation exceeded" },
+ { 4, "Illegal MySQL Operation" },
+ { 5, "Unknown transfer ID" },
+ { 6, "File already exists" },
+ { 7, "No such user" },
+ { 8, "Option negotiation failed" },
+ { 0, NULL }
+};
+#endif
+
+static guint get_mysql_pdu_len(tvbuff_t *tvb, int offset);
+static void dissect_mysql_pdu(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree);
+static int mysql_dissect_server_greeting(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree);
+static int mysql_dissect_authentication(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree);
+static int mysql_dissect_request(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree);
+static int mysql_dissect_response(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree);
+
+static void
+dissect_mysql(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ tcp_dissect_pdus(tvb, pinfo, tree, mysql_desegment, 3,
+ get_mysql_pdu_len, dissect_mysql_pdu);
+}
+
+static guint
+get_mysql_pdu_len(tvbuff_t *tvb, int offset)
+{
+ guint plen;
+
+ /*
+ * Get the length of the MySQL packet.
+ */
+ plen = tvb_get_letoh24(tvb, offset);
+
+ /*
+ * That length doesn't include the length field or the packet
+ * number itself; add them in.
+ */
+ return plen + 4;
+}
+
+static void
+dissect_mysql_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *mysql_tree = NULL;
+ proto_item *ti;
+ conversation_t *conversation;
+
+ int offset = 0;
+ guint packet_number;
+
+ gboolean is_response;
+
+ conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+
+ if (!conversation) {
+ /* create a new conversation */
+ conversation = conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ }
+
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MySQL");
+
+ if (pinfo->destport == pinfo->match_port) {
+ is_response=FALSE;
+ }else {
+ is_response=TRUE;
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_mysql, tvb, offset, -1, FALSE);
+ mysql_tree = proto_item_add_subtree(ti, ett_mysql);
+
+ proto_tree_add_item(mysql_tree, hf_mysql_packet_length, tvb,
+ offset, 3, TRUE);
+ }
+ offset += 3;
+/* packet number */
+ packet_number= tvb_get_guint8(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(mysql_tree, hf_mysql_packet_number, tvb,
+ offset, 1, packet_number);
+ }
+ offset += 1;
+
+ /*
+ * packet == 0 && response --> server greeting
+ * packet == 1 && request --> login request
+ */
+ if(is_response ) {
+ if( packet_number == 0 ) {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO, "Server Greeting" ) ;
+ }
+ offset = mysql_dissect_server_greeting(tvb,pinfo,offset,mysql_tree);
+ }else {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO, "Response" ) ;
+ }
+ offset = mysql_dissect_response(tvb,pinfo,offset,mysql_tree);
+ }
+ } else {
+ if( packet_number == 1 ) {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO, "Login Request") ;
+ }
+ offset = mysql_dissect_authentication(tvb,pinfo,offset,mysql_tree);
+ }else {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO, "Request") ;
+ }
+ offset = mysql_dissect_request(tvb,pinfo,offset,mysql_tree);
+ }
+ }
+
+/* payload */
+ if (tree && tvb_reported_length_remaining(tvb, offset) > 0) {
+ proto_tree_add_item(mysql_tree, hf_mysql_payload,
+ tvb, offset, -1, FALSE);
+ }
+}
+static int
+mysql_dissect_response(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree)
+{
+ gint response_code;
+ gint error_code;
+
+ /* response code */
+ response_code= tvb_get_guint8(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(tree, hf_mysql_response_code, tvb,
+ offset, 1, response_code);
+ }
+ offset +=1;
+
+ if(response_code== 0xff ) {
+ /* error code */
+ error_code = tvb_get_letohs(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Error Code: %x", error_code );
+ }
+ if (tree) {
+ proto_tree_add_uint(tree, hf_mysql_error_code, tvb,
+ offset, 2, error_code);
+ }
+ offset +=2;
+
+ } else {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_str(pinfo->cinfo, COL_INFO, " OK" );
+ }
+ }
+ return offset;
+}
+
+static int
+mysql_dissect_request(tvbuff_t *tvb,packet_info *pinfo,
+ int offset, proto_tree *tree)
+{
+ gint opcode;
+ gint strlen;
+ proto_item *tf;
+ proto_item *req_tree=NULL;
+
+ if(tree) {
+ tf=proto_tree_add_text(tree,tvb,offset,-1,"Command");
+ req_tree = proto_item_add_subtree(tf ,ett_request);
+ }
+
+ opcode = tvb_get_guint8(tvb, offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Command: %s",
+ val_to_str(opcode, mysql_opcode_vals, "Unknown (%u)"));
+ }
+
+ if (req_tree) {
+ proto_tree_add_uint_format(req_tree, hf_mysql_opcode, tvb,
+ offset , 1, opcode, "Command: %s (%u)",
+ val_to_str(opcode, mysql_opcode_vals, "Unknown (%u)"),opcode);
+ }
+ /* command parameter */
+
+ offset += 1;
+ if ( (strlen = tvb_length_remaining(tvb,offset)) > 0 ) {
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " : %s",
+ tvb_format_text(tvb,offset,strlen));
+ }
+
+ if (tree) {
+ proto_tree_add_item(req_tree, hf_mysql_parameter, tvb,
+ offset, strlen, FALSE );
+ }
+ offset +=strlen;
+ }
+
+ return offset;
+}
+
+
+static int
+mysql_dissect_authentication(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree)
+{
+ gint16 client_caps;
+ gint32 max_packet;
+ gint strlen;
+
+ proto_item *tf;
+ proto_item *cap_tree;
+ proto_item *login_tree=NULL;
+
+ if(tree) {
+ tf=proto_tree_add_text(tree,tvb,offset,-1,"Login Packet");
+ login_tree = proto_item_add_subtree(tf ,ett_server_greeting);
+ }
+
+ client_caps= tvb_get_letohs(tvb, offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Caps: 0x%x",client_caps) ;
+ }
+ if(tree) {
+ tf = proto_tree_add_uint_format(login_tree, hf_mysql_caps, tvb, offset , 1, client_caps, "Caps: 0x%04x ", client_caps );
+ cap_tree = proto_item_add_subtree(tf, ett_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_long_password, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_found_rows, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_long_flag, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_connect_with_db, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_no_schema, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_compress, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_odbc, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_local_files, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_ignore_space, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_change_user, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_interactive, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_ssl, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_ignore_sigpipe, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_transactions, tvb, offset, 2, client_caps);
+ }
+
+/* proto_tree_add_uint(tree, hf_mysql_client_caps, tvb,
+ offset, 2, client_caps);
+*/
+ offset +=2;
+ /* 3 bytes max packet, 16777216 - x */
+ max_packet = 0xffffff - tvb_get_letoh24(tvb, offset);
+ if(tree) {
+ proto_tree_add_uint(login_tree, hf_mysql_max_packet, tvb,
+ offset, 3, max_packet);
+ }
+ offset +=3;
+ /* User name */
+ strlen = tvb_strsize(tvb,offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " ,user: %s",
+ tvb_get_ptr(tvb,offset,strlen));
+ }
+ if (tree) {
+ proto_tree_add_item(login_tree, hf_mysql_user, tvb,
+ offset, strlen, FALSE );
+ }
+ offset +=strlen;
+
+ /* Password */
+ strlen = tvb_length_remaining(tvb,offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " ,password: %s",
+ tvb_get_ptr(tvb,offset,strlen));
+ }
+ if (tree) {
+ proto_tree_add_item(login_tree, hf_mysql_password, tvb,
+ offset, strlen, FALSE );
+ }
+ offset +=strlen;
+
+
+ return offset;
+}
+
+
+static int
+mysql_dissect_server_greeting(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree)
+{
+ gint protocol;
+ gint strlen;
+ gint32 thread_id;
+ gint16 server_caps;
+ gint charset;
+ gint16 status;
+
+ proto_item *tf;
+ proto_item *greeting_tree=NULL;
+ proto_item *cap_tree;
+
+ protocol= tvb_get_guint8(tvb, offset);
+
+ if(tree) {
+ tf = proto_tree_add_text(tree,tvb,offset,-1,"Server Greeting");
+ greeting_tree = proto_item_add_subtree(tf ,ett_server_greeting);
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Protocol : %d",protocol) ;
+ }
+ if (tree) {
+ proto_tree_add_uint(greeting_tree, hf_mysql_protocol, tvb,
+ offset, 1, protocol);
+ }
+ offset +=1;
+ /* version string */
+
+ strlen = tvb_strsize(tvb,offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " ,version: %s",
+ tvb_get_ptr(tvb,offset,strlen));
+ }
+ if (tree) {
+ proto_tree_add_item(greeting_tree, hf_mysql_version, tvb,
+ offset, strlen, FALSE );
+ }
+ offset +=strlen;
+
+ /* 4 bytes little endian thread_id */
+ thread_id = tvb_get_letohl(tvb, offset);
+ if(tree) {
+ proto_tree_add_uint(greeting_tree, hf_mysql_thread_id, tvb,
+ offset, 4, thread_id);
+ }
+ offset +=4;
+ /* salt string */
+ strlen = tvb_strsize(tvb,offset);
+ if (tree) {
+ proto_tree_add_item(greeting_tree, hf_mysql_salt, tvb,
+ offset, strlen, FALSE );
+ }
+ offset +=strlen;
+ /* 2 bytes CAPS */
+ server_caps= tvb_get_letohs(tvb, offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Caps: 0x%x",server_caps) ;
+ }
+ if(tree) {
+ tf = proto_tree_add_uint_format(greeting_tree, hf_mysql_caps, tvb, offset , 1, server_caps, "Caps: 0x%04x ", server_caps );
+ cap_tree = proto_item_add_subtree(tf, ett_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_long_password, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_found_rows, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_long_flag, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_connect_with_db, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_no_schema, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_compress, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_odbc, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_local_files, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_ignore_space, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_change_user, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_interactive, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_ssl, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_ignore_sigpipe, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_transactions, tvb, offset, 2, server_caps);
+ }
+ offset+=2;
+ /* 1 byte charset */
+ charset = tvb_get_guint8(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint_format(greeting_tree, hf_mysql_charset, tvb,
+ offset, 1, charset, "Charset: %s (%u)",
+ val_to_str(charset, mysql_charset_vals, "Unknown (%u)"), charset);
+ }
+ offset +=1;
+ /* 2 byte status */
+ status = tvb_get_letohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint_format(greeting_tree, hf_mysql_status, tvb,
+ offset, 2, status, "Status: %s (%u)",
+ val_to_str(status, mysql_status_vals, "Unknown (%u)"), status);
+ }
+ offset +=2;
+ /* other unused */
+ strlen = tvb_length_remaining(tvb,offset);
+
+ if (tree) {
+ proto_tree_add_item(greeting_tree, hf_mysql_unused, tvb,
+ offset, strlen, FALSE );
+ }
+ offset +=strlen;
+
+ return offset;
+}
+
+void
+proto_register_mysql(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_mysql_packet_length,
+ { "Packet Length", "mysql.packet_length",
+ FT_UINT24, BASE_DEC, NULL, 0x0,
+ "MySQL packet length", HFILL }},
+
+ { &hf_mysql_packet_number,
+ { "Packet Number", "mysql.packet_number",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "MySQL Packet Number", HFILL }},
+
+ { &hf_mysql_opcode,
+ { "Command", "mysql.opcode",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "MySQL OPCODE", HFILL }},
+
+ { &hf_mysql_response_code,
+ { "Response Code", "mysql.response_code",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "MySQL Respone Code", HFILL }},
+
+ { &hf_mysql_error_code,
+ { "Error Code", "mysql.error_code",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "MySQL Error CODE", HFILL }},
+
+ { &hf_mysql_protocol,
+ { "Protocol", "mysql.protocol",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "MySQL Protocol", HFILL }},
+
+ { &hf_mysql_version,
+ { "Version", "mysql.version",
+ FT_STRINGZ, BASE_DEC, NULL, 0x0,
+ "MySQL Version", HFILL }},
+
+ { &hf_mysql_caps,
+ { "Caps", "mysql.caps",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "MySQL Capabilities", HFILL }},
+
+ { &hf_mysql_cap_long_password,
+ { "Long Password","mysql.caps.lp",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_LP,
+ "", HFILL }},
+
+ { &hf_mysql_cap_found_rows,
+ { "Found Rows","mysql.caps.fr",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_FR,
+ "", HFILL }},
+
+
+ { &hf_mysql_cap_long_flag,
+ { "Long Flag","mysql.caps.lf",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_LF,
+ "", HFILL }},
+
+ { &hf_mysql_cap_connect_with_db,
+ { "Connect With Database","mysql.caps.cd",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_CD,
+ "", HFILL }},
+
+
+ { &hf_mysql_cap_no_schema,
+ { "Dont Allow database.table.column","mysql.caps.ns",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_NS,
+ "", HFILL }},
+
+ { &hf_mysql_cap_compress,
+ { "Can use compression protocol","mysql.caps.CP",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_CP,
+ "", HFILL }},
+
+ { &hf_mysql_cap_odbc,
+ { "ODBC Client","mysql.caps.ob",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_OB,
+ "", HFILL }},
+
+
+ { &hf_mysql_cap_local_files,
+ { "Can Use LOAD DATA LOCAL","mysql.caps.li",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_LI,
+ "", HFILL }},
+
+ { &hf_mysql_cap_ignore_space,
+ { "Ignore Spaces before (","mysql.caps.is",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_IS,
+ "", HFILL }},
+
+
+ { &hf_mysql_cap_change_user,
+ { "Support the mysql_change_user()","mysql.caps.cu",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_CU,
+ "", HFILL }},
+
+
+ { &hf_mysql_cap_interactive,
+ { "an Interactive Client","mysql.caps.ia",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_IA,
+ "", HFILL }},
+
+
+ { &hf_mysql_cap_ssl,
+ { "Switch to SSL after handshake","mysql.caps.sl",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_SL,
+ "", HFILL }},
+
+ { &hf_mysql_cap_ignore_sigpipe,
+ { "Ignore sigpipes","mysql.caps.ii",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_II,
+ "", HFILL }},
+
+ { &hf_mysql_cap_transactions,
+ { "Client knows about transactions","mysql.caps.ta",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_TA,
+ "", HFILL }},
+
+ { &hf_mysql_max_packet,
+ { "MAX Packet", "mysql.max_packet",
+ FT_UINT24, BASE_DEC, NULL, 0x0,
+ "MySQL Max packet", HFILL }},
+
+ { &hf_mysql_user,
+ { "Username", "mysql.user",
+ FT_STRINGZ, BASE_DEC, NULL, 0x0,
+ "Login Username", HFILL }},
+
+ { &hf_mysql_password,
+ { "Password", "mysql.password",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "Login Password", HFILL }},
+
+ { &hf_mysql_salt,
+ { "Salt", "mysql.salt",
+ FT_STRINGZ, BASE_DEC, NULL, 0x0,
+ "Salt", HFILL }},
+
+ { &hf_mysql_thread_id,
+ { "Thread ID", "mysql.thread_id",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "MySQL Thread ID", HFILL }},
+
+ { &hf_mysql_charset,
+ { "Charset", "mysql.charset",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "MySQL Charset", HFILL }},
+
+ { &hf_mysql_status,
+ { "Status", "mysql.status",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "MySQL Status", HFILL }},
+
+ { &hf_mysql_unused,
+ { "Unused", "mysql.unused",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "Unused", HFILL }},
+
+ { &hf_mysql_parameter,
+ { "Parameter", "mysql.parameter",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "Parameter", HFILL }},
+ { &hf_mysql_payload,
+ { "Payload", "mysql.payload",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "MySQL Payload", HFILL }},
+#if 0
+ { &hf_mysql_destination_file,
+ { "DESTINATION File", "mysql.destination_file",
+ FT_STRINGZ, BASE_DEC, NULL, 0x0,
+ "MySQL source file name", HFILL }},
+
+ { &hf_mysql_blocknum,
+ { "Block", "mysql.block",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Block number", HFILL }},
+
+ { &hf_mysql_error_code,
+ { "Error code", "mysql.error.code",
+ FT_UINT16, BASE_DEC, VALS(mysql_error_code_vals), 0x0,
+ "Error code in case of MySQL error message", HFILL }},
+
+ { &hf_mysql_error_string,
+ { "Error message", "mysql.error.message",
+ FT_STRINGZ, BASE_DEC, NULL, 0x0,
+ "Error string in case of MySQL error message", HFILL }},
+#endif
+ };
+ static gint *ett[] = {
+ &ett_mysql,
+ &ett_server_greeting,
+ &ett_caps,
+ &ett_request,
+ };
+ module_t *mysql_module;
+
+ proto_mysql = proto_register_protocol("MySQL Protocol",
+ "MySQL", "mysql");
+ proto_register_field_array(proto_mysql, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ mysql_module = prefs_register_protocol(proto_mysql, NULL);
+ prefs_register_bool_preference(mysql_module, "desegment_buffers",
+ "Desegment all MySQL buffers spanning multiple TCP segments",
+ "Whether the MySQL dissector should desegment all MySQL buffers spanning multiple TCP segments",
+ &mysql_desegment);
+}
+
+void
+proto_reg_handoff_mysql(void)
+{
+ dissector_handle_t mysql_handle;
+
+ mysql_handle = create_dissector_handle(dissect_mysql, proto_mysql);
+
+ dissector_add("tcp.port", TCP_PORT_MySQL, mysql_handle);
+}